test_imperative_basic.py 39.1 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

31 32
    def __init__(self):
        super(MyLayer, self).__init__()
33 34

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


42
class MLP(fluid.Layer):
43

44 45 46 47 48
    def __init__(self, input_size):
        super(MLP, self).__init__()
        self._linear1 = Linear(
            input_size,
            3,
49 50 51 52
            param_attr=fluid.ParamAttr(initializer=fluid.initializer.Constant(
                value=0.1)),
            bias_attr=fluid.ParamAttr(initializer=fluid.initializer.Constant(
                value=0.1)))
53 54 55
        self._linear2 = Linear(
            3,
            4,
56 57 58 59
            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 已提交
60 61

    def forward(self, inputs):
62 63
        x = self._linear1(inputs)
        x = self._linear2(x)
X
Xin Pan 已提交
64 65 66 67
        x = fluid.layers.reduce_sum(x)
        return x


68
class SimpleRNNCell(fluid.Layer):
69

70 71
    def __init__(self, step_input_size, hidden_size, output_size, param_attr):
        super(SimpleRNNCell, self).__init__()
72 73 74
        self.step_input_size = step_input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
75 76
        self._dtype = core.VarDesc.VarType.FP32
        self.param_attr = param_attr
77 78 79 80

        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 已提交
81
        self._i2h_w = None
82 83 84 85 86 87 88 89 90 91 92 93
        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)
94 95

    def forward(self, input, pre_hidden):
96 97 98
        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)
99
        hidden = self._helper.append_activation(hidden, act='tanh')
100 101 102
        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)
103 104 105
        return reduce_out, hidden


106
class SimpleRNN(fluid.Layer):
107

108 109
    def __init__(self):
        super(SimpleRNN, self).__init__()
J
JiabinYang 已提交
110 111
        self.seq_len = 4
        self._cell = SimpleRNNCell(
112
            3, 3, 3,
J
JiabinYang 已提交
113
            fluid.ParamAttr(initializer=fluid.initializer.Constant(value=0.1)))
J
JiabinYang 已提交
114 115

    def forward(self, inputs):
J
JiabinYang 已提交
116
        outs = list()
J
JiabinYang 已提交
117 118
        pre_hiddens = list()

119 120 121 122 123
        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 已提交
124
        pre_hidden = init_hidden
J
JiabinYang 已提交
125
        for i in range(self.seq_len):
126 127 128 129
            input = fluid.layers.slice(inputs,
                                       axes=[1],
                                       starts=[i],
                                       ends=[i + 1])
J
JiabinYang 已提交
130
            input = fluid.layers.reshape(input, shape=[1, 3])
J
JiabinYang 已提交
131 132
            out_softmax, pre_hidden = self._cell(input, pre_hidden)
            outs.append(out_softmax)
J
JiabinYang 已提交
133

J
JiabinYang 已提交
134
        return outs, pre_hiddens
J
JiabinYang 已提交
135 136


M
minqiyang 已提交
137
class TestImperative(unittest.TestCase):
138

139
    def functional_dygraph_context(self):
140 141 142 143
        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)
144
        var_inp = paddle.to_tensor(np_inp)
145 146 147 148 149 150 151 152 153
        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())
154
            var_inp = paddle.to_tensor(np_inp)
155 156 157 158 159 160
            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())
161 162
        np.testing.assert_array_equal(dy_out1, dy_out2)
        np.testing.assert_array_equal(dy_grad1, dy_grad2)
163

164 165 166 167 168 169
    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):
170 171 172
        self.assertFalse(paddle.in_dynamic_mode())
        paddle.disable_static()
        self.assertTrue(paddle.in_dynamic_mode())
173
        np_inp = np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32)
Z
Zhou Wei 已提交
174
        var_inp = paddle.to_tensor(np_inp)
175 176 177 178 179
        mlp = MLP(input_size=2)
        out = mlp(var_inp)
        dy_out1 = out.numpy()
        out.backward()
        dy_grad1 = mlp._linear1.weight.gradient()
180 181 182 183
        paddle.enable_static()
        self.assertFalse(paddle.in_dynamic_mode())
        paddle.disable_static()
        self.assertTrue(paddle.in_dynamic_mode())
Z
Zhou Wei 已提交
184
        var_inp = paddle.to_tensor(np_inp)
