1 #include "caffe2/operators/reduce_ops.h" 7 #include "caffe2/utils/math.h" 14 void ComputeReduceMinMaxGradient(
15 const std::vector<int>& dY_dims,
16 const std::vector<int>& dX_dims,
21 const int dX_size = std::accumulate(
22 dX_dims.cbegin(), dX_dims.cend(), 1, std::multiplies<int>());
23 const int ndim = dX_dims.size();
24 std::vector<int> index(ndim, 0);
25 for (
int dX_index = 0; dX_index < dX_size; ++dX_index) {
27 math::utils::GetIndexFromDims(ndim, dY_dims.data(), index.data());
29 Y_data[dY_index] == X_data[dX_index] ? dY_data[dY_index] :
T(0);
30 math::utils::IncreaseIndexInDims(ndim, dX_dims.data(), index.data());
38 bool MinReducer<CPUContext>::Backward(
39 const std::vector<int>& dY_dims,
40 const std::vector<int>& dX_dims,
46 ComputeReduceMinMaxGradient(
47 dY_dims, dX_dims, dY_data, X_data, Y_data, dX_data);
53 bool MaxReducer<CPUContext>::Backward(
54 const std::vector<int>& dY_dims,
55 const std::vector<int>& dX_dims,
61 ComputeReduceMinMaxGradient(
62 dY_dims, dX_dims, dY_data, X_data, Y_data, dX_data);
66 REGISTER_CPU_OPERATOR(
69 TensorTypes<std::int32_t, std::int64_t, float, double>,
71 MinReducer<CPUContext>>);
72 REGISTER_CPU_OPERATOR(
75 TensorTypes<std::int32_t, std::int64_t, float, double>,
77 MinReducer<CPUContext>>);
79 OPERATOR_SCHEMA(ReduceMin)
83 Computes the min of the input tensor's element along the provided axes. 84 The resulted tensor has the same rank as the input if keepdims equal True. 85 If keepdims equal false, then the resulted tensor have the reduced dimension 88 .Arg("axes",
"A list of integers, along which to reduce.")
91 "Keep the reduced dimension(s) or not, default True keeps the reduced " 93 .Input(0,
"data",
"An input tensor.")
94 .Output(0,
"reduced",
"Reduced output tensor.");
96 OPERATOR_SCHEMA(ReduceMinGradient).NumInputs(3).NumOutputs(1);
98 REGISTER_CPU_OPERATOR(
101 TensorTypes<std::int32_t, std::int64_t, float, double>,
103 MaxReducer<CPUContext>>);
104 REGISTER_CPU_OPERATOR(
107 TensorTypes<std::int32_t, std::int64_t, float, double>,
109 MaxReducer<CPUContext>>);
111 OPERATOR_SCHEMA(ReduceMax)
115 Computes the max of the input tensor's element along the provided axes. 116 The resulted tensor has the same rank as the input if keepdims equal True. 117 If keepdims equal false, then the resulted tensor have the reduced dimension 120 .Arg("axes",
"A list of integers, along which to reduce.")
123 "Keep the reduced dimension(s) or not, default True keeps the reduced " 125 .Input(0,
"data",
"An input tensor.")
126 .Output(0,
"reduced",
"Reduced output tensor.");
128 OPERATOR_SCHEMA(ReduceMaxGradient).NumInputs(3).NumOutputs(1);
130 REGISTER_CPU_OPERATOR(
133 TensorTypes<std::int32_t, std::int64_t, float, double>,
135 SumReducer<CPUContext>>);
136 REGISTER_CPU_OPERATOR(
139 TensorTypes<std::int32_t, std::int64_t, float, double>,
141 SumReducer<CPUContext>>);
143 OPERATOR_SCHEMA(ReduceSum)
147 Computes the **sum** of the input tensor's elements along the provided `axes`. The resulting tensor has the same rank as the input if the `keepdims` argument equals 1 (default). If `keepdims` is set to 0, then the `axes` dimensions are pruned. 150 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_ops.cc 154 <summary> <b>Example</b> </summary> 160 workspace.ResetWorkspace() 162 op = core.CreateOperator( 170 workspace.FeedBlob("X", np.random.randint(10, size=(1,2,5,5)).astype(np.float32)) 171 print("X:", workspace.FetchBlob("X")) 172 workspace.RunOperatorOnce(op) 173 print("Y:", workspace.FetchBlob("Y")) 194 [[13. 12. 13. 16. 12.] 205 .Arg("axes",
"(*Tuple(int)*): list of axes to reduce")
208 "(*int*): set to 1 to keep the reduced dimension(s) (default=1), else set to 0 to not keep the reduced dimension(s)")
209 .Input(0,
"X",
"(*Tensor`<float>`*): input tensor")
210 .Output(0,
"Y",
"(*Tensor`<float>`*): reduced tensor");
212 OPERATOR_SCHEMA(ReduceSumGradient).NumInputs(3).NumOutputs(1);
214 REGISTER_CPU_OPERATOR(
216 ReduceOp<TensorTypes<float>, CPUContext, MeanReducer<CPUContext>>);
217 REGISTER_CPU_OPERATOR(
219 ReduceGradientOp<TensorTypes<float>, CPUContext, MeanReducer<CPUContext>>);
221 OPERATOR_SCHEMA(ReduceMean)
225 Computes the **mean** of the input tensor's elements along the provided `axes`. The resulting tensor has the same rank as the input if the `keepdims` argument equals 1 (default). If `keepdims` is set to 0, then the `axes` dimensions are pruned. 228 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_ops.cc 232 <summary> <b>Example</b> </summary> 238 workspace.ResetWorkspace() 240 op = core.CreateOperator( 248 workspace.FeedBlob("X", np.random.randint(10, size=(1,2,5,5)).astype(np.float32)) 249 print("X:", workspace.FetchBlob("X")) 250 workspace.RunOperatorOnce(op) 251 print("Y:", workspace.FetchBlob("Y")) 284 .Arg("axes",
"(*Tuple(int)*): list of axes to reduce")
287 "(*int*): set to 1 to keep the reduced dimension(s) (default=1), else set to 0 to not keep the reduced dimension(s)")
288 .Input(0,
"X",
"(*Tensor`<float>`*): input tensor")
289 .Output(0,
"Y",
"(*Tensor`<float>`*): reduced tensor");
291 OPERATOR_SCHEMA(ReduceMeanGradient).NumInputs(3).NumOutputs(1);
294 template <
typename T>
295 bool L1Reducer<CPUContext>::Backward(
296 const std::vector<int>& dY_dims,
297 const std::vector<int>& dX_dims,
302 CPUContext* )
const {
303 const float kEps = 1e-12f;
304 const int dX_size = std::accumulate(
305 dX_dims.cbegin(), dX_dims.cend(), 1, std::multiplies<int>());
306 const int ndim = dX_dims.size();
307 std::vector<int> index(ndim, 0);
308 for (
int dX_index = 0; dX_index < dX_size; ++dX_index) {
310 math::utils::GetIndexFromDims(ndim, dY_dims.data(), index.data());
311 float temp = X_data[dX_index];
313 dX_data[dX_index] = -dY_data[dY_index];
314 }
else if (temp > kEps) {
315 dX_data[dX_index] = dY_data[dY_index];
317 dX_data[dX_index] =
T(0);
319 math::utils::IncreaseIndexInDims(ndim, dX_dims.data(), index.data());
325 template <
typename T>
326 bool L2Reducer<CPUContext>::Backward(
327 const std::vector<int>& dY_dims,
328 const std::vector<int>& dX_dims,
333 CPUContext* )
const {
334 const float kEps = 1e-12f;
335 const int dX_size = std::accumulate(
336 dX_dims.cbegin(), dX_dims.cend(), 1, std::multiplies<int>());
337 const int ndim = dX_dims.size();
338 std::vector<int> index(ndim, 0);
339 for (
int dX_index = 0; dX_index < dX_size; ++dX_index) {
341 math::utils::GetIndexFromDims(ndim, dY_dims.data(), index.data());
342 T norm = Y_data[dY_index];
344 dX_data[dX_index] = dY_data[dY_index];
346 dX_data[dX_index] = dY_data[dY_index] * X_data[dX_index] / norm;
348 math::utils::IncreaseIndexInDims(ndim, dX_dims.data(), index.data());
353 REGISTER_CPU_OPERATOR(
355 ReduceOp<TensorTypes<float>, CPUContext, L1Reducer<CPUContext>>);
356 REGISTER_CPU_OPERATOR(
358 ReduceGradientOp<TensorTypes<float>, CPUContext, L1Reducer<CPUContext>>);
360 OPERATOR_SCHEMA(ReduceL1)
364 Computes the **L1 norm** of the input tensor's elements along the provided `axes`. The resulting tensor has the same rank as the input if the `keepdims` argument equals 1 (default). If `keepdims` is set to 0, then the `axes` dimensions are pruned. 367 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_ops.cc 371 <summary> <b>Example</b> </summary> 377 workspace.ResetWorkspace() 379 op = core.CreateOperator( 387 workspace.FeedBlob("X", np.random.randint(10, size=(1,2,5,5)).astype(np.float32)) 388 print("X:", workspace.FetchBlob("X")) 389 workspace.RunOperatorOnce(op) 390 print("Y:", workspace.FetchBlob("Y")) 412 [[ 7. 15. 7. 11. 12.] 424 .Arg("axes",
"(*Tuple(int)*): list of axes to reduce")
427 "(*int*): set to 1 to keep the reduced dimension(s) (default=1), else set to 0 to not keep the reduced dimension(s)")
428 .Input(0,
"X",
"(*Tensor`<float>`*): input tensor")
429 .Output(0,
"Y",
"(*Tensor`<float>`*): reduced tensor");
431 OPERATOR_SCHEMA(ReduceL1Gradient).NumInputs(3).NumOutputs(1);
433 REGISTER_CPU_OPERATOR(
435 ReduceOp<TensorTypes<float>, CPUContext, L2Reducer<CPUContext>>);
436 REGISTER_CPU_OPERATOR(
438 ReduceGradientOp<TensorTypes<float>, CPUContext, L2Reducer<CPUContext>>);
440 OPERATOR_SCHEMA(ReduceL2)
444 Computes the **L2 norm** of the input tensor's elements along the provided `axes`. The resulting tensor has the same rank as the input if the `keepdims` argument equals 1 (default). If `keepdims` is set to 0, then the `axes` dimensions are pruned. 447 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/reduce_ops.cc 451 <summary> <b>Example</b> </summary> 457 workspace.ResetWorkspace() 459 op = core.CreateOperator( 467 workspace.FeedBlob("X", np.random.randint(10, size=(1,2,5,5)).astype(np.float32)) 468 print("X:", workspace.FetchBlob("X")) 469 workspace.RunOperatorOnce(op) 470 print("Y:", workspace.FetchBlob("Y")) 492 [[ 8.24621105 4. 6.3245554 5.38516474 8.06225777] 493 [ 1.41421354 3.1622777 8. 4. 8. ] 494 [ 5.09901953 9.48683262 6. 7.6157732 7.28010988] 495 [ 6.08276272 11.40175438 8.54400349 8.06225777 6.70820379] 496 [ 8.48528099 8.06225777 10.29563046 10.63014603 7.6157732 ]] 504 .Arg("axes",
"(*Tuple(int)*): list of axes to reduce")
507 "(*int*): set to 1 to keep the reduced dimension(s) (default=1), else set to 0 to not keep the reduced dimension(s)")
508 .Input(0,
"X",
"(*Tensor`<float>`*): input tensor")
509 .Output(0,
"Y",
"(*Tensor`<float>`*): reduced tensor")
510 .InheritOnnxSchema(
"ReduceMean");
512 OPERATOR_SCHEMA(ReduceL2Gradient).NumInputs(3).NumOutputs(1);
516 class GetReduceGradient final :
public GradientMakerBase {
517 using GradientMakerBase::GradientMakerBase;
519 std::vector<OperatorDef> GetGradientDefs()
override {
520 return SingleGradientDef(
521 def_.type() +
"Gradient",
523 std::vector<string>{GO(0), I(0), O(0)},
524 std::vector<string>{GI(0)});
530 REGISTER_GRADIENT(ReduceMin, GetReduceGradient);
531 REGISTER_GRADIENT(ReduceMax, GetReduceGradient);
532 REGISTER_GRADIENT(ReduceSum, GetReduceGradient);
533 REGISTER_GRADIENT(ReduceMean, GetReduceGradient);
534 REGISTER_GRADIENT(ReduceL1, GetReduceGradient);
535 REGISTER_GRADIENT(ReduceL2, GetReduceGradient);
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...