test_imperative_double_grad.py 26.0 KB
Newer Older
1
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest
from unittest import TestCase
17

18
import numpy as np
19 20 21

import paddle
import paddle.fluid as fluid
22
from paddle.fluid.framework import _test_eager_guard
23 24
from paddle.fluid.wrapped_decorator import wrap_decorator
from paddle.vision.models import resnet50, resnet101
25 26 27 28


def _dygraph_guard_(func):
    def __impl__(*args, **kwargs):
J
Jiabin Yang 已提交
29
        if fluid._non_static_mode():
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
            return func(*args, **kwargs)
        else:
            with fluid.dygraph.guard():
                return func(*args, **kwargs)

    return __impl__


dygraph_guard = wrap_decorator(_dygraph_guard_)


def random_var(size, low=-1, high=1, dtype='float32'):
    x_np = np.random.uniform(low=low, high=high, size=size).astype(dtype)
    return fluid.dygraph.to_variable(x_np)


46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
class TestEagerGrad(TestCase):
    def func_simple_example_eager_grad(self):
        np.random.seed(2021)
        paddle.set_device('cpu')
        np_x = np.random.random((3, 3))
        np_y = np.random.random((3, 1))
        x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
        y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
        out = paddle.matmul(x, y)
        dx = fluid.dygraph.grad(out, x)

        dout = np.ones_like(np_y)
        expected_dx = np.matmul(dout, np.transpose(np_y))

        # stop_gradient = !create_graph, create_graph default false
        self.assertEqual(dx[0].stop_gradient, True)
62
        np.testing.assert_allclose(dx[0].numpy(), expected_dx, rtol=1e-05)
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

    def test_simple_example_eager_grad(self):
        with _test_eager_guard():
            self.func_simple_example_eager_grad()
        self.func_simple_example_eager_grad()

    def func_simple_example_eager_grad_allow_unused(self):
        np.random.seed(2021)
        paddle.set_device('cpu')
        np_x = np.random.random((3, 3))
        np_y = np.random.random((3, 1))
        np_z = np.random.random((3, 1))
        x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
        y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
        z = paddle.to_tensor(np_z, dtype="float64", stop_gradient=False)
        out_z = paddle.nn.functional.sigmoid(z)
        out = paddle.matmul(x, y)

        dx = fluid.dygraph.grad(out, [x, z], allow_unused=True)
        dout = np.ones_like(np_y)
        expected_dx = np.matmul(dout, np.transpose(np_y))
84
        np.testing.assert_allclose(dx[0].numpy(), expected_dx, rtol=1e-05)
85 86 87
        # stop_gradient = !create_graph, create_graph default false
        self.assertEqual(dx[0].stop_gradient, True)
        # x is unused input in the graph
88
        self.assertIsNone(dx[1])
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

    def test_simple_example_eager_grad_allow_unused(self):
        with _test_eager_guard():
            self.func_simple_example_eager_grad_allow_unused()
        self.func_simple_example_eager_grad_allow_unused()

    def func_simple_example_eager_grad_not_allow_unused(self):
        np.random.seed(2021)
        paddle.set_device('cpu')
        np_x = np.random.random((3, 3))
        np_y = np.random.random((3, 1))
        np_z = np.random.random((3, 1))
        x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
        y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
        z = paddle.to_tensor(np_z, dtype="float64", stop_gradient=False)
        out_z = paddle.nn.functional.sigmoid(z)
        out = paddle.matmul(x, y)

        try:
            # allow_unused is false in default
            dx = fluid.dygraph.grad(out, [x, z])
        except ValueError as e:
111
            error_msg = str(e)
112 113 114 115 116 117 118
            assert error_msg.find("allow_unused") > 0

    def test_simple_example_eager_grad_not_allow_unused(self):
        with _test_eager_guard():
            self.func_simple_example_eager_grad_not_allow_unused()
        self.func_simple_example_eager_grad_not_allow_unused()

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    def func_simple_example_eager_grad_duplicate_input(self):
        np.random.seed(2021)
        paddle.set_device('cpu')
        np_x = np.random.random((3, 3))
        np_y = np.random.random((3, 1))
        np_z = np.random.random((3, 1))
        x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
        y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
        z = paddle.to_tensor(np_z, dtype="float64", stop_gradient=False)
        out_z = paddle.nn.functional.sigmoid(z)
        out = paddle.matmul(x, y)

        try:
            # duplicate input will arise RuntimeError errors
            dx = fluid.dygraph.grad(out, [x, x])
        except RuntimeError as e:
135
            error_msg = str(e)
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
            assert error_msg.find("duplicate") > 0

    def test_simple_example_eager_grad_duplicate_input(self):
        with _test_eager_guard():
            self.func_simple_example_eager_grad_duplicate_input()
        self.func_simple_example_eager_grad_duplicate_input()

    def func_simple_example_eager_grad_duplicate_output(self):
        np.random.seed(2021)
        paddle.set_device('cpu')
        np_x = np.random.random((3, 3))
        np_y = np.random.random((3, 1))
        np_z = np.random.random((3, 1))
        x = paddle.to_tensor(np_x, dtype="float64", stop_gradient=False)
        y = paddle.to_tensor(np_y, dtype="float64", stop_gradient=False)
        z = paddle.to_tensor(np_z, dtype="float64", stop_gradient=False)
        out_z = paddle.nn.functional.sigmoid(z)
        out = paddle.matmul(x, y)

        try:
            # duplicate output will arise RuntimeError errors
            dx = fluid.dygraph.grad([out, out], [x])
        except RuntimeError as e:
159
            error_msg = str(e)
160 161 162 163 164 165 166
            assert error_msg.find("duplicate") > 0

    def test_simple_example_eager_grad_duplicate_output(self):
        with _test_eager_guard():
            self.func_simple_example_eager_grad_duplicate_output()
        self.func_simple_example_eager_grad_duplicate_output()

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    def test_simple_example_eager_two_grad_output(self):
        with _test_eager_guard():
            x1 = paddle.to_tensor([1.0, 2.0])
            x1.stop_gradient = False
            x2 = paddle.to_tensor([1.0, 2.0])
            x2.stop_gradient = False
            out1 = x1 * 2
            out2 = x2 * 2

            dout2_record_by_hook = []

            def record_hook(grad):
                dout2_record_by_hook.append(grad)

            out2.register_hook(record_hook)

            out3 = paddle.multiply(out1, out2)
            out4 = paddle.mean(out3)
            egr_dout2, egr_dout3 = paddle.grad([out4], [out2, out3])

187 188 189
            np.testing.assert_array_equal(
                dout2_record_by_hook[0].numpy(), np.array([1.0, 2.0])
            )
190 191 192 193 194 195 196 197 198 199 200 201 202 203

        x1 = paddle.to_tensor([1.0, 2.0])
        x1.stop_gradient = False
        x2 = paddle.to_tensor([1.0, 2.0])
        x2.stop_gradient = False
        out1 = x1 * 2
        out2 = x2 * 2

        out3 = paddle.multiply(out1, out2)
        out4 = paddle.mean(out3)
        dout2, dout3 = paddle.grad([out4], [out2, out3])

        self.assertEqual(dout2.stop_gradient, egr_dout2.stop_gradient)
        self.assertEqual(dout3.stop_gradient, egr_dout3.stop_gradient)
204 205
        np.testing.assert_array_equal(dout2.numpy(), egr_dout2.numpy())
        np.testing.assert_array_equal(dout3.numpy(), egr_dout3.numpy())
206

207

208 209 210 211 212
class TestDygraphDoubleGrad(TestCase):
    def setUp(self):
        self.sort_sum_gradient = False
        self.shape = [5, 10]

213 214 215 216 217 218 219 220 221 222
    def grad(
        self,
        outputs,
        inputs,
        grad_outputs=None,
        no_grad_vars=None,
        retain_graph=None,
        create_graph=False,
        allow_unused=False,
    ):
223
        fluid.set_flags({'FLAGS_sort_sum_gradient': self.sort_sum_gradient})
224 225 226 227 228 229 230 231 232
        return fluid.dygraph.grad(
            outputs=outputs,
            inputs=inputs,
            grad_outputs=grad_outputs,
            no_grad_vars=no_grad_vars,
            retain_graph=retain_graph,
            create_graph=create_graph,
            allow_unused=allow_unused,
        )
233 234

    @dygraph_guard