185 186 187 188 189 190 191
        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())
192 193
        np.testing.assert_array_equal(dy_out1, dy_out2)
        np.testing.assert_array_equal(dy_grad1, dy_grad2)
194

195 196 197 198 199 200
    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):
201 202 203
        var = fluid.layers.data(shape=[1], name='x', dtype='float32')
        self.assertTrue(isinstance(var, fluid.Variable))
        with fluid.dygraph.guard():
J
Jiabin Yang 已提交
204
            if not _in_legacy_dygraph():
205
                var_base = paddle.to_tensor(np.array([3, 4, 5]))
206
                self.assertTrue(isinstance(var_base, core.eager.Tensor))
207 208 209 210 211 212 213 214 215
            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()
216

217
    def func_create_varbase(self):
218 219
        x = np.ones([2, 2], np.float32)
        y = np.zeros([3, 3], np.float32)
220 221
        t = fluid.Tensor()
        t.set(x, fluid.CPUPlace())
J
Jiabin Yang 已提交
222
        if not _in_legacy_dygraph():
223 224
            egr_tmp = fluid.core.eager.Tensor(value=x,
                                              place=fluid.core.CPUPlace())
225
            egr_tmp2 = fluid.core.eager.Tensor(y, fluid.core.CPUPlace())
226
            egr_tmp3 = paddle.to_tensor(x)
227
            egr_tmp4 = fluid.core.eager.Tensor(y)
J
Jiabin Yang 已提交
228
            egr_tmp5 = fluid.core.eager.Tensor(value=x)
229
            egr_tmp6 = fluid.core.eager.Tensor(t)
230

231 232 233 234 235 236
            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())
237
        else:
238 239
            tmp = fluid.core.VarBase(value=x, place=fluid.core.CPUPlace())
            tmp2 = fluid.core.VarBase(y, fluid.core.CPUPlace())
240
            tmp3 = paddle.to_tensor(x)
241 242
            tmp4 = fluid.core.VarBase(y)
            tmp5 = fluid.core.VarBase(value=x)
243
            tmp6 = fluid.core.VarBase(t)
244

245 246 247 248 249 250
            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())
251

252 253 254 255 256 257
    def test_create_varbase(self):
        with fluid.dygraph.guard():
            with _test_eager_guard():
                self.func_create_varbase()
            self.func_create_varbase()

258 259 260 261 262 263 264 265 266 267
    def test_no_grad_guard(self):
        data = np.array([[2, 3], [4, 5]]).astype('float32')
        with fluid.dygraph.guard():
            l0 = fluid.Linear(2, 2)
            self.assertTrue(l0.weight._grad_ivar() is None)
            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)
268
            x = paddle.to_tensor(data)
269
            y = paddle.add(l0(x), tmp)
270 271 272 273 274 275
            o = l1(y)
            o.backward()

            self.assertTrue(tmp._grad_ivar() is None)
            self.assertTrue(l0.weight._grad_ivar() is not None)

276 277 278 279 280 281
    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)
            self.assertTrue(l0.weight._grad_ivar() is None)
            l1 = fluid.Linear(2, 2)
282
            with paddle.no_grad():
283 284
                self.assertTrue(l1.weight.stop_gradient is False)
                tmp = l1.weight * 2
285
                self.assertTrue(tmp.stop_gradient)
286
            x = paddle.to_tensor(data)
287
            y = paddle.add(l0(x), tmp)
288 289 290
            o = l1(y)
            o.backward()

291
            self.assertTrue(tmp._grad_ivar() is None)
292 293
            self.assertTrue(l0.weight._grad_ivar() is not None)

294 295 296 297 298 299 300 301 302 303 304 305 306
    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)
            self.assertTrue(l0.weight._grad_ivar() is None)
            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)
307
            x = paddle.to_tensor(data)
308
            y = paddle.add(l0(x), tmp2)
309 310 311 312 313 314 315
            o = l1(y)
            o.backward()

            self.assertTrue(tmp._grad_ivar() is None)
            self.assertTrue(tmp2._grad_ivar() is not None)
            self.assertTrue(l0.weight._grad_ivar() is not None)

W
wuhuanzhou 已提交
316 317 318 319 320 321 322
    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())

323
    def func_sum_op(self):
