test_imperative_basic.py 38.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# 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
import numpy as np

import paddle.fluid as fluid
from paddle.fluid import core
20
from paddle.fluid import Linear
21
from paddle.fluid.layer_helper import LayerHelper
M
minqiyang 已提交
22
from test_imperative_base import new_program_scope
23
import paddle.fluid.dygraph_utils as dygraph_utils
24
from paddle.fluid.dygraph.layer_object_helper import LayerObjectHelper
25
import paddle
26
from paddle.fluid.framework import _in_legacy_dygraph, _test_eager_guard
27 28


29
class MyLayer(fluid.Layer):
30
    def __init__(self):
31
        super().__init__()
32 33

    def forward(self, inputs):
M
minqiyang 已提交
34
        x = fluid.layers.relu(inputs)
35
        self._x_for_debug = x
X
Xin Pan 已提交
36 37 38
        x = fluid.layers.elementwise_mul(x, x)
        x = fluid.layers.reduce_sum(x)
        return [x]
39 40


41
class MLP(fluid.Layer):
42
    def __init__(self, input_size):
43
        super().__init__()
44 45 46
        self._linear1 = Linear(
            input_size,
            3,
47 48 49 50 51 52 53
            param_attr=fluid.ParamAttr(
                initializer=fluid.initializer.Constant(value=0.1)
            ),
            bias_attr=fluid.ParamAttr(
                initializer=fluid.initializer.Constant(value=0.1)
            ),
        )
54 55 56
        self._linear2 = Linear(
            3,
            4,
57 58 59 60 61 62 63
            param_attr=fluid.ParamAttr(
                initializer=fluid.initializer.Constant(value=0.1)
            ),
            bias_attr=fluid.ParamAttr(
                initializer=fluid.initializer.Constant(value=0.1)
            ),
        )
X
Xin Pan 已提交
64 65

    def forward(self, inputs):
66 67
        x = self._linear1(inputs)
        x = self._linear2(x)
X
Xin Pan 已提交
68 69 70 71
        x = fluid.layers.reduce_sum(x)
        return x


72
class SimpleRNNCell(fluid.Layer):
73
    def __init__(self, step_input_size, hidden_size, output_size, param_attr):
74
        super().__init__()
75 76 77
        self.step_input_size = step_input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
78 79
        self._dtype = core.VarDesc.VarType.FP32
        self.param_attr = param_attr
80 81 82 83

        i2h_param_shape = [self.step_input_size, self.hidden_size]
        h2h_param_shape = [self.hidden_size, self.hidden_size]
        h2o_param_shape = [self.output_size, self.hidden_size]
S
songyouwei 已提交
84
        self._i2h_w = None
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
        self._i2h_w = self.create_parameter(
            attr=self.param_attr,
            shape=i2h_param_shape,
            dtype=self._dtype,
            is_bias=False,
        )
        self._h2h_w = self.create_parameter(
            attr=self.param_attr,
            shape=h2h_param_shape,
            dtype=self._dtype,
            is_bias=False,
        )
        self._h2o_w = self.create_parameter(
            attr=self.param_attr,
            shape=h2o_param_shape,
            dtype=self._dtype,
            is_bias=False,
        )
103 104

    def forward(self, input, pre_hidden):
105 106 107
        tmp_i2h = paddle.fluid.layers.nn.mul(input, self._i2h_w)
        tmp_h2h = paddle.fluid.layers.nn.mul(pre_hidden, self._h2h_w)
        hidden = paddle.add(tmp_h2h, tmp_i2h)
108
        hidden = self._helper.append_activation(hidden, act='tanh')
109 110 111
        out = paddle.fluid.layers.nn.mul(hidden, self._h2o_w)
        softmax_out = paddle.nn.functional.softmax(out)
        reduce_out = paddle.fluid.layers.nn.reduce_sum(softmax_out)
112 113 114
        return reduce_out, hidden


115
class SimpleRNN(fluid.Layer):
116
    def __init__(self):
117
        super().__init__()
J
JiabinYang 已提交
118 119
        self.seq_len = 4
        self._cell = SimpleRNNCell(
120 121 122 123 124
            3,
            3,
            3,
            fluid.ParamAttr(initializer=fluid.initializer.Constant(value=0.1)),
        )
J
JiabinYang 已提交
125 126

    def forward(self, inputs):
J
JiabinYang 已提交
127
        outs = list()
J
JiabinYang 已提交
128 129
        pre_hiddens = list()

130 131 132 133 134 135 136 137
        init_hidden = self.create_parameter(
            attr=fluid.ParamAttr(
                initializer=fluid.initializer.Constant(value=0.1)
            ),
            shape=[1, 3],
            dtype='float32',
            is_bias=False,
        )
J
JiabinYang 已提交
138
        pre_hidden = init_hidden
J
JiabinYang 已提交
139
        for i in range(self.seq_len):
140 141 142
            input = fluid.layers.slice(
                inputs, axes=[1], starts=[i], ends=[i + 1]
            )
J
JiabinYang 已提交
143
            input = fluid.layers.reshape(input, shape=[1, 3])
J
JiabinYang 已提交
144 145
            out_softmax, pre_hidden = self._cell(input, pre_hidden)
            outs.append(out_softmax)
J
JiabinYang 已提交
146

J
JiabinYang 已提交
147
        return outs, pre_hiddens
J
JiabinYang 已提交
148 149


M
minqiyang 已提交
150
class TestImperative(unittest.TestCase):
151
    def functional_dygraph_context(self):
152 153 154 155
        self.assertFalse(fluid.dygraph.enabled())
        fluid.enable_dygraph()
        self.assertTrue(fluid.dygraph.enabled())
        np_inp = np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32)
156
        var_inp = paddle.to_tensor(np_inp)
