Caffe2 - C++ API
A deep learning, cross platform ML framework
thresholded_relu_op.cc
1 #include "caffe2/operators/thresholded_relu_op.h"
2 
3 #include "caffe2/utils/math.h"
4 
5 namespace caffe2 {
6 
7 template <>
8 bool ThresholdedReluOp<float, CPUContext>::RunOnDevice() {
9  auto& X = Input(0);
10  auto* Y = Output(0);
11  Y->ResizeLike(X);
12 
13  ConstEigenVectorArrayMap<float> Xvec(X.data<float>(), X.size());
14  EigenVectorArrayMap<float> Yvec(Y->mutable_data<float>(), Y->size());
15  Yvec = (Xvec > alpha_).select(Xvec, 0.f);
16  /* Naive implementation
17  const float* Xdata = X.data<float>();
18  float* Ydata = Y->mutable_data<float>();
19  for (int i = 0; i < X.size(); ++i) {
20  Xdata[i] -= alpha_;
21  Ydata[i] = std::max(Xdata[i], 0.0f);
22  }
23  */
24  return true;
25 }
26 
27 template <>
28 bool ThresholdedReluGradientOp<float, CPUContext>::RunOnDevice() {
29  auto& Y = Input(0);
30  auto& dY = Input(1);
31  auto* dX = Output(0);
32  CAFFE_ENFORCE_EQ(dY.size(), Y.size());
33  dX->ResizeLike(Y);
34 
35  const float* Ydata = Y.data<float>();
36  const float* dYdata = dY.data<float>();
37  float* dXdata = dX->mutable_data<float>();
38  EigenVectorArrayMap<float> dXvec(dXdata, dX->size());
39  ConstEigenVectorArrayMap<float> Yvec(Ydata, Y.size());
40  ConstEigenVectorArrayMap<float> dYvec(dYdata, dY.size());
41  dXvec = dYvec * Yvec.cwiseSign();
42  /* Non vectorized implementation
43  for (int i = 0; i < Y.size(); ++i) {
44  dXdata[i] = Ydata[i] > 0 ? dYdata[i] : 0;
45  }
46  */
47  return true;
48 }
49 
50 REGISTER_CPU_OPERATOR(ThresholdedRelu, ThresholdedReluOp<float, CPUContext>);
51 REGISTER_CPU_OPERATOR(
52  ThresholdedReluGradient,
53  ThresholdedReluGradientOp<float, CPUContext>);
54 
55 // Input: X, output: Y
56 OPERATOR_SCHEMA(ThresholdedRelu)
57  .NumInputs(1)
58  .NumOutputs(1)
59  .AllowInplace({{0, 0}})
60  .CostInferenceFunction(PointwiseCostInference<2>)
61  .IdenticalTypeAndShape()
62  .SetDoc(R"DOC(
63 ThresholdedRelu takes one input data (Tensor) and produces one output data
64 (Tensor) where the rectified linear function, y = x for x > alpha, y = 0
65 otherwise, is applied to the tensor elementwise.
66 )DOC")
67  .Arg("alpha", "(float) defaults to 1.0.")
68  .Input(0, "X", "1D input tensor")
69  .Output(0, "Y", "1D input tensor");
70 
71 // Input: Y, dY, output: dX
72 OPERATOR_SCHEMA(ThresholdedReluGradient)
73  .NumInputs(2)
74  .NumOutputs(1)
75  .AllowInplace({{1, 0}})
76  .SetDoc(R"DOC(
77 ThresholdedReluGradient takes both Y and dY and uses this to update dX
78 according to the chain rule and derivatives of the rectified linear function.
79 )DOC");
80 
81 class GetThresholdedReluGradient : public GradientMakerBase {
82  using GradientMakerBase::GradientMakerBase;
83  vector<OperatorDef> GetGradientDefs() override {
84  return SingleGradientDef(
85  def_.type() + "Gradient",
86  "",
87  vector<string>{O(0), GO(0)},
88  vector<string>{GI(0)});
89  }
90 };
91 REGISTER_GRADIENT(ThresholdedRelu, GetThresholdedReluGradient);
92 
93 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...