| #include "caffe2/operators/softmax_utils.h" |
| |
| #include "caffe2/core/context.h" |
| #include "caffe2/utils/eigen_utils.h" |
| #include "caffe2/utils/math.h" |
| |
| namespace caffe2 { |
| namespace softmax_utils { |
| |
| #define CAFFE2_SPECIALIZED_SOFTMAX_CPU(T) \ |
| template <> \ |
| void SoftmaxCPU<T>( \ |
| const int N, \ |
| const int D, \ |
| const bool logarithmic, \ |
| const T* X, \ |
| T* Y, \ |
| T* scratch, \ |
| CPUContext* context) { \ |
| ConstEigenArrayMap<T> X_arr(X, D, N); \ |
| EigenArrayMap<T> Y_arr(Y, D, N); \ |
| EigenVectorArrayMap<T> scratch_arr(scratch, N); \ |
| scratch_arr = X_arr.colwise().maxCoeff().transpose(); \ |
| Y_arr = X_arr.rowwise() - scratch_arr.transpose(); \ |
| math::Exp<T, CPUContext>(N * D, Y, Y, context); \ |
| if (logarithmic) { \ |
| scratch_arr += Y_arr.colwise().sum().log().transpose(); \ |
| Y_arr = X_arr.rowwise() - scratch_arr.transpose(); \ |
| } else { \ |
| scratch_arr = Y_arr.colwise().sum().inverse().transpose(); \ |
| Y_arr = Y_arr.rowwise() * scratch_arr.transpose(); \ |
| } \ |
| } |
| CAFFE2_SPECIALIZED_SOFTMAX_CPU(float) |
| #undef CAFFE2_SPECIALIZED_SOFTMAX_CPU |
| |
| } // namespace softmax_utils |
| } // namespace caffe2 |