157 158 159 160 161 162 163 164 165
        mlp = MLP(input_size=2)
        out = mlp(var_inp)
        dy_out1 = out.numpy()
        out.backward()
        dy_grad1 = mlp._linear1.weight.gradient()
        fluid.disable_dygraph()
        self.assertFalse(fluid.dygraph.enabled())
        with fluid.dygraph.guard():
            self.assertTrue(fluid.dygraph.enabled())
166
            var_inp = paddle.to_tensor(np_inp)
167 168 169 170 171 172
            mlp = MLP(input_size=2)
            out = mlp(var_inp)
            dy_out2 = out.numpy()
            out.backward()
            dy_grad2 = mlp._linear1.weight.gradient()
        self.assertFalse(fluid.dygraph.enabled())
173 174
        np.testing.assert_array_equal(dy_out1, dy_out2)
        np.testing.assert_array_equal(dy_grad1, dy_grad2)
175

176 177 178 179 180 181
    def test_functional_dygraph_context(self):
        with _test_eager_guard():
            self.functional_dygraph_context()
        self.functional_dygraph_context()

    def functional_paddle_imperative_dygraph_context(self):
182 183 184
        self.assertFalse(paddle.in_dynamic_mode())
        paddle.disable_static()
        self.assertTrue(paddle.in_dynamic_mode())
185
        np_inp = np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32)
Z
Zhou Wei 已提交
186
        var_inp = paddle.to_tensor(np_inp)
187 188 189 190 191
        mlp = MLP(input_size=2)
        out = mlp(var_inp)
        dy_out1 = out.numpy()
        out.backward()
        dy_grad1 = mlp._linear1.weight.gradient()
192 193 194 195
        paddle.enable_static()
        self.assertFalse(paddle.in_dynamic_mode())
        paddle.disable_static()
        self.assertTrue(paddle.in_dynamic_mode())
Z
Zhou Wei 已提交
196
        var_inp = paddle.to_tensor(np_inp)
197 198 199 200 201 202 203
        mlp = MLP(input_size=2)
        out = mlp(var_inp)
        dy_out2 = out.numpy()
        out.backward()
        dy_grad2 = mlp._linear1.weight.gradient()
        paddle.enable_static()
        self.assertFalse(paddle.in_dynamic_mode())
204 205
        np.testing.assert_array_equal(dy_out1, dy_out2)
        np.testing.assert_array_equal(dy_grad1, dy_grad2)
206

207 208 209 210 211 212
    def test_functional_paddle_imperative_dygraph_context(self):
        with _test_eager_guard():
            self.functional_paddle_imperative_dygraph_context()
        self.functional_paddle_imperative_dygraph_context()

    def func_isinstance(self):
213 214 215
        var = fluid.layers.data(shape=[1], name='x', dtype='float32')
        self.assertTrue(isinstance(var, fluid.Variable))
        with fluid.dygraph.guard():
J
Jiabin Yang 已提交
216
            if not _in_legacy_dygraph():
217
                var_base = paddle.to_tensor(np.array([3, 4, 5]))
218
                self.assertTrue(isinstance(var_base, core.eager.Tensor))
219 220 221 222 223 224 225 226 227
            else:
                var_base = paddle.to_tensor(np.array([3, 4, 5]))
                self.assertTrue(isinstance(var_base, core.VarBase))
                self.assertTrue(isinstance(var_base, fluid.Variable))

    def test_isinstance(self):
        with _test_eager_guard():
            self.func_isinstance()
        self.func_isinstance()
228

229
    def func_create_varbase(self):
230 231
        x = np.ones([2, 2], np.float32)
        y = np.zeros([3, 3], np.float32)
232 233
        t = fluid.Tensor()
        t.set(x, fluid.CPUPlace())
J
Jiabin Yang 已提交
234
        if not _in_legacy_dygraph():
235 236 237
            egr_tmp = fluid.core.eager.Tensor(
                value=x, place=fluid.core.CPUPlace()
            )
238
            egr_tmp2 = fluid.core.eager.Tensor(y, fluid.core.CPUPlace())
239
            egr_tmp3 = paddle.to_tensor(x)
240
            egr_tmp4 = fluid.core.eager.Tensor(y)
J
Jiabin Yang 已提交
241
            egr_tmp5 = fluid.core.eager.Tensor(value=x)
242
            egr_tmp6 = fluid.core.eager.Tensor(t)
243

244 245 246 247 248 249
            np.testing.assert_array_equal(x, egr_tmp.numpy())
            np.testing.assert_array_equal(y, egr_tmp2.numpy())
            np.testing.assert_array_equal(x, egr_tmp3.numpy())
            np.testing.assert_array_equal(y, egr_tmp4.numpy())
            np.testing.assert_array_equal(x, egr_tmp5.numpy())
            np.testing.assert_array_equal(x, egr_tmp6.numpy())
250
        else:
251 252
            tmp = fluid.core.VarBase(value=x, place=fluid.core.CPUPlace())
            tmp2 = fluid.core.VarBase(y, fluid.core.CPUPlace())
253
            tmp3 = paddle.to_tensor(x)
254 255
            tmp4 = fluid.core.VarBase(y)
            tmp5 = fluid.core.VarBase(value=x)
256
            tmp6 = fluid.core.VarBase(t)
257

258 259 260 261 262 263
            np.testing.assert_array_equal(x, tmp.numpy())
            np.testing.assert_array_equal(y, tmp2.numpy())
            np.testing.assert_array_equal(x, tmp3.numpy())
            np.testing.assert_array_equal(y, tmp4.numpy())
            np.testing.assert_array_equal(x, tmp5.numpy())
            np.testing.assert_array_equal(x, tmp6.numpy())
264