M
minqiyang 已提交
324
        x = np.ones([2, 2], np.float32)
L
lujun 已提交
325
        with fluid.dygraph.guard():
M
minqiyang 已提交
326 327
            inputs = []
            for _ in range(10):
328
                tmp = paddle.to_tensor(x)
329 330
                tmp.stop_gradient = False
                inputs.append(tmp)
331
            ret = paddle.add_n(inputs)
M
minqiyang 已提交
332
            loss = fluid.layers.reduce_sum(ret)
L
lujun 已提交
333
            loss.backward()
334 335 336
        with fluid.dygraph.guard():
            inputs2 = []
            for _ in range(10):
337
                tmp = paddle.to_tensor(x)
338 339
                tmp.stop_gradient = False
                inputs2.append(tmp)
340
            ret2 = paddle.add_n(inputs2)
341
            loss2 = fluid.layers.reduce_sum(ret2)
342 343
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            loss2.backward()
344

345 346 347
            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)
348
            a = inputs2[0].gradient()
349
            np.testing.assert_allclose(inputs2[0].gradient(), x, rtol=1e-05)
M
minqiyang 已提交
350

351 352 353 354 355
    def test_sum_op(self):
        with _test_eager_guard():
            self.func_sum_op()
        self.func_sum_op()

356
    def func_empty_var(self):
357 358 359
        with fluid.dygraph.guard():
            cur_program = fluid.Program()
            cur_block = cur_program.current_block()
360
            # Normally, we don't allow tensor with -1 shape being created in dygraph mode, this test is not good.
J
Jiabin Yang 已提交
361
            if _in_legacy_dygraph():
362 363 364
                new_variable = cur_block.create_var(name="X",
                                                    shape=[-1, 23, 48],
                                                    dtype='float32')
365
            else:
366 367 368
                new_variable = cur_block.create_var(name="X",
                                                    shape=[1, 23, 48],
                                                    dtype='float32')
369 370 371
            try:
                new_variable.numpy()
            except Exception as e:
372
                assert type(e) == ValueError
373 374 375 376

            try:
                new_variable.backward()
            except Exception as e:
377
                assert type(e) == core.EnforceNotMet
J
Jiabin Yang 已提交
378 379 380 381
            try:
                new_variable.clear_gradient()
            except Exception as e:
                assert type(e) == core.EnforceNotMet
382

383 384 385 386
    def test_empty_var(self):
        with _test_eager_guard():
            self.func_empty_var()
        self.func_empty_var()
387

388
    def func_empty_grad(self):
389 390
        with fluid.dygraph.guard():
            x = np.ones([2, 2], np.float32)
391
            new_var = paddle.to_tensor(x)
392
            self.assertIsNone(new_var.gradient())
J
Jiabin Yang 已提交
393 394 395 396
            try:
                new_var.clear_gradient()
            except Exception as e:
                assert type(e) == core.EnforceNotMet
397 398 399 400

        with fluid.dygraph.guard():
            cur_program = fluid.Program()
            cur_block = cur_program.current_block()
401
            # Normally, we don't allow tensor with -1 shape being created in dygraph mode, this test is not good.
J
Jiabin Yang 已提交
402
            if _in_legacy_dygraph():
403 404 405
                new_variable = cur_block.create_var(name="X",
                                                    shape=[-1, 23, 48],
                                                    dtype='float32')
406
            else:
407 408 409
                new_variable = cur_block.create_var(name="X",
                                                    shape=[1, 23, 48],
                                                    dtype='float32')
410 411 412 413 414
            try:
                new_variable.gradient()
            except Exception as e:
                assert type(e) == ValueError

415 416 417 418 419 420
    def test_empty_grad(self):
        with _test_eager_guard():
            self.func_empty_grad()
        self.func_empty_grad()

    def func_set_persistable(self):
421 422
        with fluid.dygraph.guard():
            x = np.ones([2, 2], np.float32)
423
            new_var = paddle.to_tensor(x)
424 425
            self.assertFalse(new_var.persistable)
            new_var.persistable = True
426
            self.assertTrue(new_var.persistable)
427

428 429 430 431 432 433
    def test_set_persistable(self):
        with _test_eager_guard():
            self.func_set_persistable()
        self.func_set_persistable()

    def func_layer(self):
