Caffe2 - C++ API
A deep learning, cross platform ML framework
hard_sigmoid_op.cc
1 #include "caffe2/operators/hard_sigmoid_op.h"
2 
3 #include <algorithm>
4 #include <functional>
5 #include <string>
6 
7 #include "caffe2/utils/eigen_utils.h"
8 
9 namespace caffe2 {
10 
11 template <>
12 template <typename T>
13 bool HardSigmoidFunctor<CPUContext>::
14 operator()(const int N, const T* X, T* Y, CPUContext* /* context */) const {
15  EigenVectorArrayMap<T>(Y, N) =
16  (ConstEigenVectorArrayMap<T>(X, N) * T(alpha) + T(beta))
17  .cwiseMin(T(1))
18  .cwiseMax(T(0));
19  return true;
20 }
21 
22 template <>
23 template <typename T>
24 bool HardSigmoidGradientFunctor<CPUContext>::Forward(
25  const std::vector<int>& Y_dims,
26  const std::vector<int>& /* dY_dims */,
27  const T* Y,
28  const T* dY,
29  T* dX,
30  CPUContext* /* context */) const {
31  const int size = std::accumulate(
32  Y_dims.cbegin(), Y_dims.cend(), 1, std::multiplies<int>());
33  ConstEigenVectorArrayMap<T> Y_arr(Y, size);
34  EigenVectorArrayMap<T>(dX, size) =
35  (Y_arr > T(0) && Y_arr < T(1))
36  .select(ConstEigenVectorArrayMap<T>(dY, size) * alpha, T(0));
37  return true;
38 }
39 
40 namespace {
41 
42 OpSchema::Cost CostInferenceForHardSigmoid(
43  const OperatorDef& def,
44  const vector<TensorShape>& in) {
45  struct OpSchema::Cost cost = PointwiseCostInference<4>(def, in);
46  cost.params_bytes = 0;
47  return cost;
48 }
49 
50 } // namespace
51 
52 REGISTER_CPU_OPERATOR(
53  HardSigmoid,
54  UnaryElementwiseWithArgsOp<
55  TensorTypes<float>,
56  CPUContext,
57  HardSigmoidFunctor<CPUContext>>);
58 REGISTER_CPU_OPERATOR(
59  HardSigmoidGradient,
60  BinaryElementwiseWithArgsOp<
61  TensorTypes<float>,
62  CPUContext,
63  HardSigmoidGradientFunctor<CPUContext>>);
64 
65 // Input: X, output: Y
66 OPERATOR_SCHEMA(HardSigmoid)
67  .NumInputs(1)
68  .NumOutputs(1)
69  .AllowInplace({{0, 0}})
70  .CostInferenceFunction(CostInferenceForHardSigmoid)
71  .IdenticalTypeAndShape()
72  .SetDoc(R"DOC(
73 Applies hard sigmoid operation to the input data element-wise.
74 The HardSigmoid operation takes one input $X$, produces one output $Y$, and is defined as:
75 
76 $$Y = max(0,min(1,x * alpha + beta))$$
77 
78 Github Links:
79 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/hard_sigmoid_op.h
80 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/hard_sigmoid_op.cc
81 
82 <details>
83 
84 <summary> <b>Example</b> </summary>
85 
86 **Code**
87 
88 ```
89 
90 workspace.ResetWorkspace()
91 
92 op = core.CreateOperator(
93  "HardSigmoid",
94  ["X"],
95  ["Y"],
96  alpha = 0.2,
97  beta = 0.5,
98 )
99 
100 workspace.FeedBlob("X", np.random.randn(5).astype(np.float32))
101 print("input:", workspace.FetchBlob("X"))
102 workspace.RunOperatorOnce(op)
103 print("sigmoid:", workspace.FetchBlob("Y"))
104 
105 ```
106 
107 **Result**
108 
109 ```
110 
111 input: [ 1.5744036 0.31632107 1.7842269 1.4450722 -2.1726978 ]
112 hard_sigmoid: [ 0.81488073, 0.56326419, 0.85684538, 0.78901446, 0.06546044]
113 
114 ```
115 
116 </details>
117 
118 
119 )DOC")
120  .Arg("alpha", "float: the slope of the function. Defaults to 0.2")
121  .Arg("beta", "float: the bias value of the function. Defaults to 0.5")
122  .Input(0, "X", "1D input tensor")
123  .Output(0, "Y", "1D output tensor with same shape as input")
124  .InheritOnnxSchema();
125 
126 // Input: Y, dY, output: dX
127 OPERATOR_SCHEMA(HardSigmoidGradient)
128  .NumInputs(2)
129  .NumOutputs(1)
130  .AllowInplace({{1, 0}})
131  .SetDoc(R"DOC(
132 HardSigmoidGradient takes both Y and dY as well as an argument alpha and uses
133 this to update dX according to the chain rule and derivatives of the hard
134 sigmoid function.
135 )DOC");
136 
137 namespace {
138 
139 class GetHardSigmoidGradient : public GradientMakerBase {
140  using GradientMakerBase::GradientMakerBase;
141  std::vector<OperatorDef> GetGradientDefs() override {
142  return SingleGradientDef(
143  def_.type() + "Gradient",
144  "",
145  std::vector<std::string>{O(0), GO(0)},
146  std::vector<std::string>{GI(0)});
147  }
148 };
149 
150 } // namespace
151 
152 REGISTER_GRADIENT(HardSigmoid, GetHardSigmoidGradient);
153 
154 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13