265 266 267 268 269 270
    def test_create_varbase(self):
        with fluid.dygraph.guard():
            with _test_eager_guard():
                self.func_create_varbase()
            self.func_create_varbase()

271 272 273 274
    def test_no_grad_guard(self):
        data = np.array([[2, 3], [4, 5]]).astype('float32')
        with fluid.dygraph.guard():
            l0 = fluid.Linear(2, 2)
275
            self.assertIsNone(l0.weight._grad_ivar())
276 277 278 279 280
            l1 = fluid.Linear(2, 2)
            with fluid.dygraph.no_grad():
                self.assertTrue(l1.weight.stop_gradient is False)
                tmp = l1.weight * 2
                self.assertTrue(tmp.stop_gradient)
281
            x = paddle.to_tensor(data)
282
            y = paddle.add(l0(x), tmp)
283 284 285
            o = l1(y)
            o.backward()

286 287
            self.assertIsNone(tmp._grad_ivar())
            self.assertIsNotNone(l0.weight._grad_ivar())
288

289 290 291 292
    def test_paddle_imperative_no_grad_guard(self):
        data = np.array([[2, 3], [4, 5]]).astype('float32')
        with fluid.dygraph.guard():
            l0 = fluid.Linear(2, 2)
293
            self.assertIsNone(l0.weight._grad_ivar())
294
            l1 = fluid.Linear(2, 2)
295
            with paddle.no_grad():
296 297
                self.assertTrue(l1.weight.stop_gradient is False)
                tmp = l1.weight * 2
298
                self.assertTrue(tmp.stop_gradient)
299
            x = paddle.to_tensor(data)
300
            y = paddle.add(l0(x), tmp)
301 302 303
            o = l1(y)
            o.backward()

304 305
            self.assertIsNone(tmp._grad_ivar())
            self.assertIsNotNone(l0.weight._grad_ivar())
306

307 308 309 310
    def test_paddle_imperative_set_grad_enabled(self):
        data = np.array([[2, 3], [4, 5]]).astype('float32')
        with fluid.dygraph.guard():
            l0 = fluid.Linear(2, 2)
311
            self.assertIsNone(l0.weight._grad_ivar())
312 313 314 315 316 317 318 319
            l1 = fluid.Linear(2, 2)
            with paddle.set_grad_enabled(False):
                self.assertTrue(l1.weight.stop_gradient is False)
                tmp = l1.weight * 2
                with paddle.set_grad_enabled(True):
                    tmp2 = l1.weight * 2
                self.assertTrue(tmp.stop_gradient)
                self.assertTrue(tmp2.stop_gradient is False)
320
            x = paddle.to_tensor(data)
321
            y = paddle.add(l0(x), tmp2)
322 323 324
            o = l1(y)
            o.backward()

325 326 327
            self.assertIsNone(tmp._grad_ivar())
            self.assertIsNotNone(tmp2._grad_ivar())
            self.assertIsNotNone(l0.weight._grad_ivar())
328

W
wuhuanzhou 已提交
329 330 331 332 333 334 335
    def test_paddle_imperative_is_grad_enabled(self):
        with fluid.dygraph.guard():
            with paddle.set_grad_enabled(False):
                self.assertTrue(paddle.is_grad_enabled() is False)
                with paddle.set_grad_enabled(True):
                    self.assertTrue(paddle.is_grad_enabled())

336
    def func_sum_op(self):
M
minqiyang 已提交
337
        x = np.ones([2, 2], np.float32)
L
lujun 已提交
338
        with fluid.dygraph.guard():
M
minqiyang 已提交
339 340
            inputs = []
            for _ in range(10):
341
                tmp = paddle.to_tensor(x)
342 343
                tmp.stop_gradient = False
                inputs.append(tmp)
344
            ret = paddle.add_n(inputs)
M
minqiyang 已提交
345
            loss = fluid.layers.reduce_sum(ret)
L
lujun 已提交
346
            loss.backward()
347 348 349
        with fluid.dygraph.guard():
            inputs2 = []
            for _ in range(10):
350
                tmp = paddle.to_tensor(x)
351 352
                tmp.stop_gradient = False
                inputs2.append(tmp)
353
            ret2 = paddle.add_n(inputs2)
354
            loss2 = fluid.layers.reduce_sum(ret2)
355 356
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            loss2.backward()
357

358 359 360
            np.testing.assert_allclose(ret.numpy(), x * 10, rtol=1e-05)
            np.testing.assert_allclose(inputs[0].gradient(), x, rtol=1e-05)
            np.testing.assert_allclose(ret2.numpy(), x * 10, rtol=1e-05)
361
            a = inputs2[0].gradient()
362
            np.testing.assert_allclose(inputs2[0].gradient(), x, rtol=1e-05)
M
minqiyang 已提交
363

364 365 366 367 368
    def test_sum_op(self):
        with _test_eager_guard():
            self.func_sum_op()
        self.func_sum_op()

369
    def func_empty_var(self):
370 371 372
        with fluid.dygraph.guard():
            cur_program = fluid.Program()
            cur_block = cur_program.current_block()
373
            # Normally, we don't allow tensor with -1 shape being created in dygraph mode, this test is not good.
J
Jiabin Yang 已提交
374
            if _in_legacy_dygraph():
375 376 377
                new_variable = cur_block.create_var(
                    name="X", shape=[-1, 23, 48], dtype='float32'
                )
378
            else:
379 380 381
                new_variable = cur_block.create_var(
                    name="X", shape=[1, 23, 48], dtype='float32'
                )
382 383 384
            try:
                new_variable.numpy()
            except Exception as e:
385
                assert type(e) == ValueError
386 387 388 389

            try:
                new_variable.backward()
            except Exception as e:
390
                assert type(e) == core.EnforceNotMet