L
lujun 已提交
434
        with fluid.dygraph.guard():
435
            l = fluid.Layer("l")
M
minqiyang 已提交
436 437
            self.assertRaises(NotImplementedError, l.forward, [])

438 439 440 441 442 443
    def test_layer(self):
        with _test_eager_guard():
            self.func_layer()
        self.func_layer()

    def func_layer_in_out(self):
M
minqiyang 已提交
444
        np_inp = np.array([1.0, 2.0, -1.0], dtype=np.float32)
L
lujun 已提交
445
        with fluid.dygraph.guard():
446
            var_inp = paddle.to_tensor(np_inp)
447
            var_inp.stop_gradient = False
448
            l = MyLayer()
M
minqiyang 已提交
449 450
            x = l(var_inp)[0]
            self.assertIsNotNone(x)
451
            dy_out = x.numpy()
L
lujun 已提交
452
            x.backward()
453
            dy_grad = l._x_for_debug.gradient()
M
minqiyang 已提交
454

455
        with fluid.dygraph.guard():
456
            var_inp2 = paddle.to_tensor(np_inp)
457
            var_inp2.stop_gradient = False
458
            l2 = MyLayer()
459 460 461
            x2 = l2(var_inp2)[0]
            self.assertIsNotNone(x2)
            dy_out2 = x2.numpy()
462 463
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            x2.backward()
464 465
            dy_grad2 = l2._x_for_debug.gradient()

M
minqiyang 已提交
466
        with new_program_scope():
467 468 469
            inp = fluid.layers.data(name="inp",
                                    shape=[3],
                                    append_batch_size=False)
470
            l = MyLayer()
M
minqiyang 已提交
471 472 473 474 475 476 477 478 479 480
            x = l(inp)[0]
            param_grads = fluid.backward.append_backward(
                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))

            static_out, static_grad = exe.run(
                feed={inp.name: np_inp},
                fetch_list=[x.name, param_grads[1].name])

481 482 483 484
        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 已提交
485

486
    def test_layer_in_out(self):
487
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": True})
488 489 490
        with _test_eager_guard():
            self.func_layer_in_out()
        self.func_layer_in_out()
491
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": False})
492 493

    def func_mlp(self):
M
minqiyang 已提交
494
        np_inp = np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32)
L
lujun 已提交
495
        with fluid.dygraph.guard():
496
            var_inp = paddle.to_tensor(np_inp)
497
            mlp = MLP(input_size=2)
M
minqiyang 已提交
498
            out = mlp(var_inp)
499
            dy_out = out.numpy()
L
lujun 已提交
500
            out.backward()
501
            dy_grad = mlp._linear1.weight.gradient()
M
minqiyang 已提交
502

503
        with fluid.dygraph.guard():
504
            var_inp2 = paddle.to_tensor(np_inp)
505
            mlp2 = MLP(input_size=2)
506 507
            out2 = mlp2(var_inp2)
            dy_out2 = out2.numpy()
508 509
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            out2.backward()
510
            dy_grad2 = mlp2._linear1.weight.gradient()
511

M
minqiyang 已提交
512
        with new_program_scope():
513 514 515
            inp = fluid.layers.data(name="inp",
                                    shape=[2, 2],
                                    append_batch_size=False)
516
            mlp = MLP(input_size=2)
M
minqiyang 已提交
517 518
            out = mlp(inp)
            param_grads = fluid.backward.append_backward(
519
                out, parameter_list=[mlp._linear1.weight.name])[0]
M
minqiyang 已提交
520 521 522 523 524 525 526 527
            exe = fluid.Executor(fluid.CPUPlace(
            ) if not core.is_compiled_with_cuda() else fluid.CUDAPlace(0))
            exe.run(fluid.default_startup_program())

            static_out, static_grad = exe.run(
                feed={inp.name: np_inp},
                fetch_list=[out.name, param_grads[1].name])

528 529 530 531
        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 已提交
532 533

        params = mlp.parameters(True)
534 535 536 537
        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 已提交
538 539
        self.assertEqual(len(params), 4)

J
Jiabin Yang 已提交
540
        sublayers = mlp.sublayers()
541 542
        self.assertEqual(mlp._linear1, sublayers[0])
        self.assertEqual(mlp._linear2, sublayers[1])
