1 #include "caffe2/operators/pow_op.h" 2 #include "caffe2/utils/math.h" 9 #define EIGEN_POW(x, y) (x.pow(y)) 12 template <
int b_is_scalar,
typename T1,
typename T2,
typename R>
14 Run(
size_t n,
const T1* a,
const T2* b, T2 e, R* out,
CPUContext*) {
16 EigenVectorArrayMap<R>(out, n) =
17 EIGEN_POW((ConstEigenVectorArrayMap<T1>(a, n)), (e));
20 EigenVectorArrayMap<R>(out, n) =
21 EIGEN_POW((ConstEigenVectorArrayMap<T1>(a, n)), (b[0]));
23 EigenVectorArrayMap<R>(out, n) = EIGEN_POW(
24 (ConstEigenVectorArrayMap<T1>(a, n)),
25 (ConstEigenVectorArrayMap<T2>(b, n)));
29 template <
typename T1,
typename T2,
typename R>
30 void RunWithBroadcast(
37 EigenArrayMap<R>(out, n, pre) = EIGEN_POW(
38 (ConstEigenArrayMap<T1>(a, n, pre)),
39 (ConstEigenVectorArrayMap<T2>(b, n)).rowwise().replicate(pre));
48 template <
typename T1,
typename T2,
typename R>
49 void RunWithBroadcast2(
57 for (
int i = 0; i < pre; ++i) {
58 EigenArrayMap<R>(out + i * n * post, post, n) = EIGEN_POW(
59 (ConstEigenArrayMap<T1>(a + i * n * post, post, n)),
60 (Eigen::Map<const Eigen::Array<T2, 1, Eigen::Dynamic>>(b, n))
74 REGISTER_CPU_OPERATOR(
85 .Arg(
"exponent",
"The exponent of the power function.")
86 .AllowInplace({{0, 0}, {1, 0}})
87 .IdenticalTypeAndShapeOfInput(0)
89 Pow takes input data (Tensor<T>) and an argument exponent, which can be a 90 scalar or another tensor. It produces one output data (Tensor<T>), where 91 the function `f(x) = x^exponent` is applied to the data tensor elementwise. 93 .Input(0, "X",
"Input tensor of any shape")
94 .Input(1,
"exponent",
"The exponent of the power function.")
95 .Output(0,
"Y",
"Output tensor (same size as X)");
98 using GradientMakerBase::GradientMakerBase;
99 vector<OperatorDef> GetGradientDefs()
override {
101 if (arg_helper.HasArgument(
"exponent")) {
105 float exponent = arg_helper.GetSingleArgument<
float>(
"exponent", 0.0);
107 scale_arg.set_name(
"scale");
108 scale_arg.set_f(exponent);
110 pow_arg.set_name(
"exponent");
112 pow_arg.set_f(exponent - 1);
114 LOG(WARNING) <<
"In-place Pow gradient, possible loss of precision";
115 constexpr
float kEps = 1e-12f;
116 CAFFE_ENFORCE(std::fabs(exponent) > kEps);
117 pow_arg.set_f((exponent - 1) / exponent);
119 return vector<OperatorDef>{CreateOperatorDef(
122 std::vector<string>{I(0)},
123 std::vector<string>{GI(0)},
124 std::vector<Argument>{pow_arg}),
128 std::vector<string>{GI(0), GO(0)},
129 std::vector<string>{GI(0)}),
133 std::vector<string>{GI(0)},
134 std::vector<string>{GI(0)},
135 std::vector<Argument>{scale_arg})};
157 Def().input(0) != Def().output(0) &&
158 Def().input(1) != Def().output(0),
159 "Gradient computation cannot be carried out if Pow uses in-place " 161 ProtoDebugString(Def()));
162 vector<OperatorDef> grad_ops;
164 one_arg.set_name(
"value");
166 Argument broadcast, axis, axis_str, order;
167 bool bflag = ArgumentHelper::HasArgument(Def(),
"broadcast");
170 if (ArgumentHelper::HasArgument(Def(),
"broadcast")) {
171 broadcast = GetArgument(Def(),
"broadcast");
173 broadcast = MakeArgument<int>(
"broadcast", 0);
175 if (ArgumentHelper::HasArgument(Def(),
"axis")) {
176 axis = GetArgument(Def(),
"axis");
178 axis = MakeArgument<int>(
"axis", -1);
180 if (ArgumentHelper::HasArgument(Def(),
"axis_str")) {
181 axis_str = GetArgument(Def(),
"axis_str");
183 axis_str = MakeArgument<string>(
"axis_str",
"");
185 if (ArgumentHelper::HasArgument(Def(),
"order")) {
186 order = GetArgument(Def(),
"order");
188 order = MakeArgument<string>(
"order",
"NCHW");
195 grad_ops.push_back(CreateOperatorDef(
198 std::vector<string>{I(1)},
199 std::vector<string>{GI(1)},
200 std::vector<Argument>{one_arg}));
201 grad_ops.push_back(CreateOperatorDef(
204 std::vector<string>{I(1), GI(1)},
205 std::vector<string>{GI(1)}));
207 grad_ops.push_back(CreateOperatorDef(
210 std::vector<string>{I(0), GI(1)},
211 std::vector<string>{GI(0)},
212 vector<Argument>{broadcast, axis, axis_str, order}));
214 grad_ops.push_back(CreateOperatorDef(
217 std::vector<string>{I(0), GI(1)},
218 std::vector<string>{GI(0)}));
221 grad_ops.push_back(CreateOperatorDef(
224 std::vector<string>{GI(0), GO(0)},
225 std::vector<string>{GI(0)}));
227 grad_ops.push_back(CreateOperatorDef(
230 std::vector<string>{GI(0), I(1)},
231 std::vector<string>{GI(0)},
232 vector<Argument>{broadcast, axis, axis_str, order}));
234 grad_ops.push_back(CreateOperatorDef(
237 std::vector<string>{GI(0), I(1)},
238 std::vector<string>{GI(0)}));
272 grad_ops.push_back(CreateOperatorDef(
275 std::vector<string>{I(0)},
276 std::vector<string>{GI(1) +
"_autogen_pre_red"}));
277 grad_ops.push_back(CreateOperatorDef(
280 std::vector<string>{GI(1) +
"_autogen_pre_red", O(0)},
281 std::vector<string>{GI(1) +
"_autogen_pre_red"}));
283 grad_ops.push_back(CreateOperatorDef(
286 std::vector<string>{GI(1) +
"_autogen_pre_red", GO(0)},
287 std::vector<string>{GI(1) +
"_autogen_pre_red"}));
288 grad_ops.push_back(CreateOperatorDef(
291 vector<string>{GI(1) +
"_autogen_pre_red", I(1)},
292 vector<string>{GI(1)},
293 vector<Argument>{axis, axis_str, order}));
295 grad_ops.push_back(CreateOperatorDef(
298 std::vector<string>{GI(1) +
"_autogen_pre_red", GO(0)},
299 std::vector<string>{GI(1)}));
307 bool CopyArguments()
const override {
312 REGISTER_GRADIENT(Pow, GetPowGradient);
The CPU Context, representing the bare minimum of what a Context class in Caffe2 should implement...
A helper class to index into arguments.
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...