J
Jiabin Yang 已提交
391 392 393 394
            try:
                new_variable.clear_gradient()
            except Exception as e:
                assert type(e) == core.EnforceNotMet
395

396 397 398 399
    def test_empty_var(self):
        with _test_eager_guard():
            self.func_empty_var()
        self.func_empty_var()
400

401
    def func_empty_grad(self):
402 403
        with fluid.dygraph.guard():
            x = np.ones([2, 2], np.float32)
404
            new_var = paddle.to_tensor(x)
405
            self.assertIsNone(new_var.gradient())
J
Jiabin Yang 已提交
406 407 408 409
            try:
                new_var.clear_gradient()
            except Exception as e:
                assert type(e) == core.EnforceNotMet
410 411 412 413

        with fluid.dygraph.guard():
            cur_program = fluid.Program()
            cur_block = cur_program.current_block()
414
            # Normally, we don't allow tensor with -1 shape being created in dygraph mode, this test is not good.
J
Jiabin Yang 已提交
415
            if _in_legacy_dygraph():
416 417 418
                new_variable = cur_block.create_var(
                    name="X", shape=[-1, 23, 48], dtype='float32'
                )
419
            else:
420 421 422
                new_variable = cur_block.create_var(
                    name="X", shape=[1, 23, 48], dtype='float32'
                )
423 424 425 426 427
            try:
                new_variable.gradient()
            except Exception as e:
                assert type(e) == ValueError

428 429 430 431 432 433
    def test_empty_grad(self):
        with _test_eager_guard():
            self.func_empty_grad()
        self.func_empty_grad()

    def func_set_persistable(self):
434 435
        with fluid.dygraph.guard():
            x = np.ones([2, 2], np.float32)
436
            new_var = paddle.to_tensor(x)
437 438
            self.assertFalse(new_var.persistable)
            new_var.persistable = True
439
            self.assertTrue(new_var.persistable)
440

441 442 443 444 445 446
    def test_set_persistable(self):
        with _test_eager_guard():
            self.func_set_persistable()
        self.func_set_persistable()

    def func_layer(self):
L
lujun 已提交
447
        with fluid.dygraph.guard():
448
            l = fluid.Layer("l")
M
minqiyang 已提交
449 450
            self.assertRaises(NotImplementedError, l.forward, [])

451 452 453 454 455 456
    def test_layer(self):
        with _test_eager_guard():
            self.func_layer()
        self.func_layer()

    def func_layer_in_out(self):
M
minqiyang 已提交
457
        np_inp = np.array([1.0, 2.0, -1.0], dtype=np.float32)
L
lujun 已提交
458
        with fluid.dygraph.guard():
459
            var_inp = paddle.to_tensor(np_inp)
460
            var_inp.stop_gradient = False
461
            l = MyLayer()
M
minqiyang 已提交
462 463
            x = l(var_inp)[0]
            self.assertIsNotNone(x)
464
            dy_out = x.numpy()
L
lujun 已提交
465
            x.backward()
466
            dy_grad = l._x_for_debug.gradient()
M
minqiyang 已提交
467

468
        with fluid.dygraph.guard():
469
            var_inp2 = paddle.to_tensor(np_inp)
470
            var_inp2.stop_gradient = False
471
            l2 = MyLayer()
472 473 474
            x2 = l2(var_inp2)[0]
            self.assertIsNotNone(x2)
            dy_out2 = x2.numpy()
475 476
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            x2.backward()
477 478
            dy_grad2 = l2._x_for_debug.gradient()

M
minqiyang 已提交
479
        with new_program_scope():
480 481 482
            inp = fluid.layers.data(
                name="inp", shape=[3], append_batch_size=False
            )
483
            l = MyLayer()
M
minqiyang 已提交
484 485
            x = l(inp)[0]
            param_grads = fluid.backward.append_backward(
486 487 488 489 490 491 492
                x, parameter_list=[l._x_for_debug.name]
            )[0]
            exe = fluid.Executor(
                fluid.CPUPlace()
                if not core.is_compiled_with_cuda()
                else fluid.CUDAPlace(0)
            )
M
minqiyang 已提交
493 494 495

            static_out, static_grad = exe.run(
                feed={inp.name: np_inp},
496 497
                fetch_list=[x.name, param_grads[1].name],
            )
M
minqiyang 已提交
498

499 500 501 502
        np.testing.assert_array_equal(dy_out, static_out)
        np.testing.assert_array_equal(dy_grad, static_grad)
        np.testing.assert_array_equal(dy_out2, static_out)
        np.testing.assert_array_equal(dy_grad2, static_grad)
M
minqiyang 已提交
503

504
    def test_layer_in_out(self):
505
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": True})
506 507 508
        with _test_eager_guard():
            self.func_layer_in_out()
        self.func_layer_in_out()
509
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": False})
510 511

    def func_mlp(self):
M
minqiyang 已提交
512
        np_inp = np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32)
L
lujun 已提交
513
        with fluid.dygraph.guard():
514
            var_inp = paddle.to_tensor(np_inp)
515
            mlp = MLP(input_size=2)
M
minqiyang 已提交
516
            out = mlp(var_inp)
517
            dy_out = out.numpy()
L
lujun 已提交
518
            out.backward()
519
            dy_grad = mlp._linear1.weight.gradient()
M
minqiyang 已提交
520

521
        with fluid.dygraph.guard():
522
            var_inp2 = paddle.to_tensor(np_inp)
523
            mlp2 = MLP(input_size=2)
524 525
            out2 = mlp2(var_inp2)
            dy_out2 = out2.numpy()
526 527
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            out2.backward()
528
            dy_grad2 = mlp2._linear1.weight.gradient()
529

M
minqiyang 已提交
530
        with new_program_scope():