M
minqiyang 已提交
543 544
        self.assertEqual(len(sublayers), 2)

545 546 547 548 549
    def test_mlp(self):
        with _test_eager_guard():
            self.func_mlp()
        self.func_mlp()

550
    def test_gradient_accumulation(self):
551

552 553 554 555 556 557
        def test_single_api(sort_sum_gradient):
            fluid.set_flags({'FLAGS_sort_sum_gradient': sort_sum_gradient})
            x = paddle.to_tensor(5., stop_gradient=False)
            for i in range(10):
                y = paddle.pow(x, 4.0)
                y.backward()
558
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
559
            x.clear_gradient()
560
            self.assertEqual(x.grad.numpy(), 0.)
561
            for i in range(10):
562 563
                y = paddle.pow(x, 4.0)
                y.backward()
564
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
565
            x.clear_grad()
566
            self.assertEqual(x.grad.numpy(), 0.)
567 568 569 570 571 572 573 574 575 576

        def test_simple_net(sort_sum_gradient):
            fluid.set_flags({'FLAGS_sort_sum_gradient': sort_sum_gradient})
            x = paddle.to_tensor(5., stop_gradient=False)
            y = paddle.to_tensor(2., stop_gradient=False)
            z = paddle.to_tensor(3., stop_gradient=False)

            def fun(x, y, z):
                loss1 = x * x * y
                loss2 = x * z
577 578
                loss1.backward(retain_graph=True)
                loss2.backward(retain_graph=True)
579 580 581
                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])
582 583 584 585
                x.clear_grad()
                y.clear_grad()
                z.clear_grad()

586 587
                dx = paddle.grad([loss1], x, create_graph=True)[0]
                loss = loss1 + loss2 + dx
588
                # loss = x*x*y + x*z + 2*x*y
589 590 591 592
                return loss

            loss = fun(x, y, z)
            loss.backward(retain_graph=True)
593
            # x.grad = 2*x*y + z + 2*y = 27
594
            np.testing.assert_array_equal(x.grad.numpy(), [27])
595 596

            loss.backward(retain_graph=True)
597
            np.testing.assert_array_equal(x.grad.numpy(), [54])
598 599

            loss.backward()
600
            np.testing.assert_array_equal(x.grad.numpy(), [81])
601 602 603 604 605 606 607 608 609

            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()
610 611
            np.testing.assert_array_equal(dx.grad.numpy(), [1])
            np.testing.assert_array_equal(x.grad.numpy(), [108])
612 613 614 615 616 617 618 619 620

        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)

621 622 623 624
            expected_weight1_grad = 0.
            expected_bias1_grad = 0.
            expected_weight2_grad = 0.
            expected_bias2_grad = 0.
625

626
            for batch_id in range(100):
627 628 629 630
                x = paddle.uniform([10, input_size])
                detach_x = x.detach()
                clear_loss = mlp2(detach_x)
                clear_loss.backward()
631 632 633 634 635 636 637 638
                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())
639 640 641 642

                loss = mlp1(x)
                loss.backward()

643
                np.testing.assert_array_equal(loss.grad.numpy(), [1])
644 645 646 647 648 649 650 651 652 653 654 655
                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)
656 657

                mlp2.clear_gradients()
658
                np.testing.assert_array_equal(clear_loss.grad.numpy(), [1])
659
                if ((batch_id + 1) % 10) % 2 == 0:
660
                    mlp1.clear_gradients()
661 662 663 664
                    expected_weight1_grad = 0.
                    expected_bias1_grad = 0.
                    expected_weight2_grad = 0.
                    expected_bias2_grad = 0.
665 666 667 668 669 670 671 672 673
                elif ((batch_id + 1) % 10) % 2 == 1:
                    mlp1.clear_gradients()
                    mlp1._linear1.weight._set_grad_ivar(
                        paddle.ones([input_size, 3]))
                    mlp1._linear2.weight._set_grad_ivar(paddle.ones([3, 4]))
                    expected_weight1_grad = 1.
                    expected_bias1_grad = 0.
                    expected_weight2_grad = 1.
                    expected_bias2_grad = 0.
674 675 676 677 678 679 680 681 682

        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)

683
    def func_dygraph_vs_static(self):
684 685
        np_inp1 = np.random.rand(4, 3, 3)
        np_inp2 = np.random.rand(4, 3, 3)