235
    def func_exception(self):
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
        with self.assertRaises(AssertionError):
            self.grad(None, None)

        shape = self.shape

        with self.assertRaises(AssertionError):
            self.grad(1, random_var(shape))

        with self.assertRaises(AssertionError):
            self.grad(random_var(shape), 1)

        with self.assertRaises(AssertionError):
            self.grad([1], [random_var(shape)])

        with self.assertRaises(AssertionError):
            self.grad([random_var(shape)], [1])

        with self.assertRaises(AssertionError):
254 255 256 257 258
            self.grad(
                [random_var(shape), random_var(shape)],
                [random_var(shape)],
                [random_var(shape)],
            )
259 260

        with self.assertRaises(AssertionError):
261 262 263
            self.grad(
                [random_var(shape)], [random_var(shape)], no_grad_vars=[1]
            )
264 265

        with self.assertRaises(AssertionError):
Z
Zeng Jinle 已提交
266
            self.grad([random_var(shape)], [random_var(shape)], no_grad_vars=1)
267

268 269 270 271 272
    def test_exception(self):
        with _test_eager_guard():
            self.func_exception()
        self.func_exception()

273
    @dygraph_guard
274
    def func_simple_example(self):
275 276 277 278 279
        x = random_var(self.shape)
        x.stop_gradient = False
        y = x + 1

        for create_graph in [False, True]:
280 281 282
            (dx,) = self.grad(
                [x], [x], create_graph=create_graph, retain_graph=True
            )
283 284 285 286
            self.assertEqual(dx.shape, x.shape)
            self.assertTrue(np.all(dx.numpy() == 1))
            self.assertNotEqual(dx.stop_gradient, create_graph)

287 288 289
            (dx_mul_2,) = self.grad(
                [y, x], [x], create_graph=create_graph, retain_graph=True
            )
290 291 292 293
            self.assertEqual(dx_mul_2.shape, x.shape)
            self.assertTrue(np.all(dx_mul_2.numpy() == 2))
            self.assertNotEqual(dx_mul_2.stop_gradient, create_graph)

294 295 296
            (none_grad,) = self.grad(
                [x], [y], create_graph=create_graph, allow_unused=True
            )
297
            self.assertIsNone(none_grad)
298

299 300 301
            (grad_with_none_and_not_none,) = self.grad(
                [x, y], [y], create_graph=create_graph
            )
302 303
            self.assertTrue(grad_with_none_and_not_none.shape, x.shape)
            self.assertTrue(np.all(grad_with_none_and_not_none.numpy() == 1))
304 305 306
            self.assertNotEqual(
                grad_with_none_and_not_none.stop_gradient, create_graph
            )
307

308 309 310 311 312
    def test_simple_example(self):
        with _test_eager_guard():
            self.func_simple_example()
        self.func_simple_example()

313
    @dygraph_guard
314 315 316 317 318 319 320 321 322 323 324 325 326 327
    def func_example_no_grad_vars(self):
        x = random_var(self.shape)
        x_np = x.numpy()
        numel = x_np.size
        x.stop_gradient = False

        y1 = fluid.layers.relu(x)
        y2 = fluid.layers.relu(x)
        z = y1 + y2
        w = z * z

        w_mean = fluid.layers.reduce_mean(w)
        del y1, z, w

328 329 330
        (dx_actual,) = self.grad(
            [w_mean], [x], create_graph=True, no_grad_vars=[y2]
        )
331 332 333 334

        self.assertFalse(y2.stop_gradient)
        self.assertFalse(dx_actual.stop_gradient)

335 336 337 338 339 340 341
        dx_expected = (
            1.0
            / float(numel)
            * (np.maximum(x_np, 0) + y2.numpy())
            * (x_np > 0)
            * 2
        ).astype('float32')
342

343
        np.testing.assert_allclose(dx_actual.numpy(), dx_expected, rtol=1e-05)
344 345 346 347 348 349 350 351

    def test_example_no_grad_vars(self):
        with _test_eager_guard():
            self.func_example_no_grad_vars()
        self.func_example_no_grad_vars()

    @dygraph_guard
    def func_none_one_initial_gradient(self):
352 353 354 355 356 357
        numel = 1
        for s in self.shape:
            numel *= s

        half_numel = int(numel / 2)
        half_x_positive = np.random.uniform(low=1, high=2, size=[half_numel])
358 359 360 361 362 363
        half_x_negative = np.random.uniform(
            low=-2, high=-1, size=[numel - half_numel]
        )
        x_np = np.array(list(half_x_positive) + list(half_x_negative)).astype(
            'float32'
        )