531 532 533
            inp = fluid.layers.data(
                name="inp", shape=[2, 2], append_batch_size=False
            )
534
            mlp = MLP(input_size=2)
M
minqiyang 已提交
535 536
            out = mlp(inp)
            param_grads = fluid.backward.append_backward(
537 538 539 540 541 542 543
                out, parameter_list=[mlp._linear1.weight.name]
            )[0]
            exe = fluid.Executor(
                fluid.CPUPlace()
                if not core.is_compiled_with_cuda()
                else fluid.CUDAPlace(0)
            )
M
minqiyang 已提交
544 545 546 547
            exe.run(fluid.default_startup_program())

            static_out, static_grad = exe.run(
                feed={inp.name: np_inp},
548 549
                fetch_list=[out.name, param_grads[1].name],
            )
M
minqiyang 已提交
550

551 552 553 554
        np.testing.assert_allclose(dy_out, static_out, rtol=1e-05)
        np.testing.assert_allclose(dy_grad, static_grad, rtol=1e-05)
        np.testing.assert_allclose(dy_out2, static_out, rtol=1e-05)
        np.testing.assert_allclose(dy_grad2, static_grad, rtol=1e-05)
M
minqiyang 已提交
555 556

        params = mlp.parameters(True)
557 558 559 560
        self.assertEqual("linear_0.w_0", params[0].name)
        self.assertEqual("linear_0.b_0", params[1].name)
        self.assertEqual("linear_1.w_0", params[2].name)
        self.assertEqual("linear_1.b_0", params[3].name)
M
minqiyang 已提交
561 562
        self.assertEqual(len(params), 4)

J
Jiabin Yang 已提交
563
        sublayers = mlp.sublayers()
564 565
        self.assertEqual(mlp._linear1, sublayers[0])
        self.assertEqual(mlp._linear2, sublayers[1])
M
minqiyang 已提交
566 567
        self.assertEqual(len(sublayers), 2)

568 569 570 571 572
    def test_mlp(self):
        with _test_eager_guard():
            self.func_mlp()
        self.func_mlp()

573 574 575
    def test_gradient_accumulation(self):
        def test_single_api(sort_sum_gradient):
            fluid.set_flags({'FLAGS_sort_sum_gradient': sort_sum_gradient})
576
            x = paddle.to_tensor(5.0, stop_gradient=False)
577 578 579
            for i in range(10):
                y = paddle.pow(x, 4.0)
                y.backward()
580
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
581
            x.clear_gradient()
582
            self.assertEqual(x.grad.numpy(), 0.0)
583
            for i in range(10):
584 585
                y = paddle.pow(x, 4.0)
                y.backward()
586
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
587
            x.clear_grad()
588
            self.assertEqual(x.grad.numpy(), 0.0)
589 590 591

        def test_simple_net(sort_sum_gradient):
            fluid.set_flags({'FLAGS_sort_sum_gradient': sort_sum_gradient})
592 593 594
            x = paddle.to_tensor(5.0, stop_gradient=False)
            y = paddle.to_tensor(2.0, stop_gradient=False)
            z = paddle.to_tensor(3.0, stop_gradient=False)
595 596 597 598

            def fun(x, y, z):
                loss1 = x * x * y
                loss2 = x * z
599 600
                loss1.backward(retain_graph=True)
                loss2.backward(retain_graph=True)
601 602 603
                np.testing.assert_array_equal(x.grad.numpy(), [23.0])
                np.testing.assert_array_equal(y.grad.numpy(), [25.0])
                np.testing.assert_array_equal(z.grad.numpy(), [5.0])
604 605 606 607
                x.clear_grad()
                y.clear_grad()
                z.clear_grad()

608 609
                dx = paddle.grad([loss1], x, create_graph=True)[0]
                loss = loss1 + loss2 + dx
610
                # loss = x*x*y + x*z + 2*x*y
611 612 613 614
                return loss

            loss = fun(x, y, z)
            loss.backward(retain_graph=True)
615
            # x.grad = 2*x*y + z + 2*y = 27
616
            np.testing.assert_array_equal(x.grad.numpy(), [27])
617 618

            loss.backward(retain_graph=True)
619
            np.testing.assert_array_equal(x.grad.numpy(), [54])
620 621

            loss.backward()
622
            np.testing.assert_array_equal(x.grad.numpy(), [81])
623 624 625 626 627 628 629 630 631

            with self.assertRaises(RuntimeError):
                loss.backward()

            loss1 = x * x * y
            loss2 = x * z
            dx = paddle.grad([loss1], x, create_graph=True)[0]
            loss = loss1 + loss2 + dx
            loss.backward()
632 633
            np.testing.assert_array_equal(dx.grad.numpy(), [1])
            np.testing.assert_array_equal(x.grad.numpy(), [108])
634 635 636 637 638 639 640 641 642

        def test_mlp(sort_sum_gradient):
            fluid.set_flags({'FLAGS_sort_sum_gradient': sort_sum_gradient})
            input_size = 5
            paddle.seed(1)
            mlp1 = MLP(input_size=input_size)
            # generate the gradient of each step
            mlp2 = MLP(input_size=input_size)

643 644 645 646
            expected_weight1_grad = 0.0
            expected_bias1_grad = 0.0
            expected_weight2_grad = 0.0
            expected_bias2_grad = 0.0
647

648
            for batch_id in range(100):
649 650 651 652
                x = paddle.uniform([10, input_size])
                detach_x = x.detach()
                clear_loss = mlp2(detach_x)
                clear_loss.backward()