X
Xin Pan 已提交
686 687 688

        # dynamic graph
        with fluid.dygraph.guard():
689 690
            inp1 = paddle.to_tensor(np_inp1)
            inp2 = paddle.to_tensor(np_inp2)
691
            if np.sum(np_inp1) < np.sum(np_inp2):
X
Xin Pan 已提交
692 693 694
                x = fluid.layers.elementwise_add(inp1, inp2)
            else:
                x = fluid.layers.elementwise_sub(inp1, inp2)
L
lujun 已提交
695
            dygraph_result = x.numpy()
X
Xin Pan 已提交
696 697 698

        # static graph
        with new_program_scope():
699 700 701 702 703 704
            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 已提交
705 706

            a = fluid.layers.expand(
707 708
                fluid.layers.reshape(fluid.layers.reduce_sum(inp_data1),
                                     [1, 1]), [4, 1])
X
Xin Pan 已提交
709
            b = fluid.layers.expand(
710 711
                fluid.layers.reshape(fluid.layers.reduce_sum(inp_data2),
                                     [1, 1]), [4, 1])
X
Xin Pan 已提交
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
            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()

            exe = fluid.Executor(fluid.CPUPlace(
            ) if not core.is_compiled_with_cuda() else fluid.CUDAPlace(0))
            static_result = exe.run(fluid.default_main_program(),
731 732 733 734
                                    feed={
                                        'inp1': np_inp1,
                                        'inp2': np_inp2
                                    },
X
Xin Pan 已提交
735
                                    fetch_list=out)[0]
736
        np.testing.assert_allclose(dygraph_result, static_result, rtol=1e-05)
X
Xin Pan 已提交
737

738 739 740 741 742 743
    def test_dygraph_vs_static(self):
        with _test_eager_guard():
            self.func_dygraph_vs_static()
        self.func_dygraph_vs_static()

    def func_rnn(self):
M
minqiyang 已提交
744 745 746 747
        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]])
        np_inp = np_inp.reshape((1, 4, 3))
        np_inp = np_inp.astype(np.float32)
L
lujun 已提交
748
        with fluid.dygraph.guard():
749
            var_inp = paddle.to_tensor(np_inp)
M
minqiyang 已提交
750
            var_inp = fluid.layers.reshape(var_inp, shape=[1, 4, 3])
751
            simple_rnn = SimpleRNN()
M
minqiyang 已提交
752
            outs, pre_hiddens = simple_rnn.forward(var_inp)
753
            dy_out = outs[3].numpy()
L
lujun 已提交
754
            outs[3].backward()
755 756 757
            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 已提交
758

759
        with fluid.dygraph.guard():
760
            var_inp2 = paddle.to_tensor(np_inp)
761
            var_inp2 = fluid.layers.reshape(var_inp2, shape=[1, 4, 3])
762
            simple_rnn2 = SimpleRNN()
763 764
            outs2, pre_hiddens2 = simple_rnn2.forward(var_inp2)
            dy_out2 = outs2[3].numpy()
765 766
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            outs2[3].backward()
767 768 769 770
            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 已提交
771
        with new_program_scope():
772 773 774
            inp = fluid.layers.data(name="inp",
                                    shape=[1, 4, 3],
                                    append_batch_size=False)
775
            simple_rnn = SimpleRNN()
M
minqiyang 已提交
776 777 778 779 780 781 782 783 784 785
            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())
            static_out, static_grad_h2o, static_grad_h2h, static_grad_i2h = exe.run(
                feed={inp.name: np_inp},
                fetch_list=[
                    outs[3].name, param_grads[0][1].name,
                    param_grads[1][1].name, param_grads[2][1].name
                ])
786

787 788 789 790 791 792 793 794
        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)
795 796 797 798 799

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

801
    def func_layer_attrs(self):
802 803 804 805 806 807
        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)

808 809 810 811 812 813 814 815 816 817 818 819 820
        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)

821 822 823 824 825
    def test_layer_attrs(self):
        with _test_eager_guard():
            self.func_layer_attrs()
        self.func_layer_attrs()

826

827
class TestDygraphUtils(unittest.TestCase):
828

829
    def func_append_activation_in_dygraph_exception(self):
830 831 832 833 834 835
        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")