364 365 366
        np.random.shuffle(x_np)

        x = fluid.dygraph.to_variable(x_np)
367 368
        x.stop_gradient = False

369
        alpha = 0.2
370
        y = paddle.nn.functional.leaky_relu(x, alpha)
371 372 373 374
        y = y * y
        z = y * y

        x_np = x.numpy()
375 376
        relu_x_np = np.maximum(x_np, alpha * x_np).astype('float32')
        relu_x_grad_np = ((x_np > 0) + (x_np < 0) * alpha).astype('float32')
377
        dy_expected = (relu_x_np * relu_x_grad_np * 2).astype('float32')
378 379 380
        dz_expected = (np.power(relu_x_np, 3) * relu_x_grad_np * 4).astype(
            'float32'
        )
381

382 383
        random_grad_y = random_var(y.shape, low=1, high=2)
        random_grad_z = random_var(z.shape, low=1, high=2)
384 385 386 387 388 389 390 391 392
        ones_grad_y = np.ones(y.shape).astype('float32')
        ones_grad_z = np.ones(z.shape).astype('float32')

        original_random_grad_y = random_grad_y.numpy()
        original_random_grad_z = random_grad_z.numpy()

        for grad_y in [random_grad_y]:
            for grad_z in [random_grad_z]:
                for create_graph in [False, True]:
393 394 395 396 397 398 399
                    (dx_actual,) = self.grad(
                        outputs=[y, z],
                        inputs=[x],
                        grad_outputs=[grad_y, grad_z],
                        create_graph=create_graph,
                        retain_graph=True,
                    )
400

401 402
                    grad_y_np = (
                        ones_grad_y if grad_y is None else grad_y.numpy()
403
                    )
404 405
                    grad_z_np = (
                        ones_grad_z if grad_z is None else grad_z.numpy()
406 407
                    )

408 409 410 411 412 413
                    dx_expected = (
                        dy_expected * grad_y_np + dz_expected * grad_z_np
                    )
                    np.testing.assert_allclose(
                        dx_actual.numpy(), dx_expected, rtol=1e-05
                    )
414 415 416

                    if grad_y is not None:
                        self.assertTrue(grad_y.stop_gradient)
417 418 419
                        np.testing.assert_array_equal(
                            grad_y.numpy(), original_random_grad_y
                        )
420 421 422

                    if grad_z is not None:
                        self.assertTrue(grad_z.stop_gradient)
423 424 425
                        np.testing.assert_array_equal(
                            grad_z.numpy(), original_random_grad_z
                        )
426

427 428 429 430 431
    def test_none_one_initial_gradient(self):
        with _test_eager_guard():
            self.func_none_one_initial_gradient()
        self.func_none_one_initial_gradient()

432
    @dygraph_guard
433
    def func_example_with_gradient_accumulation_and_create_graph(self):
434 435 436 437 438 439 440 441 442 443 444 445
        x = random_var(self.shape)
        x_np = x.numpy()
        numel = x_np.size
        x.stop_gradient = False

        y = fluid.layers.relu(x)
        z = y + 1
        w = z * z

        w_mean = fluid.layers.reduce_mean(w)
        del y, z, w

446
        (dx_actual,) = self.grad([w_mean], [x], create_graph=True)
447 448 449 450 451
        del w_mean

        self.assertFalse(dx_actual.stop_gradient)

        # Theoritical result based on math calculation
452 453 454
        dx_expected = (
            1.0 / float(numel) * (np.maximum(x_np, 0) + 1) * (x_np > 0) * 2
        ).astype('float32')
455
        np.testing.assert_allclose(dx_actual.numpy(), dx_expected, rtol=1e-05)
456

457 458
        loss = fluid.layers.reduce_mean(dx_actual * dx_actual + x * x)
        loss.backward(retain_graph=True)
459

460
        x_grad_actual = x.gradient()
461 462 463 464 465
        x_grad_expected = (
            2.0
            / float(numel)
            * (x_np + dx_expected * (x_np > 0) * 2 / float(numel))
        ).astype('float32')
466
        np.testing.assert_allclose(x_grad_actual, x_grad_expected, rtol=1e-05)
467 468 469

        for i in range(5):
            loss.backward(retain_graph=True)
470
            x_grad_actual = x.gradient()
