Caffe2 - C++ API
A deep learning, cross platform ML framework
elu_op.cc
1 #include "caffe2/operators/elu_op.h"
2 
3 #include "caffe2/utils/math.h"
4 
5 namespace caffe2 {
6 
7 template <>
8 bool EluOp<float, CPUContext>::RunOnDevice() {
9  auto& X = Input(0);
10  auto* Y = Output(0);
11  // Otherwise inplace gradient and Elu dosen't make sense.
12  CAFFE_ENFORCE_GE(alpha_, 0);
13  Y->ResizeLike(X);
14  const auto* Xdata = X.template data<float>();
15  auto* Ydata = Y->template mutable_data<float>();
16  ConstEigenVectorArrayMap<float> Xvec(Xdata, X.size());
17  EigenVectorArrayMap<float> Yvec(Ydata, Y->size());
18  Yvec = Xvec.cwiseMax(0.f) + (alpha_ * (Xvec.exp() - 1.0f)).cwiseMin(0.f);
19  return true;
20 }
21 
22 template <>
23 bool EluGradientOp<float, CPUContext>::RunOnDevice() {
24  auto& Y = Input(0);
25  auto& dY = Input(1);
26  auto* dX = Output(0);
27  DCHECK_GT(Y.size(), 0);
28  DCHECK_EQ(dY.size(), Y.size());
29  dX->ResizeLike(Y);
30 
31  const float* Ydata = Y.data<float>();
32  const float* dYdata = dY.data<float>();
33  float* dXdata = dX->mutable_data<float>();
34  ConstEigenVectorArrayMap<float> Yvec(Ydata, Y.size());
35  ConstEigenVectorArrayMap<float> dYvec(dYdata, dY.size());
36  EigenVectorArrayMap<float> dXvec(dXdata, dX->size());
37  dXvec = (Yvec > 0).select(dYvec, dYvec * (Yvec + alpha_));
38  return true;
39 }
40 
41 REGISTER_CPU_OPERATOR(Elu, EluOp<float, CPUContext>);
42 REGISTER_CPU_OPERATOR(EluGradient, EluGradientOp<float, CPUContext>);
43 
44 // Input: X, output: Y
45 OPERATOR_SCHEMA(Elu)
46  .NumInputs(1)
47  .NumOutputs(1)
48  .AllowInplace({{0, 0}})
49  .IdenticalTypeAndShape()
50  .SetDoc(R"DOC(
51 
52 Elu takes one input data (Tensor<T>) and produces one output data
53 (Tensor<T>) where the function `f(x) = alpha * (exp(x) - 1.) for x <
54 0`, `f(x) = x for x >= 0`., is applied to the tensor elementwise.
55 
56 )DOC")
57  .Input(0, "X", "1D input tensor")
58  .Output(0, "Y", "1D input tensor")
59  .InheritOnnxSchema("Elu");
60 
61 // Input: Y, dY, output: dX
62 OPERATOR_SCHEMA(EluGradient)
63  .NumInputs(2)
64  .NumOutputs(1)
65  .AllowInplace({{1, 0}})
66  .SetDoc(R"DOC(
67 EluGradient takes both Y and dY and uses this to update dX according to the
68 chain rule and derivatives of the rectified linear function.
69 )DOC");
70 
71 class GetEluGradient : public GradientMakerBase {
72  using GradientMakerBase::GradientMakerBase;
73  vector<OperatorDef> GetGradientDefs() override {
74  return SingleGradientDef(
75  def_.type() + "Gradient",
76  "",
77  vector<string>{O(0), GO(0)},
78  vector<string>{GI(0)});
79  }
80 };
81 REGISTER_GRADIENT(Elu, GetEluGradient);
82 
83 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
static vector< OperatorDef > SingleGradientDef(const Args &...args)
a helper function to allow one to create one single operator def, which is usually the case for many ...