653 654 655 656 657 658 659 660 661 662 663 664
                expected_weight1_grad = (
                    expected_weight1_grad + mlp2._linear1.weight.grad.numpy()
                )
                expected_bias1_grad = (
                    expected_bias1_grad + mlp2._linear1.bias.grad.numpy()
                )
                expected_weight2_grad = (
                    expected_weight2_grad + mlp2._linear2.weight.grad.numpy()
                )
                expected_bias2_grad = (
                    expected_bias2_grad + mlp2._linear2.bias.grad.numpy()
                )
665 666 667 668

                loss = mlp1(x)
                loss.backward()

669
                np.testing.assert_array_equal(loss.grad.numpy(), [1])
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
                np.testing.assert_allclose(
                    mlp1._linear1.weight.grad.numpy(),
                    expected_weight1_grad,
                    rtol=1e-05,
                )
                np.testing.assert_allclose(
                    mlp1._linear1.bias.grad.numpy(),
                    expected_bias1_grad,
                    rtol=1e-05,
                )
                np.testing.assert_allclose(
                    mlp1._linear2.weight.grad.numpy(),
                    expected_weight2_grad,
                    rtol=1e-05,
                )
                np.testing.assert_allclose(
                    mlp1._linear2.bias.grad.numpy(),
                    expected_bias2_grad,
                    rtol=1e-05,
                )
690 691

                mlp2.clear_gradients()
692
                np.testing.assert_array_equal(clear_loss.grad.numpy(), [1])
693
                if ((batch_id + 1) % 10) % 2 == 0:
694
                    mlp1.clear_gradients()
695 696 697 698
                    expected_weight1_grad = 0.0
                    expected_bias1_grad = 0.0
                    expected_weight2_grad = 0.0
                    expected_bias2_grad = 0.0
699 700 701
                elif ((batch_id + 1) % 10) % 2 == 1:
                    mlp1.clear_gradients()
                    mlp1._linear1.weight._set_grad_ivar(
702 703
                        paddle.ones([input_size, 3])
                    )
704
                    mlp1._linear2.weight._set_grad_ivar(paddle.ones([3, 4]))
705 706 707 708
                    expected_weight1_grad = 1.0
                    expected_bias1_grad = 0.0
                    expected_weight2_grad = 1.0
                    expected_bias2_grad = 0.0
709 710 711 712 713 714 715 716 717

        with fluid.dygraph.guard():
            test_single_api(False)
            test_single_api(True)
            test_simple_net(False)
            test_simple_net(True)
            test_mlp(False)
            test_mlp(True)

718
    def func_dygraph_vs_static(self):
719 720
        np_inp1 = np.random.rand(4, 3, 3)
        np_inp2 = np.random.rand(4, 3, 3)
X
Xin Pan 已提交
721 722 723

        # dynamic graph
        with fluid.dygraph.guard():
724 725
            inp1 = paddle.to_tensor(np_inp1)
            inp2 = paddle.to_tensor(np_inp2)
726
            if np.sum(np_inp1) < np.sum(np_inp2):
X
Xin Pan 已提交
727 728 729
                x = fluid.layers.elementwise_add(inp1, inp2)
            else:
                x = fluid.layers.elementwise_sub(inp1, inp2)
L
lujun 已提交
730
            dygraph_result = x.numpy()
X
Xin Pan 已提交
731 732 733

        # static graph
        with new_program_scope():
734 735 736 737 738 739
            inp_data1 = fluid.layers.data(
                name='inp1', shape=[3, 3], dtype=np.float32
            )
            inp_data2 = fluid.layers.data(
                name='inp2', shape=[3, 3], dtype=np.float32
            )
X
Xin Pan 已提交
740 741

            a = fluid.layers.expand(
742 743 744 745 746
                fluid.layers.reshape(
                    fluid.layers.reduce_sum(inp_data1), [1, 1]
                ),
                [4, 1],
            )
X
Xin Pan 已提交
747
            b = fluid.layers.expand(
748 749 750 751 752
                fluid.layers.reshape(
                    fluid.layers.reduce_sum(inp_data2), [1, 1]
                ),
                [4, 1],
            )
X
Xin Pan 已提交
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
            cond = fluid.layers.less_than(x=a, y=b)

            ie = fluid.layers.IfElse(cond)
            with ie.true_block():
                d1 = ie.input(inp_data1)
                d2 = ie.input(inp_data2)
                d3 = fluid.layers.elementwise_add(d1, d2)
                ie.output(d3)

            with ie.false_block():
                d1 = ie.input(inp_data1)
                d2 = ie.input(inp_data2)
                d3 = fluid.layers.elementwise_sub(d1, d2)
                ie.output(d3)
            out = ie()

769 770 771 772 773 774 775 776 777 778
            exe = fluid.Executor(
                fluid.CPUPlace()
                if not core.is_compiled_with_cuda()
                else fluid.CUDAPlace(0)
            )
            static_result = exe.run(
                fluid.default_main_program(),
                feed={'inp1': np_inp1, 'inp2': np_inp2},
                fetch_list=out,
            )[0]
779
        np.testing.assert_allclose(dygraph_result, static_result, rtol=1e-05)
X
Xin Pan 已提交
780

781 782 783 784 785 786
    def test_dygraph_vs_static(self):
        with _test_eager_guard():
            self.func_dygraph_vs_static()
        self.func_dygraph_vs_static()

    def func_rnn(self):
787 788 789 790 791 792 793 794
        np_inp = np.array(
            [
                [1.0, 2.0, 3.0],
                [4.0, 5.0, 6.0],
                [7.0, 8.0, 9.0],
                [10.0, 11.0, 12.0],
            ]
        )
M
minqiyang 已提交
795 796
        np_inp = np_inp.reshape((1, 4, 3))
        np_inp = np_inp.astype(np.float32)
L
lujun 已提交
797
        with fluid.dygraph.guard():
798
            var_inp = paddle.to_tensor(np_inp)