471 472 473 474 475 476 477 478
            x_grad_expected = (i + 2) * (
                2.0
                / float(numel)
                * (x_np + dx_expected * (x_np > 0) * 2 / float(numel))
            ).astype('float32')
            np.testing.assert_allclose(
                x_grad_actual, x_grad_expected, rtol=1e-05
            )
479

480 481 482 483 484
    def test_example_with_gradient_accumulation_and_create_graph(self):
        with _test_eager_guard():
            self.func_example_with_gradient_accumulation_and_create_graph()
        self.func_example_with_gradient_accumulation_and_create_graph()

485
    @dygraph_guard
486
    def func_example_with_gradient_accumulation_and_no_grad_vars(self):
487 488 489 490 491 492 493 494 495 496 497 498 499
        x = random_var(self.shape)
        x_np = x.numpy()
        numel = x_np.size
        x.stop_gradient = False

        y1 = fluid.layers.relu(x)
        y2 = fluid.layers.relu(x)
        z = y1 + y2
        w = z * z

        w_mean = fluid.layers.reduce_mean(w)
        del y1, z, w

500 501 502 503 504 505 506
        (dx_actual,) = self.grad(
            [w_mean],
            [x],
            retain_graph=True,
            create_graph=True,
            no_grad_vars=[y2],
        )
507 508 509 510

        self.assertFalse(y2.stop_gradient)
        self.assertFalse(dx_actual.stop_gradient)

511 512 513 514 515 516 517
        dx_expected = (
            1.0
            / float(numel)
            * (np.maximum(x_np, 0) + y2.numpy())
            * (x_np > 0)
            * 2
        ).astype('float32')
518
        np.testing.assert_allclose(dx_actual.numpy(), dx_expected, rtol=1e-05)
519

520 521
        loss = fluid.layers.reduce_mean(dx_actual * dx_actual + x * x)
        loss.backward()
522

523
        x_grad_actual = x.gradient()
524 525 526 527 528
        x_grad_expected = (
            2.0
            / float(numel)
            * (x_np + dx_expected * (x_np > 0) * 4 / float(numel))
        ).astype('float32')
529
        np.testing.assert_allclose(x_grad_actual, x_grad_expected, rtol=1e-05)
530 531 532 533 534

    def test_example_with_gradient_accumulation_and_no_grad_vars(self):
        with _test_eager_guard():
            self.func_example_with_gradient_accumulation_and_no_grad_vars()
        self.func_example_with_gradient_accumulation_and_no_grad_vars()
535 536

    @dygraph_guard
537
    def func_example_with_gradient_accumulation_and_not_create_graph(self):
538 539 540 541 542 543 544 545 546 547 548 549
        x = random_var(self.shape)
        x_np = x.numpy()
        numel = x_np.size
        x.stop_gradient = False

        y = fluid.layers.relu(x)
        z = y + 1
        w = z * z

        w_mean = fluid.layers.reduce_mean(w)
        del y, z, w

550
        (dx_actual,) = self.grad([w_mean], [x], create_graph=False)
551 552 553 554
        del w_mean

        self.assertTrue(dx_actual.stop_gradient)

555 556 557
        dx_expected = (
            1.0 / float(numel) * (np.maximum(x_np, 0) + 1) * (x_np > 0) * 2
        ).astype('float32')
558

559
        np.testing.assert_allclose(dx_actual.numpy(), dx_expected, rtol=1e-05)
560

561 562
        loss = fluid.layers.reduce_mean(dx_actual * dx_actual + x * x)
        loss.backward()
563

564 565
        x_grad_actual = x.gradient()
        x_grad_expected = (2.0 * x_np / float(numel)).astype('float32')
566
        np.testing.assert_allclose(x_grad_actual, x_grad_expected, rtol=1e-05)
567 568 569 570 571

    def test_example_with_gradient_accumulation_and_not_create_graph(self):
        with _test_eager_guard():
            self.func_example_with_gradient_accumulation_and_not_create_graph()
        self.func_example_with_gradient_accumulation_and_not_create_graph()
572 573 574 575 576 577 578 579


class TestDygraphDoubleGradSortGradient(TestDygraphDoubleGrad):
    def setUp(self):
        self.sort_sum_gradient = True
        self.shape = [5, 10]


H
hong 已提交
580
class TestDygraphDoubleGradVisitedUniq(TestCase):
581
    def func_compare(self):
