未验证 提交 fe2bfe15 编写于 作者: 六个骨头 提交者: GitHub

【PaddlePaddle Hackathon 3 No.14】为 Paddle 新增 remainder_ API (#45266)

上级 236ac0d0
......@@ -56,7 +56,8 @@ class ElementwiseModOpMaker : public ElementwiseOpMaker {
namespace ops = paddle::operators;
REGISTER_OP_WITHOUT_GRADIENT(elementwise_mod,
ops::ElementwiseOp,
ops::ElementwiseModOpMaker);
ops::ElementwiseModOpMaker,
ops::ElementwiseOpInplaceInferer);
REGISTER_OP_VERSION(elementwise_mod)
.AddCheckpoint(
......
......@@ -239,6 +239,7 @@ from .tensor.math import mm # noqa: F401
from .tensor.math import divide # noqa: F401
from .tensor.math import floor_divide # noqa: F401
from .tensor.math import remainder # noqa: F401
from .tensor.math import remainder_ # noqa: F401
from .tensor.math import mod # noqa: F401
from .tensor.math import floor_mod # noqa: F401
from .tensor.math import multiply # noqa: F401
......
......@@ -97,12 +97,15 @@ class TestElementwiseModOpDouble(TestElementwiseModOpFloat):
class TestRemainderOp(unittest.TestCase):
def _executed_api(self, x, y, name=None):
return paddle.remainder(x, y, name)
def test_name(self):
with fluid.program_guard(fluid.Program()):
x = fluid.data(name="x", shape=[2, 3], dtype="int64")
y = fluid.data(name='y', shape=[2, 3], dtype='int64')
y_1 = paddle.remainder(x, y, name='div_res')
y_1 = self._executed_api(x, y, name='div_res')
self.assertEqual(('div_res' in y_1.name), True)
def test_dygraph(self):
......@@ -111,7 +114,7 @@ class TestRemainderOp(unittest.TestCase):
np_y = np.array([1, 5, 3, 3]).astype('int64')
x = paddle.to_tensor(np_x)
y = paddle.to_tensor(np_y)
z = paddle.remainder(x, y)
z = self._executed_api(x, y)
np_z = z.numpy()
z_expected = np.array([0, 3, 2, 1])
self.assertEqual((np_z == z_expected).all(), True)
......@@ -133,5 +136,44 @@ class TestRemainderOp(unittest.TestCase):
np.testing.assert_allclose(z_expected, z.numpy(), rtol=1e-05)
class TestRemainderInplaceOp(TestRemainderOp):
def _executed_api(self, x, y, name=None):
return x.remainder_(y, name)
class TestRemainderInplaceBroadcastSuccess(unittest.TestCase):
def init_data(self):
self.x_numpy = np.random.rand(2, 3, 4).astype('float')
self.y_numpy = np.random.rand(3, 4).astype('float')
def test_broadcast_success(self):
paddle.disable_static()
self.init_data()
x = paddle.to_tensor(self.x_numpy)
y = paddle.to_tensor(self.y_numpy)
inplace_result = x.remainder_(y)
numpy_result = self.x_numpy % self.y_numpy
self.assertEqual((inplace_result.numpy() == numpy_result).all(), True)
paddle.enable_static()
class TestRemainderInplaceBroadcastSuccess2(TestRemainderInplaceBroadcastSuccess
):
def init_data(self):
self.x_numpy = np.random.rand(1, 2, 3, 1).astype('float')
self.y_numpy = np.random.rand(3, 1).astype('float')
class TestRemainderInplaceBroadcastSuccess3(TestRemainderInplaceBroadcastSuccess
):
def init_data(self):
self.x_numpy = np.random.rand(2, 3, 1, 5).astype('float')
self.y_numpy = np.random.rand(1, 3, 1, 5).astype('float')
if __name__ == '__main__':
unittest.main()
......@@ -494,6 +494,29 @@ class TestDygraphInplaceSubtract(TestDygraphInplaceAdd):
return var.subtract_(input_var_2)
class TestDygraphInplaceRemainder(TestDygraphInplaceAdd):
def non_inplace_api_processing(self, var):
input_var_2 = paddle.to_tensor(self.input_var_numpy_2)
return var.remainder(input_var_2)
def inplace_api_processing(self, var):
input_var_2 = paddle.to_tensor(self.input_var_numpy_2)
return var.remainder_(input_var_2)
def test_leaf_inplace_var_error(self):
pass
def test_backward_error(self):
pass
def test_backward_success_1(self):
pass
def test_backward_success_2(self):
pass
class TestLossIsInplaceVar(unittest.TestCase):
def func_test_loss_is_inplace_var(self):
......
......@@ -184,6 +184,7 @@ from .math import mm # noqa: F401
from .math import divide # noqa: F401
from .math import floor_divide # noqa: F401
from .math import remainder # noqa: F401
from .math import remainder_ # noqa: F401
from .math import mod # noqa: F401
from .math import floor_mod # noqa: F401
from .math import multiply # noqa: F401
......@@ -367,6 +368,7 @@ tensor_method_func = [ # noqa
'divide',
'floor_divide',
'remainder',
'remainder_',
'mod',
'floor_mod',
'multiply',
......
......@@ -784,6 +784,24 @@ def remainder(x, y, name=None):
return _elementwise_op(LayerHelper(op_type, **locals()))
@inplace_apis_in_dygraph_only
def remainder_(x, y, name=None):
r"""
Inplace version of ``remainder`` API, the output Tensor will be inplaced with input ``x``.
Please refer to :ref:`api_tensor_remainder`.
"""
op_type = 'elementwise_mod_'
axis = -1
out_shape = broadcast_shape(x.shape, y.shape)
if out_shape != x.shape:
raise ValueError(
"The shape of broadcast output {} is different from that of inplace tensor {} in the Inplace operation.".format(
out_shape, x.shape))
return _elementwise_op_in_dygraph(x, y, axis=axis, op_name=op_type)
mod = remainder # noqa: F841
floor_mod = remainder # noqa: F841
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册