M
minqiyang 已提交
799
            var_inp = fluid.layers.reshape(var_inp, shape=[1, 4, 3])
800
            simple_rnn = SimpleRNN()
M
minqiyang 已提交
801
            outs, pre_hiddens = simple_rnn.forward(var_inp)
802
            dy_out = outs[3].numpy()
L
lujun 已提交
803
            outs[3].backward()
804 805 806
            dy_grad_h2o = simple_rnn._cell._h2o_w.gradient()
            dy_grad_h2h = simple_rnn._cell._h2h_w.gradient()
            dy_grad_i2h = simple_rnn._cell._i2h_w.gradient()
M
minqiyang 已提交
807

808
        with fluid.dygraph.guard():
809
            var_inp2 = paddle.to_tensor(np_inp)
810
            var_inp2 = fluid.layers.reshape(var_inp2, shape=[1, 4, 3])
811
            simple_rnn2 = SimpleRNN()
812 813
            outs2, pre_hiddens2 = simple_rnn2.forward(var_inp2)
            dy_out2 = outs2[3].numpy()
814 815
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            outs2[3].backward()
816 817 818 819
            dy_grad_h2o2 = simple_rnn2._cell._h2o_w.gradient()
            dy_grad_h2h2 = simple_rnn2._cell._h2h_w.gradient()
            dy_grad_i2h2 = simple_rnn2._cell._i2h_w.gradient()

M
minqiyang 已提交
820
        with new_program_scope():
821 822 823
            inp = fluid.layers.data(
                name="inp", shape=[1, 4, 3], append_batch_size=False
            )
824
            simple_rnn = SimpleRNN()
M
minqiyang 已提交
825 826 827 828
            outs, pre_hiddens = simple_rnn(inp)
            param_grads = fluid.backward.append_backward(outs[3])
            exe = fluid.Executor(fluid.CPUPlace())
            exe.run(fluid.default_startup_program())
829 830 831 832 833 834
            (
                static_out,
                static_grad_h2o,
                static_grad_h2h,
                static_grad_i2h,
            ) = exe.run(
M
minqiyang 已提交
835 836
                feed={inp.name: np_inp},
                fetch_list=[
837 838 839 840 841 842
                    outs[3].name,
                    param_grads[0][1].name,
                    param_grads[1][1].name,
                    param_grads[2][1].name,
                ],
            )
843

844 845 846 847 848 849 850 851
        np.testing.assert_array_equal(dy_out, static_out)
        np.testing.assert_array_equal(dy_grad_h2o, static_grad_h2o)
        np.testing.assert_array_equal(dy_grad_h2h, static_grad_h2h)
        np.testing.assert_array_equal(dy_grad_i2h, static_grad_i2h)
        np.testing.assert_array_equal(dy_out2, static_out)
        np.testing.assert_array_equal(dy_grad_h2o2, static_grad_h2o)
        np.testing.assert_array_equal(dy_grad_h2h2, static_grad_h2h)
        np.testing.assert_array_equal(dy_grad_i2h2, static_grad_i2h)
852 853 854 855 856

    def test_rnn(self):
        with _test_eager_guard():
            self.func_rnn()
        self.func_rnn()
M
minqiyang 已提交
857

858
    def func_layer_attrs(self):
859 860 861 862 863 864
        layer = fluid.dygraph.Layer("test")
        layer.test_attr = 1
        self.assertFalse(hasattr(layer, "whatever"))
        self.assertTrue(hasattr(layer, "test_attr"))
        self.assertEqual(layer.test_attr, 1)

865 866 867 868 869 870 871 872 873 874 875 876 877
        my_layer = MyLayer()
        my_layer.w1 = my_layer.create_parameter([3, 3])
        my_layer.add_parameter('w2', None)
        self.assertEqual(len(my_layer.parameters()), 1)
        self.assertRaises(TypeError, my_layer.__setattr__, 'w1', 'str')
        my_layer.w1 = None
        self.assertEqual(len(my_layer.parameters()), 0)
        my_layer.l1 = fluid.dygraph.Linear(3, 3)
        self.assertEqual(len(my_layer.sublayers()), 1)
        self.assertRaises(TypeError, my_layer.__setattr__, 'l1', 'str')
        my_layer.l1 = None
        self.assertEqual(len(my_layer.sublayers()), 0)

878 879 880 881 882
    def test_layer_attrs(self):
        with _test_eager_guard():
            self.func_layer_attrs()
        self.func_layer_attrs()

883

884
class TestDygraphUtils(unittest.TestCase):
885
    def func_append_activation_in_dygraph_exception(self):
886 887 888 889 890 891
        with new_program_scope():
            np_inp = np.random.random(size=(10, 20, 30)).astype(np.float32)
            a = fluid.layers.data("a", [10, 20])
            func = dygraph_utils._append_activation_in_dygraph
            self.assertRaises(AssertionError, func, a, act="sigmoid")

892 893 894 895 896 897
    def test_append_activation_in_dygraph_exception(self):
        with _test_eager_guard():
            self.func_append_activation_in_dygraph_exception()
        self.func_append_activation_in_dygraph_exception()

    def func_append_activation_in_dygraph1(self):
898 899 900
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_activation_in_dygraph
        with fluid.dygraph.guard():
901
            a = paddle.to_tensor(a_np)
902 903
            res1 = func(a, act="hard_sigmoid")
            res2 = fluid.layers.hard_sigmoid(a)
904
            np.testing.assert_array_equal(res1.numpy(), res2.numpy())
905

906 907 908 909 910 911
    def test_append_activation_in_dygraph1(self):
        with _test_eager_guard():
            self.func_append_activation_in_dygraph1()
        self.func_append_activation_in_dygraph1()

    def func_append_activation_in_dygraph2(self):
912 913 914
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_activation_in_dygraph
        with fluid.dygraph.guard():