582 583 584 585 586
        value = (
            np.random.uniform(-0.5, 0.5, 100)
            .reshape(10, 2, 5)
            .astype("float32")
        )
H
hong 已提交
587 588

        def model_f(input):
589
            linear = fluid.dygraph.Linear(5, 3, bias_attr=False)
H
hong 已提交
590 591
            for i in range(10):
                if i == 0:
592
                    out = linear(input)
H
hong 已提交
593
                else:
594
                    out = out + linear(input)
H
hong 已提交
595 596
            return out

597 598
        fluid.set_flags({'FLAGS_sort_sum_gradient': True})

H
hong 已提交
599
        with fluid.dygraph.guard():
C
cnn 已提交
600
            paddle.seed(123)
L
Leo Chen 已提交
601
            paddle.framework.random._manual_program_seed(123)
H
hong 已提交
602 603 604 605 606
            a = fluid.dygraph.to_variable(value)
            a.stop_gradient = False

            out = model_f(a)

607 608 609 610 611 612 613
            dx = fluid.dygraph.grad(
                outputs=[out],
                inputs=[a],
                create_graph=False,
                only_inputs=True,
                allow_unused=False,
            )
H
hong 已提交
614 615 616 617

            grad_1 = dx[0].numpy()

        with fluid.dygraph.guard():
C
cnn 已提交
618
            paddle.seed(123)
L
Leo Chen 已提交
619
            paddle.framework.random._manual_program_seed(123)
H
hong 已提交
620 621 622 623
            a = fluid.dygraph.to_variable(value)
            a.stop_gradient = False

            out = model_f(a)
624
            out.backward()
H
hong 已提交
625 626 627

            grad_2 = a.gradient()

628
        np.testing.assert_array_equal(grad_1, grad_2)
629

630 631 632 633 634
    def test_compare(self):
        with _test_eager_guard():
            self.func_compare()
        self.func_compare()

635 636 637 638 639 640

class TestRaiseNoDoubleGradOp(TestCase):
    def raise_no_grad_op(self):
        with fluid.dygraph.guard():
            x = fluid.layers.ones(shape=[2, 3, 2, 2], dtype='float32')
            x.stop_gradient = False
641
            y = paddle.static.nn.group_norm(x, groups=1)
642

643 644 645
            dx = fluid.dygraph.grad(
                outputs=[y], inputs=[x], create_graph=True, retain_graph=True
            )[0]
646 647 648 649 650

            loss = fluid.layers.reduce_mean(dx)
            loss.backward()

    def test_raise(self):
651
        self.assertRaises(RuntimeError, self.raise_no_grad_op)
H
hong 已提交
652 653


W
Weilong Wu 已提交
654 655 656 657 658 659
class TestDoubleGradResNet(TestCase):
    def setUp(self):
        paddle.seed(123)
        paddle.framework.random._manual_program_seed(123)
        self.data = np.random.rand(1, 3, 224, 224).astype(np.float32)

Z
Zeng Jinle 已提交
660
    @dygraph_guard
W
Weilong Wu 已提交
661 662 663 664 665 666 667 668
    def test_resnet_resnet50(self):
        with _test_eager_guard():
            model = resnet50(pretrained=False)
            egr_data = paddle.to_tensor(self.data)
            egr_data.stop_gradient = False
            egr_out = model(egr_data)
            egr_preds = paddle.argmax(egr_out, axis=1)
            egr_label_onehot = paddle.nn.functional.one_hot(
669 670
                paddle.to_tensor(egr_preds), num_classes=egr_out.shape[1]
            )
W
Weilong Wu 已提交
671 672 673 674 675 676 677 678
            egr_target = paddle.sum(egr_out * egr_label_onehot, axis=1)

            egr_g = paddle.grad(outputs=egr_target, inputs=egr_out)[0]
            egr_g_numpy = egr_g.numpy()
            self.assertEqual(list(egr_g_numpy.shape), list(egr_out.shape))

        model = resnet50(pretrained=False)
        data = paddle.to_tensor(self.data)
Z
Zeng Jinle 已提交
679
        data.stop_gradient = False
W
Weilong Wu 已提交
680
        out = model(data)
Z
Zeng Jinle 已提交
681
        preds = paddle.argmax(out, axis=1)
682 683 684
        label_onehot = paddle.nn.functional.one_hot(
            paddle.to_tensor(preds), num_classes=out.shape[1]
        )
