Caffe2 - C++ API
A deep learning, cross platform ML framework
spatial_batch_norm_op.cc
1 #include "caffe2/operators/spatial_batch_norm_op.h"
2 
3 #include <array>
4 
5 #include "caffe2/utils/eigen_utils.h"
6 
7 namespace caffe2 {
8 
9 namespace {
10 
11 OpSchema::Cost CostInferenceForSpatialBN(
12  const OperatorDef& def,
13  const vector<TensorShape>& in) {
14  struct OpSchema::Cost cost = PointwiseCostInference<4>(def, in);
15  ArgumentHelper helper(def);
16  auto order =
17  StringToStorageOrder(helper.GetSingleArgument<string>("order", "NCHW"));
18  const TensorShape X = in[0];
19  const int C =
20  (order == StorageOrder::NCHW ? X.dims(1) : X.dims(X.dims_size() - 1));
21  cost.params_bytes = 2 * C * sizeof(float);
22  return cost;
23 }
24 
25 } // namespace
26 
27 REGISTER_CPU_OPERATOR(SpatialBN, SpatialBNOp<CPUContext>);
28 
29 OPERATOR_SCHEMA(SpatialBN)
30  .NumInputs({5, 7})
31  .NumOutputs({1, 5})
32  .AllowInplace({{0, 0}, {5, 3}, {6, 4}})
33  .EnforceInplace({{3, 1}, {4, 2}})
34  .CostInferenceFunction(CostInferenceForSpatialBN)
35  .TensorInferenceFunction([](const OperatorDef& def,
36  const vector<TensorShape>& in) {
37  ArgumentHelper helper(def);
38  bool is_test = helper.GetSingleArgument<int>(OpSchema::Arg_IsTest, 0);
39 
40  if (!is_test) {
41  vector<TensorShape> out;
42  StorageOrder order = StringToStorageOrder(
43  helper.GetSingleArgument<string>("order", "NCHW"));
44  const TensorShape& X = in[0];
45  const int C =
46  (order == StorageOrder::NCHW ? X.dims(1)
47  : X.dims(X.dims_size() - 1));
48 
49  out.push_back(in[0]);
50  TensorShape meanvar_tp =
51  CreateTensorShape(vector<int>{C}, TensorProto::FLOAT);
52  out.push_back(meanvar_tp); // RUNNING_MEAN
53  out.push_back(meanvar_tp); // RUNNING_MEAN
54  out.push_back(meanvar_tp); // SAVED_MEAN
55  out.push_back(meanvar_tp); // SAVED_VAR
56  return out;
57  } else {
58  return vector<TensorShape>{in[0]};
59  }
60  })
61  .SetDoc(R"DOC(
62 Applies spatial batch normalization to the input tensor as described in the original paper, [Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift](https://arxiv.org/abs/1502.03167). Be aware, this operator has two different output sets, depending on the value of *is_test*. According to the paper, the primary operation of spatial batch normalization is:
63 
64 $$Y = \frac{X - \mu_x}{\sqrt{\sigma^2_{x} + \epsilon}}*\gamma + b$$
65 
66 In the equation, $\mu_x$ is the *mean*, $X$ is the input data, $\sigma^2_{x}$ is the *var*, $\epsilon$ is *epsilon*, $\gamma$ is the *scale*, $b$ is the *bias*, and $Y$ is the output data. The *momentum* arg also affects this calculation in the computation of the running mean and variance. The influence of *momentum* is as follows:
67 
68 $$running\_mean = running\_mean * momentum + mean * (1 - momentum)$$
69 
70 $$running\_var = running\_var * momentum + var * (1 - momentum)$$
71 
72 Output when is_test = 0 (train mode): *Y, mean, var, saved_mean, saved_var*
73 
74 Output when is_test = 1 (test mode): *Y*
75 
76 Github Links:
77 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/spatial_batch_norm_op.cc
78 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/spatial_batch_norm_op.h
79 
80 )DOC")
81  .ArgIsTest(
82  "*(type: int; default: 0)* If set to nonzero, run spatial batch normalization in test mode.")
83  .Arg(
84  "epsilon",
85  "*(type: float; default: 1e-5)* The epsilon value to use to avoid division by zero.")
86  .Arg(
87  "order",
88  "*(type: string; default: \"NCHW\")* Specifies the order of the input data blob, where $N$ is batch size, $C$ is number of channels, $H$ is spatial height, and $W$ is spatial width. The only other valid option is \"NHWC\".")
89  .Arg(
90  "momentum",
91  "*(type: float; default: 0.9)* Factor used in computing the running mean and variance. e.g., running_mean = running_mean x momentum + mean x (1 - momentum)")
92  .Arg(
93  "num_batches",
94  "*(type: int; default: 1)* Specifies the number of batches to apply normalization on. Requires specifying the optional sums and sumsq inputs that provide statistics across multiple batches from which mean and variance can be determined.")
95  .Input(
96  0,
97  "X",
98  "The input 4-dimensional tensor of shape $NCHW$ or $NHWC$ depending on the order parameter.")
99  .Input(
100  1,
101  "scale",
102  "The scale as a 1-dimensional tensor of size $C$ to be applied to the output.")
103  .Input(
104  2,
105  "bias",
106  "The bias as a 1-dimensional tensor of size $C$ to be applied to the output.")
107  .Input(
108  3,
109  "mean",
110  "The running mean (training) or the estimated mean (testing) as a 1-dimensional tensor of size $C$.")
111  .Input(
112  4,
113  "var",
114  "The running variance (training) or the estimated variance (testing) as a 1-dimensional tensor of size $C$.")
115  .Input(
116  5,
117  "sums",
118  "*(optional)* Per-channel sums of elements to be used to determine the mean and variance for this batch.")
119  .Input(
120  6,
121  "sumsq",
122  "*(optional)* Per-channel sum of elements squared per channel to be used to determine the variance for this batch.")
123 
124  .Output(0, "Y", "The output 4-dimensional tensor of the same shape as $X$.")
125  .Output(
126  1,
127  "mean",
128  "The running mean after the spatial BN operator. Must be in-place with the input *mean*. Should not be used for testing.")
129  .Output(
130  2,
131  "var",
132  "The running variance after the spatial BN operator. Must be in-place with the input *var*. Should not be used for testing.")
133  .Output(
134  3,
135  "saved_mean",
136  "Saved mean used during training to speed up gradient computation. Should not be used for testing.")
137  .Output(
138  4,
139  "saved_var",
140  "Saved variance used during training to speed up gradient computation. Should not be used for testing.")
141  .InheritOnnxSchema("BatchNormalization");
142 
143 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13
Definition: static.cpp:64