915
            a = paddle.to_tensor(a_np)
916
            res1 = func(a, act="sigmoid", use_mkldnn=True, use_cudnn=True)
917
            res2 = paddle.nn.functional.sigmoid(a)
918
            np.testing.assert_allclose(res1.numpy(), res2.numpy(), rtol=1e-05)
919

920 921 922 923 924 925
    def test_append_activation_in_dygraph2(self):
        with _test_eager_guard():
            self.func_append_activation_in_dygraph2()
        self.func_append_activation_in_dygraph2()

    def func_append_activation_in_dygraph3(self):
926 927 928 929
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        helper = LayerObjectHelper(fluid.unique_name.generate("test"))
        func = helper.append_activation
        with fluid.dygraph.guard():
930
            a = paddle.to_tensor(a_np)
931
            res1 = func(a, act="sigmoid", use_cudnn=True)
932
            res2 = paddle.nn.functional.sigmoid(a)
933
            np.testing.assert_array_equal(res1.numpy(), res2.numpy())
934

935 936 937 938 939 940
    def test_append_activation_in_dygraph3(self):
        with _test_eager_guard():
            self.func_append_activation_in_dygraph3()
        self.func_append_activation_in_dygraph3()

    def func_append_activation_in_dygraph_use_mkldnn(self):
941
        a_np = np.random.uniform(-2, 2, (10, 20, 30)).astype(np.float32)
942 943 944
        helper = LayerHelper(
            fluid.unique_name.generate("test"), act="relu", use_mkldnn=True
        )
945 946
        func = helper.append_activation
        with fluid.dygraph.guard():
947
            a = paddle.to_tensor(a_np)
948 949
            res1 = func(a)
            res2 = fluid.layers.relu(a)
950
            np.testing.assert_array_equal(res1.numpy(), res2.numpy())
951

952 953 954 955 956 957
    def test_append_activation_in_dygraph_use_mkldnn(self):
        with _test_eager_guard():
            self.func_append_activation_in_dygraph_use_mkldnn()
        self.func_append_activation_in_dygraph_use_mkldnn()

    def func_append_activation_in_dygraph_global_use_mkldnn(self):
958 959 960
        a_np = np.random.uniform(-2, 2, (10, 20, 30)).astype(np.float32)
        helper = LayerHelper(fluid.unique_name.generate("test"), act="relu")
        func = helper.append_activation
961
        with fluid.dygraph.guard(fluid.core.CPUPlace()):
962
            a = paddle.to_tensor(a_np)
963 964 965 966 967 968
            fluid.set_flags({'FLAGS_use_mkldnn': True})
            try:
                res1 = func(a)
            finally:
                fluid.set_flags({'FLAGS_use_mkldnn': False})
            res2 = fluid.layers.relu(a)
969
        np.testing.assert_array_equal(res1.numpy(), res2.numpy())
970

971 972 973 974 975 976
    def test_append_activation_in_dygraph_global_use_mkldnn(self):
        with _test_eager_guard():
            self.func_append_activation_in_dygraph_global_use_mkldnn()
        self.func_append_activation_in_dygraph_global_use_mkldnn()

    def func_append_bias_in_dygraph_exception(self):
977 978 979 980 981 982
        with new_program_scope():
            np_inp = np.random.random(size=(10, 20, 30)).astype(np.float32)
            a = fluid.layers.data("a", [10, 20])
            func = dygraph_utils._append_bias_in_dygraph
            self.assertRaises(AssertionError, func, a)

983 984 985 986 987 988
    def test_append_bias_in_dygraph_exception(self):
        with _test_eager_guard():
            self.func_append_bias_in_dygraph_exception()
        self.func_append_bias_in_dygraph_exception()

    def func_append_bias_in_dygraph(self):
989 990 991
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_bias_in_dygraph
        with fluid.dygraph.guard():
992
            a = paddle.to_tensor(a_np)
993
            res1 = func(a, bias=a)
994
            res2 = paddle.add(a, a)
995
            np.testing.assert_array_equal(res1.numpy(), res2.numpy())
996

997 998 999 1000 1001
    def test_append_bias_in_dygraph(self):
        with _test_eager_guard():
            self.func_append_bias_in_dygraph()
        self.func_append_bias_in_dygraph()

1002

1003
class TestDygraphGuardWithError(unittest.TestCase):
1004
    def func_without_guard(self):
1005
        with fluid.dygraph.guard():
1006
            x = paddle.to_tensor(np.zeros([10, 10]))
1007 1008 1009
        with self.assertRaisesRegexp(
            TypeError, "Please use `with fluid.dygraph.guard()"
        ):
1010 1011
            y = fluid.layers.matmul(x, x)

1012 1013 1014 1015 1016
    def test_without_guard(self):
        with _test_eager_guard():
            self.func_without_guard()
        self.func_without_guard()

1017

1018
class TestMetaclass(unittest.TestCase):
1019
    def func_metaclass(self):
1020 1021
        self.assertEqual(type(MyLayer).__name__, 'type')
        self.assertNotEqual(type(MyLayer).__name__, 'pybind11_type')
J
Jiabin Yang 已提交
1022
        if not _in_legacy_dygraph():
1023
            self.assertEqual(
1024 1025
                type(paddle.fluid.core.eager.Tensor).__name__, 'type'
            )
1026 1027
        else:
            self.assertEqual(
1028 1029
                type(paddle.fluid.core.VarBase).__name__, 'pybind11_type'
            )
1030 1031 1032 1033 1034

    def test_metaclass(self):
        with _test_eager_guard():
            self.func_metaclass()
        self.func_metaclass()
1035 1036


1037
if __name__ == '__main__':
1038
    paddle.enable_static()
1039
    unittest.main()