From c5f957ae387f6193a399c8749f923f1635df19e3 Mon Sep 17 00:00:00 2001 From: lilong12 Date: Thu, 10 Sep 2020 15:55:09 +0800 Subject: [PATCH] add double grad for tile op and expand_v2 op (#27114) * add double grad for tile, test=develop * add double grad for expand_v2 op, test=develop --- paddle/fluid/operators/expand_v2_op.cc | 22 +++++++++ paddle/fluid/operators/tile_op.cc | 22 +++++++++ .../fluid/tests/unittests/test_nn_grad.py | 49 +++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/paddle/fluid/operators/expand_v2_op.cc b/paddle/fluid/operators/expand_v2_op.cc index 359d512c34..a1ee47b7f9 100644 --- a/paddle/fluid/operators/expand_v2_op.cc +++ b/paddle/fluid/operators/expand_v2_op.cc @@ -230,6 +230,26 @@ class ExpandV2GradOpMaker : public framework::SingleGradOpMaker { } }; +template +class ExpandV2DoubleGradOpMaker : public framework::SingleGradOpMaker { + public: + using framework::SingleGradOpMaker::SingleGradOpMaker; + + protected: + void Apply(GradOpPtr op) const override { + op->SetType("expand_v2"); + op->SetInput("X", this->OutputGrad(framework::GradVarName("X"))); + op->SetOutput("Out", this->InputGrad(framework::GradVarName("Out"))); + if (this->HasInput("expand_shapes_tensor")) { + op->SetInput("expand_shapes_tensor", this->Input("expand_shapes_tensor")); + } + if (this->HasInput("Shape")) { + op->SetInput("Shape", this->Input("Shape")); + } + op->SetAttrMap(this->Attrs()); + } +}; + DECLARE_NO_NEED_BUFFER_VARS_INFERER(ExpandV2GradNoNeedBufVarsInferer, "X"); } // namespace operators @@ -240,6 +260,8 @@ REGISTER_OPERATOR(expand_v2, ops::ExpandV2Op, ops::ExpandV2OpMaker, ops::ExpandV2GradOpMaker, ops::ExpandV2GradOpMaker); REGISTER_OPERATOR(expand_v2_grad, ops::ExpandV2GradOp, + ops::ExpandV2DoubleGradOpMaker, + ops::ExpandV2DoubleGradOpMaker, ops::ExpandV2GradNoNeedBufVarsInferer); REGISTER_OP_CPU_KERNEL( expand_v2, ops::ExpandV2Kernel, diff --git a/paddle/fluid/operators/tile_op.cc b/paddle/fluid/operators/tile_op.cc index da4ca87296..bc1cb3b4aa 100644 --- a/paddle/fluid/operators/tile_op.cc +++ b/paddle/fluid/operators/tile_op.cc @@ -241,6 +241,26 @@ class TileGradOpMaker : public framework::SingleGradOpMaker { } }; +template +class TileDoubleGradOpMaker : public framework::SingleGradOpMaker { + public: + using framework::SingleGradOpMaker::SingleGradOpMaker; + + protected: + void Apply(GradOpPtr op) const override { + op->SetType("tile"); + op->SetInput("X", this->OutputGrad(framework::GradVarName("X"))); + op->SetOutput("Out", this->InputGrad(framework::GradVarName("Out"))); + if (this->HasInput("repeat_times_tensor")) { + op->SetInput("repeat_times_tensor", this->Input("repeat_times_tensor")); + } + if (this->HasInput("RepeatTimes")) { + op->SetInput("RepeatTimes", this->Input("RepeatTimes")); + } + op->SetAttrMap(this->Attrs()); + } +}; + DECLARE_NO_NEED_BUFFER_VARS_INFERER(TileGradNoNeedBufVarsInferer, "X"); } // namespace operators @@ -251,6 +271,8 @@ REGISTER_OPERATOR(tile, ops::TileOp, ops::TileOpMaker, ops::TileGradOpMaker, ops::TileGradOpMaker); REGISTER_OPERATOR(tile_grad, ops::TileGradOp, + ops::TileDoubleGradOpMaker, + ops::TileDoubleGradOpMaker, ops::TileGradNoNeedBufVarsInferer); REGISTER_OP_CPU_KERNEL( tile, ops::TileKernel, diff --git a/python/paddle/fluid/tests/unittests/test_nn_grad.py b/python/paddle/fluid/tests/unittests/test_nn_grad.py index 0e4f89f602..5d1e016287 100644 --- a/python/paddle/fluid/tests/unittests/test_nn_grad.py +++ b/python/paddle/fluid/tests/unittests/test_nn_grad.py @@ -17,6 +17,7 @@ from __future__ import print_function import unittest import numpy as np +import paddle import paddle.fluid as fluid import paddle.fluid.layers as layers import paddle.fluid.core as core @@ -200,5 +201,53 @@ class TestExpandDoubleGradCheck(unittest.TestCase): self.func(p) +class TestTileDoubleGradCheck(unittest.TestCase): + @prog_scope() + def func(self, place): + x_shape = [3, 12] + repeat_times = [4, 9] + eps = 0.005 + dtype = np.float64 + + x = layers.data('x', x_shape, False, dtype) + x.persistable = True + out = paddle.tile(x, repeat_times) + x_arr = np.random.uniform(-1, 1, x_shape).astype(dtype) + + gradient_checker.double_grad_check( + [x], out, x_init=x_arr, place=place, eps=eps) + + def test_grad(self): + places = [fluid.CPUPlace()] + if core.is_compiled_with_cuda(): + places.append(fluid.CUDAPlace(0)) + for p in places: + self.func(p) + + +class TestExpandV2DoubleGradCheck(unittest.TestCase): + @prog_scope() + def func(self, place): + x_shape = [1, 12] + new_shape = [4, 12] + eps = 0.005 + dtype = np.float64 + + x = layers.data('x', x_shape, False, dtype) + x.persistable = True + out = paddle.expand(x, new_shape) + x_arr = np.random.uniform(-1, 1, x_shape).astype(dtype) + + gradient_checker.double_grad_check( + [x], out, x_init=x_arr, place=place, eps=eps) + + def test_grad(self): + places = [fluid.CPUPlace()] + if core.is_compiled_with_cuda(): + places.append(fluid.CUDAPlace(0)) + for p in places: + self.func(p) + + if __name__ == "__main__": unittest.main() -- GitLab