diff --git a/src/operator/contrib/gradient_multiplier_op.cc b/src/operator/contrib/gradient_multiplier_op.cc index 47f891ef802b..f1664a3eaac4 100644 --- a/src/operator/contrib/gradient_multiplier_op.cc +++ b/src/operator/contrib/gradient_multiplier_op.cc @@ -76,9 +76,7 @@ In forward pass it acts as an identity transform. During backpropagation it multiplies the gradient from the subsequent level by a scalar factor lambda and passes it to the preceding layer. )code" ADD_FILELINE) -.set_attr_parser([](NodeAttrs* attrs) { - attrs->parsed = std::stod(attrs->dict["scalar"]); - }) +.set_attr_parser(ParamParser) .set_attr("FInferStorageType", ElemwiseStorageType<1, 1, false, true, true>) .set_attr("FCompute", UnaryOp::IdentityCompute) .set_attr("FComputeEx", UnaryOp::IdentityComputeEx) @@ -87,7 +85,7 @@ the preceding layer. [](const NodeAttrs& attrs){ return std::vector{true}; }) -.add_argument("scalar", "float", "lambda multiplier"); +.add_arguments(NumpyBinaryScalarParam::__FIELDS__()); MXNET_OPERATOR_REGISTER_BINARY_SCALAR(_contrib_backward_gradientmultiplier) .set_attr("TIsBackward", true) diff --git a/src/operator/numpy/np_elemwise_broadcast_logic_op.cc b/src/operator/numpy/np_elemwise_broadcast_logic_op.cc index b44a22d65856..8c8320de30c6 100644 --- a/src/operator/numpy/np_elemwise_broadcast_logic_op.cc +++ b/src/operator/numpy/np_elemwise_broadcast_logic_op.cc @@ -223,7 +223,8 @@ struct TVMBinaryBroadcastScalarCompute { // scalar param type_codes[1] = kDLFloat; - values[1].v_float64 = nnvm::get(attrs.parsed); + const NumpyBinaryScalarParam& param = nnvm::get(attrs.parsed); + values[1].v_float64 = param.scalar; // output tensor type_codes[2] = kTVMDLTensorHandle; diff --git a/src/operator/numpy/np_elemwise_broadcast_op.cc b/src/operator/numpy/np_elemwise_broadcast_op.cc index c2db0fee7512..e23d23e36fce 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op.cc +++ b/src/operator/numpy/np_elemwise_broadcast_op.cc @@ -37,10 +37,6 @@ DMLC_REGISTER_PARAMETER(NumpyBinaryScalarParam); .set_attr_parser(ParamParser) \ .set_attr("FInferShape", ElemwiseShape<1, 1>) \ .set_attr("FInferType", NumpyBinaryScalarType) \ - .set_attr("FInplaceOption", \ - [](const NodeAttrs& attrs){ \ - return std::vector >{{0, 0}}; \ - }) \ .set_attr("FResourceRequest", \ [](const NodeAttrs& attrs) { \ return std::vector{ResourceRequest::kTempSpace}; \ diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc index 96e27789cf11..ce7f59a5520f 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc @@ -36,10 +36,6 @@ namespace op { .set_attr_parser(ParamParser) \ .set_attr("FInferShape", ElemwiseShape<1, 1>) \ .set_attr("FInferType", NumpyBinaryScalarType) \ - .set_attr("FInplaceOption", \ - [](const NodeAttrs& attrs){ \ - return std::vector >{{0, 0}}; \ - }) \ .set_attr("FResourceRequest", \ [](const NodeAttrs& attrs) { \ return std::vector{ResourceRequest::kTempSpace}; \ diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc b/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc index 3ae3ab93e0bb..e1b94ac20765 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc @@ -36,10 +36,6 @@ namespace op { .set_attr_parser(ParamParser) \ .set_attr("FInferShape", ElemwiseShape<1, 1>) \ .set_attr("FInferType", NumpyBinaryScalarType) \ - .set_attr("FInplaceOption", \ - [](const NodeAttrs& attrs){ \ - return std::vector >{{0, 0}}; \ - }) \ .set_attr("FResourceRequest", \ [](const NodeAttrs& attrs) { \ return std::vector{ResourceRequest::kTempSpace}; \ diff --git a/src/operator/numpy/np_true_divide-inl.h b/src/operator/numpy/np_true_divide-inl.h index 3132097b7cb5..c6b8cdfd7852 100644 --- a/src/operator/numpy/np_true_divide-inl.h +++ b/src/operator/numpy/np_true_divide-inl.h @@ -47,7 +47,8 @@ void TrueDivideScalarCompute(const nnvm::NodeAttrs &attrs, using namespace mxnet_op; using namespace mshadow::expr; Stream *s = ctx.get_stream(); - const double alpha = nnvm::get(attrs.parsed); + const NumpyBinaryScalarParam& param = nnvm::get(attrs.parsed); + const double alpha = param.scalar; const TBlob& data = inputs[0]; const TBlob& out = outputs[0]; if (out.type_flag_ == data.type_flag_) { diff --git a/src/operator/numpy/np_true_divide.cc b/src/operator/numpy/np_true_divide.cc index bf7324be5d16..7311d896d71c 100644 --- a/src/operator/numpy/np_true_divide.cc +++ b/src/operator/numpy/np_true_divide.cc @@ -104,9 +104,7 @@ NNVM_REGISTER_OP(_backward_npi_broadcast_div) NNVM_REGISTER_OP(_npi_true_divide_scalar) .set_num_inputs(1) .set_num_outputs(1) -.set_attr_parser([](NodeAttrs* attrs) { - attrs->parsed = std::stod(attrs->dict["scalar"]); - }) +.set_attr_parser(ParamParser) .set_attr("FInferShape", ElemwiseShape<1, 1>) .set_attr("FInferType", TrueDivideType<1>) .set_attr("FInplaceOption", @@ -122,14 +120,12 @@ NNVM_REGISTER_OP(_npi_true_divide_scalar) .set_attr("FCompute", TrueDivideScalarCompute) .set_attr("FGradient", ElemwiseGradUseNone{"_backward_div_scalar"}) .add_argument("data", "NDArray-or-Symbol", "source input") -.add_argument("scalar", "float", "scalar input"); +.add_arguments(NumpyBinaryScalarParam::__FIELDS__()); NNVM_REGISTER_OP(_npi_rtrue_divide_scalar) .set_num_inputs(1) .set_num_outputs(1) -.set_attr_parser([](NodeAttrs* attrs) { - attrs->parsed = std::stod(attrs->dict["scalar"]); - }) +.set_attr_parser(ParamParser) .set_attr("FInferShape", ElemwiseShape<1, 1>) .set_attr("FInferType", TrueDivideType<1>) .set_attr("FInplaceOption", @@ -145,7 +141,7 @@ NNVM_REGISTER_OP(_npi_rtrue_divide_scalar) .set_attr("FCompute", TrueDivideScalarCompute) .set_attr("FGradient", ElemwiseGradUseIn{"_backward_rdiv_scalar"}) .add_argument("data", "NDArray-or-Symbol", "source input") -.add_argument("scalar", "float", "scalar input"); +.add_arguments(NumpyBinaryScalarParam::__FIELDS__()); } // namespace op } // namespace mxnet diff --git a/src/operator/tensor/elemwise_binary_scalar_op.h b/src/operator/tensor/elemwise_binary_scalar_op.h index 3e3a1e3bdad4..c09e41867f46 100644 --- a/src/operator/tensor/elemwise_binary_scalar_op.h +++ b/src/operator/tensor/elemwise_binary_scalar_op.h @@ -44,7 +44,7 @@ struct NumpyBinaryScalarParam : public dmlc::Parameter { .set_default(1) .describe("Scalar input value"); DMLC_DECLARE_FIELD(is_int) - .set_default(false) + .set_default(true) .describe("Indicate whether scalar input is int type"); } diff --git a/tests/python/unittest/test_higher_order_grad.py b/tests/python/unittest/test_higher_order_grad.py index 8ccadd02f0a2..1c465d43539d 100644 --- a/tests/python/unittest/test_higher_order_grad.py +++ b/tests/python/unittest/test_higher_order_grad.py @@ -163,6 +163,7 @@ def grad_grad_op(x): check_second_order_unary(array, arccos, grad_grad_op) +@xfail_when_nonstandard_decimal_separator @with_seed() def test_arctan(): def arctan(x): @@ -214,6 +215,7 @@ def grad_grad_op(x): check_second_order_unary(array, arccosh, grad_grad_op) +@xfail_when_nonstandard_decimal_separator @with_seed() def test_arctanh(): def arctanh(x): @@ -290,6 +292,7 @@ def grad_grad_op(x): array = random_arrays(shape) check_second_order_unary(array, log2, grad_grad_op) + @xfail_when_nonstandard_decimal_separator @with_seed() def test_log10(): @@ -305,6 +308,7 @@ def grad_grad_op(x): check_second_order_unary(array, log10, grad_grad_op) +@xfail_when_nonstandard_decimal_separator @with_seed() def test_square(): def grad_grad_op(x): @@ -457,6 +461,7 @@ def grad_grad_op(x): check_second_order_unary(array, cbrt, grad_grad_op) +@xfail_when_nonstandard_decimal_separator @with_seed() def test_rsqrt(): def rsqrt(x): @@ -477,6 +482,7 @@ def grad_grad_op(x): check_second_order_unary(array, rsqrt, grad_grad_op) +@xfail_when_nonstandard_decimal_separator @with_seed() def test_rcbrt(): def rcbrt(x): diff --git a/tests/python/unittest/test_numpy_op.py b/tests/python/unittest/test_numpy_op.py index 3bb0668af7bb..fca7c71f4b57 100644 --- a/tests/python/unittest/test_numpy_op.py +++ b/tests/python/unittest/test_numpy_op.py @@ -2719,7 +2719,7 @@ def hybrid_forward(self, F, a, *args, **kwargs): mx_test_x1 = np.array(np_test_x1, dtype=ltype) mx_test_x2 = np_test_x2 np_func = getattr(_np, func) - mx_func = TestBinaryScalar(func, np_test_x2) + mx_func = TestBinaryScalar(func, mx_test_x2) if hybridize: mx_func.hybridize() rtol = 1e-2 if ltype is np.float16 else 1e-3 @@ -2729,14 +2729,14 @@ def hybrid_forward(self, F, a, *args, **kwargs): mx_test_x1.attach_grad() np_out = np_func(np_test_x1, np_test_x2) with mx.autograd.record(): - y = mx_func(mx_test_x1, mx_test_x2) + y = mx_func(mx_test_x1) assert y.shape == np_out.shape assert_almost_equal(y.asnumpy(), np_out.astype(y.dtype), rtol=rtol, atol=atol) if lgrad: y.backward() assert_almost_equal(mx_test_x1.grad.asnumpy(), collapse_sum_like(lgrad(y.asnumpy(), np_test_x1, np_test_x2), mx_test_x1.shape), - rtol=1e-1, atol=1e-2, equal_nan=True, use_broadcast=False) + rtol=rtol, atol=atol, equal_nan=True, use_broadcast=False) # Test imperative np_out = getattr(_np, func)(np_test_x1, np_test_x2) @@ -2757,7 +2757,7 @@ def hybrid_forward(self, F, a, *args, **kwargs): flags = [True, False] for func, func_data in funcs.items(): low, high, lgrad = func_data - for shape, ltype, is_int, is_int, hybridize in itertools.product(shapes, ltypes, flags, flags): + for shape, ltype, is_int, hybridize in itertools.product(shapes, ltypes, flags, flags): check_binary_scalar_func(func, low, high, shape, lgrad, ltype, is_int, hybridize)