Z
Zeng Jinle 已提交
685 686 687 688 689 690
        target = paddle.sum(out * label_onehot, axis=1)

        g = paddle.grad(outputs=target, inputs=out)[0]
        g_numpy = g.numpy()
        self.assertEqual(list(g_numpy.shape), list(out.shape))

691 692
        np.testing.assert_array_equal(egr_out, out)
        np.testing.assert_array_equal(egr_g_numpy, g_numpy)
Z
Zeng Jinle 已提交
693

W
Weilong Wu 已提交
694 695 696 697 698 699 700 701 702
    @dygraph_guard
    def test_resnet_resnet101(self):
        with _test_eager_guard():
            model = resnet101(pretrained=False)
            egr_data = paddle.to_tensor(self.data)
            egr_data.stop_gradient = False
            egr_out = model(egr_data)
            egr_preds = paddle.argmax(egr_out, axis=1)
            egr_label_onehot = paddle.nn.functional.one_hot(
703 704
                paddle.to_tensor(egr_preds), num_classes=egr_out.shape[1]
            )
W
Weilong Wu 已提交
705 706 707 708 709 710 711 712 713 714 715
            egr_target = paddle.sum(egr_out * egr_label_onehot, axis=1)

            egr_g = paddle.grad(outputs=egr_target, inputs=egr_out)[0]
            egr_g_numpy = egr_g.numpy()
            self.assertEqual(list(egr_g_numpy.shape), list(egr_out.shape))

        model = resnet101(pretrained=False)
        data = paddle.to_tensor(self.data)
        data.stop_gradient = False
        out = model(data)
        preds = paddle.argmax(out, axis=1)
716 717 718
        label_onehot = paddle.nn.functional.one_hot(
            paddle.to_tensor(preds), num_classes=out.shape[1]
        )
W
Weilong Wu 已提交
719
        target = paddle.sum(out * label_onehot, axis=1)
Z
Zeng Jinle 已提交
720

W
Weilong Wu 已提交
721 722 723
        g = paddle.grad(outputs=target, inputs=out)[0]
        g_numpy = g.numpy()
        self.assertEqual(list(g_numpy.shape), list(out.shape))
Z
Zeng Jinle 已提交
724

725 726
        np.testing.assert_array_equal(egr_out, out)
        np.testing.assert_array_equal(egr_g_numpy, g_numpy)
Z
Zeng Jinle 已提交
727 728


729 730 731 732
class TestDoubleGradBasics(TestCase):
    def test_matmul(self):
        input_numpy = np.ones([3, 3]) * 2
        with _test_eager_guard():
733 734 735 736 737 738 739 740 741
            x = paddle.to_tensor(
                input_numpy, stop_gradient=False, dtype='float32'
            )
            y = paddle.to_tensor(
                input_numpy, stop_gradient=False, dtype='float32'
            )
            grad_out = paddle.to_tensor(
                np.ones([3, 3]), stop_gradient=False, dtype='float32'
            )
742 743

            out = paddle.matmul(x, y, False, False)
744 745 746
            new_x_g, new_y_g = paddle.grad(
                [out], [x, y], [grad_out], retain_graph=True, create_graph=True
            )
747 748 749
            new_x_g.backward()

            out_ref = np.ones([3, 3]) * 12.0
750
            np.testing.assert_array_equal(out.numpy(), out_ref)
751 752 753

            new_x_g_ref = np.ones([3, 3]) * 6.0
            new_y_g_ref = np.ones([3, 3]) * 6.0
754 755
            np.testing.assert_array_equal(new_x_g.numpy(), new_x_g_ref)
            np.testing.assert_array_equal(new_y_g.numpy(), new_y_g_ref)
756 757

            x_grad_ref = np.ones([3, 3]) * 0.0
758
            np.testing.assert_array_equal(x.grad.numpy(), x_grad_ref)
759 760

            y_grad_ref = np.ones([3, 3]) * 3.0
761
            np.testing.assert_array_equal(y.grad.numpy(), y_grad_ref)
762 763

            grad_out_grad_ref = np.ones([3, 3]) * 6.0
764 765 766
            np.testing.assert_array_equal(
                grad_out.grad.numpy(), grad_out_grad_ref
            )
767 768


769 770
if __name__ == '__main__':
    unittest.main()