836 837 838 839 840 841
    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):
842 843 844
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_activation_in_dygraph
        with fluid.dygraph.guard():
845
            a = paddle.to_tensor(a_np)
846 847
            res1 = func(a, act="hard_sigmoid")
            res2 = fluid.layers.hard_sigmoid(a)
848
            np.testing.assert_array_equal(res1.numpy(), res2.numpy())
849

850 851 852 853 854 855
    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):
856 857 858
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_activation_in_dygraph
        with fluid.dygraph.guard():
859
            a = paddle.to_tensor(a_np)
860 861
            res1 = func(a, act="sigmoid", use_mkldnn=True, use_cudnn=True)
            res2 = fluid.layers.sigmoid(a)
862
            np.testing.assert_allclose(res1.numpy(), res2.numpy(), rtol=1e-05)
863

864 865 866 867 868 869
    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):
870 871 872 873
        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():
874
            a = paddle.to_tensor(a_np)
875 876
            res1 = func(a, act="sigmoid", use_cudnn=True)
            res2 = fluid.layers.sigmoid(a)
877
            np.testing.assert_array_equal(res1.numpy(), res2.numpy())
878

879 880 881 882 883 884
    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):
885
        a_np = np.random.uniform(-2, 2, (10, 20, 30)).astype(np.float32)
886 887 888
        helper = LayerHelper(fluid.unique_name.generate("test"),
                             act="relu",
                             use_mkldnn=True)
889 890
        func = helper.append_activation
        with fluid.dygraph.guard():
891
            a = paddle.to_tensor(a_np)
892 893
            res1 = func(a)
            res2 = fluid.layers.relu(a)
894
            np.testing.assert_array_equal(res1.numpy(), res2.numpy())
895

896 897 898 899 900 901
    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):
902 903 904
        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
905
        with fluid.dygraph.guard(fluid.core.CPUPlace()):
906
            a = paddle.to_tensor(a_np)
907 908 909 910 911 912
            fluid.set_flags({'FLAGS_use_mkldnn': True})
            try:
                res1 = func(a)
            finally:
                fluid.set_flags({'FLAGS_use_mkldnn': False})
            res2 = fluid.layers.relu(a)
913
        np.testing.assert_array_equal(res1.numpy(), res2.numpy())
914

915 916 917 918 919 920
    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):
921 922 923 924 925 926
        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)

927 928 929 930 931 932
    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):
933 934 935
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_bias_in_dygraph
        with fluid.dygraph.guard():
936
            a = paddle.to_tensor(a_np)
937
            res1 = func(a, bias=a)
938
            res2 = paddle.add(a, a)
939
            np.testing.assert_array_equal(res1.numpy(), res2.numpy())
940

941 942 943 944 945
    def test_append_bias_in_dygraph(self):
        with _test_eager_guard():
            self.func_append_bias_in_dygraph()
        self.func_append_bias_in_dygraph()

946

947
class TestDygraphGuardWithError(unittest.TestCase):
948

949
    def func_without_guard(self):
950
        with fluid.dygraph.guard():
951
            x = paddle.to_tensor(np.zeros([10, 10]))
952 953 954 955
        with self.assertRaisesRegexp(TypeError,
                                     "Please use `with fluid.dygraph.guard()"):
            y = fluid.layers.matmul(x, x)

956 957 958 959 960
    def test_without_guard(self):
        with _test_eager_guard():
            self.func_without_guard()
        self.func_without_guard()

961

962
class TestMetaclass(unittest.TestCase):
963

964
    def func_metaclass(self):
965 966
        self.assertEqual(type(MyLayer).__name__, 'type')
        self.assertNotEqual(type(MyLayer).__name__, 'pybind11_type')
J
Jiabin Yang 已提交
967
        if not _in_legacy_dygraph():
968
            self.assertEqual(
969
                type(paddle.fluid.core.eager.Tensor).__name__, 'type')
970 971 972 973 974 975 976 977
        else:
            self.assertEqual(
                type(paddle.fluid.core.VarBase).__name__, 'pybind11_type')

    def test_metaclass(self):
        with _test_eager_guard():
            self.func_metaclass()
        self.func_metaclass()
978 979


980
if __name__ == '__main__':
981
    paddle.enable_static()
982
    unittest.main()