test_imperative_basic.py 36.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# 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.

X
Xin Pan 已提交
15
import contextlib
16 17 18 19 20
import unittest
import numpy as np

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


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

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


67
class SimpleRNNCell(fluid.Layer):
68 69
    def __init__(self, step_input_size, hidden_size, output_size, param_attr):
        super(SimpleRNNCell, self).__init__()
70 71 72
        self.step_input_size = step_input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
73 74
        self._dtype = core.VarDesc.VarType.FP32
        self.param_attr = param_attr
75 76 77 78

        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 已提交
79
        self._i2h_w = None
80 81
        self._i2h_w = self.create_parameter(
            attr=self.param_attr,
82 83 84
            shape=i2h_param_shape,
            dtype=self._dtype,
            is_bias=False)
85 86
        self._h2h_w = self.create_parameter(
            attr=self.param_attr,
87 88 89
            shape=h2h_param_shape,
            dtype=self._dtype,
            is_bias=False)
90 91
        self._h2o_w = self.create_parameter(
            attr=self.param_attr,
92 93 94 95 96
            shape=h2o_param_shape,
            dtype=self._dtype,
            is_bias=False)

    def forward(self, input, pre_hidden):
97 98 99 100 101 102
        tmp_i2h = self.create_variable(dtype=self._dtype)
        tmp_h2h = self.create_variable(dtype=self._dtype)
        hidden = self.create_variable(dtype=self._dtype)
        out = self.create_variable(dtype=self._dtype)
        softmax_out = self.create_variable(dtype=self._dtype)
        reduce_out = self.create_variable(dtype=self._dtype)
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
        self._helper.append_op(
            type="mul",
            inputs={"X": input,
                    "Y": self._i2h_w},
            outputs={"Out": tmp_i2h},
            attrs={"x_num_col_dims": 1,
                   "y_num_col_dims": 1})

        self._helper.append_op(
            type="mul",
            inputs={"X": pre_hidden,
                    "Y": self._h2h_w},
            outputs={"Out": tmp_h2h},
            attrs={"x_num_col_dims": 1,
                   "y_num_col_dims": 1})

        self._helper.append_op(
            type="elementwise_add",
            inputs={'X': tmp_h2h,
                    'Y': tmp_i2h},
            outputs={'Out': hidden},
            attrs={'axis': -1,
                   'use_mkldnn': False})
126
        hidden = self._helper.append_activation(hidden, act='tanh')
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

        self._helper.append_op(
            type="mul",
            inputs={"X": hidden,
                    "Y": self._h2o_w},
            outputs={"Out": out},
            attrs={"x_num_col_dims": 1,
                   "y_num_col_dims": 1})

        self._helper.append_op(
            type="softmax",
            inputs={"X": out},
            outputs={"Out": softmax_out},
            attrs={"use_cudnn": False})

        self._helper.append_op(
            type='reduce_sum',
            inputs={'X': softmax_out},
            outputs={'Out': reduce_out},
146
            attrs={'keep_dim': False,
147 148 149 150 151
                   'reduce_all': True})

        return reduce_out, hidden


152
class SimpleRNN(fluid.Layer):
153 154
    def __init__(self):
        super(SimpleRNN, self).__init__()
J
JiabinYang 已提交
155 156 157 158 159 160
        self.seq_len = 4
        self._cell = SimpleRNNCell(
            3,
            3,
            3,
            fluid.ParamAttr(initializer=fluid.initializer.Constant(value=0.1)))
J
JiabinYang 已提交
161 162

    def forward(self, inputs):
J
JiabinYang 已提交
163
        outs = list()
J
JiabinYang 已提交
164 165
        pre_hiddens = list()

166
        init_hidden = self.create_parameter(
J
JiabinYang 已提交
167 168 169 170 171 172
            attr=fluid.ParamAttr(
                initializer=fluid.initializer.Constant(value=0.1)),
            shape=[1, 3],
            dtype='float32',
            is_bias=False)
        pre_hidden = init_hidden
J
JiabinYang 已提交
173
        for i in range(self.seq_len):
J
JiabinYang 已提交
174 175 176
            input = fluid.layers.slice(
                inputs, axes=[1], starts=[i], ends=[i + 1])
            input = fluid.layers.reshape(input, shape=[1, 3])
J
JiabinYang 已提交
177 178
            out_softmax, pre_hidden = self._cell(input, pre_hidden)
            outs.append(out_softmax)
J
JiabinYang 已提交
179

J
JiabinYang 已提交
180
        return outs, pre_hiddens
J
JiabinYang 已提交
181 182


M
minqiyang 已提交
183
class TestImperative(unittest.TestCase):
184
    def functional_dygraph_context(self):
185 186 187 188
        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)
189
        var_inp = paddle.to_tensor(np_inp)
190 191 192 193 194 195 196 197 198
        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())
199
            var_inp = paddle.to_tensor(np_inp)
200 201 202 203 204 205 206
            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())
        self.assertTrue(np.array_equal(dy_out1, dy_out2))
207 208
        self.assertTrue(np.array_equal(dy_grad1, dy_grad2))

209 210 211 212 213 214
    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):
215 216 217
        self.assertFalse(paddle.in_dynamic_mode())
        paddle.disable_static()
        self.assertTrue(paddle.in_dynamic_mode())
218
        np_inp = np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32)
Z
Zhou Wei 已提交
219
        var_inp = paddle.to_tensor(np_inp)
220 221 222 223 224
        mlp = MLP(input_size=2)
        out = mlp(var_inp)
        dy_out1 = out.numpy()
        out.backward()
        dy_grad1 = mlp._linear1.weight.gradient()
225 226 227 228
        paddle.enable_static()
        self.assertFalse(paddle.in_dynamic_mode())
        paddle.disable_static()
        self.assertTrue(paddle.in_dynamic_mode())
Z
Zhou Wei 已提交
229
        var_inp = paddle.to_tensor(np_inp)
230 231 232 233 234 235 236
        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())
237
        self.assertTrue(np.array_equal(dy_out1, dy_out2))
238 239
        self.assertTrue(np.array_equal(dy_grad1, dy_grad2))

240 241 242 243 244 245
    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):
246 247 248
        var = fluid.layers.data(shape=[1], name='x', dtype='float32')
        self.assertTrue(isinstance(var, fluid.Variable))
        with fluid.dygraph.guard():
249 250 251 252 253 254 255 256 257 258 259 260
            if fluid.framework._in_eager_mode():
                var_base = paddle.to_tensor(np.array([3, 4, 5]))
                self.assertTrue(isinstance(var_base, core.eager.EagerTensor))
            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()
261 262 263 264

    def test_create_VarBase(self):
        x = np.ones([2, 2], np.float32)
        y = np.zeros([3, 3], np.float32)
265 266
        t = fluid.Tensor()
        t.set(x, fluid.CPUPlace())
267 268 269
        with fluid.dygraph.guard():
            tmp = fluid.core.VarBase(value=x, place=fluid.core.CPUPlace())
            tmp2 = fluid.core.VarBase(y, fluid.core.CPUPlace())
270
            tmp3 = paddle.to_tensor(x)
271 272
            tmp4 = fluid.core.VarBase(y)
            tmp5 = fluid.core.VarBase(value=x)
273
            tmp6 = fluid.core.VarBase(t)
274 275 276 277 278 279

            self.assertTrue(np.array_equal(x, tmp.numpy()))
            self.assertTrue(np.array_equal(y, tmp2.numpy()))
            self.assertTrue(np.array_equal(x, tmp3.numpy()))
            self.assertTrue(np.array_equal(y, tmp4.numpy()))
            self.assertTrue(np.array_equal(x, tmp5.numpy()))
280
            self.assertTrue(np.array_equal(x, tmp6.numpy()))
281

282 283 284 285 286 287 288 289 290 291
    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)
292
            x = paddle.to_tensor(data)
293 294 295 296 297 298 299
            y = l0(x) + tmp
            o = l1(y)
            o.backward()

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

300 301 302 303 304 305
    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)
306
            with paddle.no_grad():
307 308
                self.assertTrue(l1.weight.stop_gradient is False)
                tmp = l1.weight * 2
309
                self.assertTrue(tmp.stop_gradient)
310
            x = paddle.to_tensor(data)
311 312 313 314
            y = l0(x) + tmp
            o = l1(y)
            o.backward()

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

318 319 320 321 322 323 324 325 326 327 328 329 330
    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)
331
            x = paddle.to_tensor(data)
332 333 334 335 336 337 338 339
            y = l0(x) + tmp2
            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 已提交
340 341 342 343 344 345 346
    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())

M
minqiyang 已提交
347 348
    def test_sum_op(self):
        x = np.ones([2, 2], np.float32)
L
lujun 已提交
349
        with fluid.dygraph.guard():
M
minqiyang 已提交
350 351
            inputs = []
            for _ in range(10):
352
                tmp = paddle.to_tensor(x)
353 354
                tmp.stop_gradient = False
                inputs.append(tmp)
M
minqiyang 已提交
355 356
            ret = fluid.layers.sums(inputs)
            loss = fluid.layers.reduce_sum(ret)
L
lujun 已提交
357
            loss.backward()
358 359 360
        with fluid.dygraph.guard():
            inputs2 = []
            for _ in range(10):
361
                tmp = paddle.to_tensor(x)
362 363
                tmp.stop_gradient = False
                inputs2.append(tmp)
364 365
            ret2 = fluid.layers.sums(inputs2)
            loss2 = fluid.layers.reduce_sum(ret2)
366 367
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            loss2.backward()
368

369 370
            self.assertTrue(np.allclose(ret.numpy(), x * 10))
            self.assertTrue(np.allclose(inputs[0].gradient(), x))
371 372 373
            self.assertTrue(np.allclose(ret2.numpy(), x * 10))
            a = inputs2[0].gradient()
            self.assertTrue(np.allclose(inputs2[0].gradient(), x))
M
minqiyang 已提交
374

375 376 377 378 379 380 381 382 383
    def test_empty_var(self):
        with fluid.dygraph.guard():
            cur_program = fluid.Program()
            cur_block = cur_program.current_block()
            new_variable = cur_block.create_var(
                name="X", shape=[-1, 23, 48], dtype='float32')
            try:
                new_variable.numpy()
            except Exception as e:
384
                assert type(e) == ValueError
385 386 387 388

            try:
                new_variable.backward()
            except Exception as e:
389
                assert type(e) == core.EnforceNotMet
390 391 392 393

            try:
                new_variable.clear_gradient()
            except Exception as e:
394
                assert type(e) == core.EnforceNotMet
395 396 397 398

    def test_empty_grad(self):
        with fluid.dygraph.guard():
            x = np.ones([2, 2], np.float32)
399
            new_var = paddle.to_tensor(x)
400 401 402 403 404 405 406 407
            try:
                new_var.gradient()
            except Exception as e:
                assert type(e) == ValueError

            try:
                new_var.clear_gradient()
            except Exception as e:
408
                assert type(e) == core.EnforceNotMet
409 410 411 412 413 414 415 416 417 418 419 420 421 422

        with fluid.dygraph.guard():
            cur_program = fluid.Program()
            cur_block = cur_program.current_block()
            new_variable = cur_block.create_var(
                name="X", shape=[-1, 23, 48], dtype='float32')
            try:
                new_variable.gradient()
            except Exception as e:
                assert type(e) == ValueError

    def test_set_persistable(self):
        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

M
minqiyang 已提交
428
    def test_layer(self):
L
lujun 已提交
429
        with fluid.dygraph.guard():
430
            l = fluid.Layer("l")
M
minqiyang 已提交
431 432 433 434
            self.assertRaises(NotImplementedError, l.forward, [])

    def test_layer_in_out(self):
        np_inp = np.array([1.0, 2.0, -1.0], dtype=np.float32)
L
lujun 已提交
435
        with fluid.dygraph.guard():
436
            var_inp = paddle.to_tensor(np_inp)
437
            var_inp.stop_gradient = False
438
            l = MyLayer()
M
minqiyang 已提交
439 440
            x = l(var_inp)[0]
            self.assertIsNotNone(x)
441
            dy_out = x.numpy()
L
lujun 已提交
442
            x.backward()
443
            dy_grad = l._x_for_debug.gradient()
M
minqiyang 已提交
444

445
        with fluid.dygraph.guard():
446
            var_inp2 = paddle.to_tensor(np_inp)
447
            var_inp2.stop_gradient = False
448
            l2 = MyLayer()
449 450 451
            x2 = l2(var_inp2)[0]
            self.assertIsNotNone(x2)
            dy_out2 = x2.numpy()
452 453
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            x2.backward()
454 455
            dy_grad2 = l2._x_for_debug.gradient()

M
minqiyang 已提交
456 457 458
        with new_program_scope():
            inp = fluid.layers.data(
                name="inp", shape=[3], append_batch_size=False)
459
            l = MyLayer()
M
minqiyang 已提交
460 461 462 463 464 465 466 467 468 469 470 471
            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])

        self.assertTrue(np.allclose(dy_out, static_out))
        self.assertTrue(np.allclose(dy_grad, static_grad))
472 473
        self.assertTrue(np.allclose(dy_out2, static_out))
        self.assertTrue(np.allclose(dy_grad2, static_grad))
M
minqiyang 已提交
474 475 476

    def test_mlp(self):
        np_inp = np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32)
L
lujun 已提交
477
        with fluid.dygraph.guard():
478
            var_inp = paddle.to_tensor(np_inp)
479
            mlp = MLP(input_size=2)
M
minqiyang 已提交
480
            out = mlp(var_inp)
481
            dy_out = out.numpy()
L
lujun 已提交
482
            out.backward()
483
            dy_grad = mlp._linear1.weight.gradient()
M
minqiyang 已提交
484

485
        with fluid.dygraph.guard():
486
            var_inp2 = paddle.to_tensor(np_inp)
487
            mlp2 = MLP(input_size=2)
488 489
            out2 = mlp2(var_inp2)
            dy_out2 = out2.numpy()
490 491
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            out2.backward()
492
            dy_grad2 = mlp2._linear1.weight.gradient()
493

M
minqiyang 已提交
494 495 496
        with new_program_scope():
            inp = fluid.layers.data(
                name="inp", shape=[2, 2], append_batch_size=False)
497
            mlp = MLP(input_size=2)
M
minqiyang 已提交
498 499
            out = mlp(inp)
            param_grads = fluid.backward.append_backward(
500
                out, parameter_list=[mlp._linear1.weight.name])[0]
M
minqiyang 已提交
501 502 503 504 505 506 507 508 509 510
            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])

        self.assertTrue(np.allclose(dy_out, static_out))
        self.assertTrue(np.allclose(dy_grad, static_grad))
511 512
        self.assertTrue(np.allclose(dy_out2, static_out))
        self.assertTrue(np.allclose(dy_grad2, static_grad))
M
minqiyang 已提交
513 514

        params = mlp.parameters(True)
515 516 517 518
        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 已提交
519 520
        self.assertEqual(len(params), 4)

J
Jiabin Yang 已提交
521
        sublayers = mlp.sublayers()
522 523
        self.assertEqual(mlp._linear1, sublayers[0])
        self.assertEqual(mlp._linear2, sublayers[1])
M
minqiyang 已提交
524 525
        self.assertEqual(len(sublayers), 2)

526 527 528 529 530 531 532
    def test_gradient_accumulation(self):
        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()
533
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
534
            x.clear_gradient()
535
            self.assertEqual(x.grad.numpy(), 0.)
536
            for i in range(10):
537 538
                y = paddle.pow(x, 4.0)
                y.backward()
539
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
540
            x.clear_grad()
541
            self.assertEqual(x.grad.numpy(), 0.)
542 543 544 545 546 547 548 549 550 551

        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
552 553
                loss1.backward(retain_graph=True)
                loss2.backward(retain_graph=True)
554 555 556
                self.assertTrue(np.array_equal(x.grad.numpy(), [23.]))
                self.assertTrue(np.array_equal(y.grad.numpy(), [25.]))
                self.assertTrue(np.array_equal(z.grad.numpy(), [5.]))
557 558 559 560
                x.clear_grad()
                y.clear_grad()
                z.clear_grad()

561 562
                dx = paddle.grad([loss1], x, create_graph=True)[0]
                loss = loss1 + loss2 + dx
563
                # loss = x*x*y + x*z + 2*x*y
564 565 566 567 568
                return loss

            loss = fun(x, y, z)
            loss.backward(retain_graph=True)
            # x.grad = 2*x*y + z + 2*y = 27 
569
            self.assertTrue(np.array_equal(x.grad.numpy(), [27]))
570 571

            loss.backward(retain_graph=True)
572
            self.assertTrue(np.array_equal(x.grad.numpy(), [54]))
573 574

            loss.backward()
575
            self.assertTrue(np.array_equal(x.grad.numpy(), [81]))
576 577 578 579 580 581 582 583 584

            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()
585 586
            self.assertTrue(np.array_equal(dx.grad.numpy(), [1]))
            self.assertTrue(np.array_equal(x.grad.numpy(), [108]))
587 588 589 590 591 592 593 594 595

        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)

596 597 598 599
            expected_weight1_grad = 0.
            expected_bias1_grad = 0.
            expected_weight2_grad = 0.
            expected_bias2_grad = 0.
600

601
            for batch_id in range(100):
602 603 604 605
                x = paddle.uniform([10, input_size])
                detach_x = x.detach()
                clear_loss = mlp2(detach_x)
                clear_loss.backward()
606 607 608 609 610 611 612 613
                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())
614 615 616 617

                loss = mlp1(x)
                loss.backward()

618
                self.assertTrue(np.array_equal(loss.grad.numpy(), [1]))
619
                self.assertTrue(
620
                    np.allclose(mlp1._linear1.weight.grad.numpy(),
621 622
                                expected_weight1_grad))
                self.assertTrue(
623 624
                    np.allclose(mlp1._linear1.bias.grad.numpy(),
                                expected_bias1_grad))
625
                self.assertTrue(
626
                    np.allclose(mlp1._linear2.weight.grad.numpy(),
627 628
                                expected_weight2_grad))
                self.assertTrue(
629 630
                    np.allclose(mlp1._linear2.bias.grad.numpy(),
                                expected_bias2_grad))
631 632

                mlp2.clear_gradients()
633
                self.assertTrue(np.array_equal(clear_loss.grad.numpy(), [1]))
634
                if ((batch_id + 1) % 10) % 2 == 0:
635
                    mlp1.clear_gradients()
636 637 638 639
                    expected_weight1_grad = 0.
                    expected_bias1_grad = 0.
                    expected_weight2_grad = 0.
                    expected_bias2_grad = 0.
640 641 642 643 644 645 646 647 648
                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.
649 650 651 652 653 654 655 656 657

        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)

X
Xin Pan 已提交
658
    def test_dygraph_vs_static(self):
659 660
        np_inp1 = np.random.rand(4, 3, 3)
        np_inp2 = np.random.rand(4, 3, 3)
X
Xin Pan 已提交
661 662 663

        # dynamic graph
        with fluid.dygraph.guard():
664 665
            inp1 = paddle.to_tensor(np_inp1)
            inp2 = paddle.to_tensor(np_inp2)
666
            if np.sum(np_inp1) < np.sum(np_inp2):
X
Xin Pan 已提交
667 668 669
                x = fluid.layers.elementwise_add(inp1, inp2)
            else:
                x = fluid.layers.elementwise_sub(inp1, inp2)
L
lujun 已提交
670
            dygraph_result = x.numpy()
X
Xin Pan 已提交
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703

        # static graph
        with new_program_scope():
            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)

            a = fluid.layers.expand(
                fluid.layers.reshape(
                    fluid.layers.reduce_sum(inp_data1), [1, 1]), [4, 1])
            b = fluid.layers.expand(
                fluid.layers.reshape(
                    fluid.layers.reduce_sum(inp_data2), [1, 1]), [4, 1])
            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(),
704 705
                                    feed={'inp1': np_inp1,
                                          'inp2': np_inp2},
X
Xin Pan 已提交
706 707 708
                                    fetch_list=out)[0]
        self.assertTrue(np.allclose(dygraph_result, static_result))

M
minqiyang 已提交
709 710 711 712 713
    def test_rnn(self):
        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 已提交
714
        with fluid.dygraph.guard():
715
            var_inp = paddle.to_tensor(np_inp)
M
minqiyang 已提交
716
            var_inp = fluid.layers.reshape(var_inp, shape=[1, 4, 3])
717
            simple_rnn = SimpleRNN()
M
minqiyang 已提交
718
            outs, pre_hiddens = simple_rnn.forward(var_inp)
719
            dy_out = outs[3].numpy()
L
lujun 已提交
720
            outs[3].backward()
721 722 723
            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 已提交
724

725
        with fluid.dygraph.guard():
726
            var_inp2 = paddle.to_tensor(np_inp)
727
            var_inp2 = fluid.layers.reshape(var_inp2, shape=[1, 4, 3])
728
            simple_rnn2 = SimpleRNN()
729 730
            outs2, pre_hiddens2 = simple_rnn2.forward(var_inp2)
            dy_out2 = outs2[3].numpy()
731 732
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            outs2[3].backward()
733 734 735 736
            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 已提交
737 738 739
        with new_program_scope():
            inp = fluid.layers.data(
                name="inp", shape=[1, 4, 3], append_batch_size=False)
740
            simple_rnn = SimpleRNN()
M
minqiyang 已提交
741 742 743 744 745 746 747 748 749 750
            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
                ])
751

M
minqiyang 已提交
752 753 754 755
        self.assertTrue(np.allclose(dy_out, static_out))
        self.assertTrue(np.allclose(dy_grad_h2o, static_grad_h2o))
        self.assertTrue(np.allclose(dy_grad_h2h, static_grad_h2h))
        self.assertTrue(np.allclose(dy_grad_i2h, static_grad_i2h))
756 757 758 759
        self.assertTrue(np.allclose(dy_out2, static_out))
        self.assertTrue(np.allclose(dy_grad_h2o2, static_grad_h2o))
        self.assertTrue(np.allclose(dy_grad_h2h2, static_grad_h2h))
        self.assertTrue(np.allclose(dy_grad_i2h2, static_grad_i2h))
M
minqiyang 已提交
760

761 762 763 764 765 766 767
    def test_layer_attrs(self):
        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)

768 769 770 771 772 773 774 775 776 777 778 779 780
        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)

781

782
class TestDygraphUtils(unittest.TestCase):
783
    def func_append_activation_in_dygraph_exception(self):
784 785 786 787 788 789
        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")

790 791 792 793 794 795
    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):
796 797 798
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_activation_in_dygraph
        with fluid.dygraph.guard():
799
            a = paddle.to_tensor(a_np)
800 801 802 803
            res1 = func(a, act="hard_sigmoid")
            res2 = fluid.layers.hard_sigmoid(a)
            self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

804 805 806 807 808 809
    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):
810 811 812
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_activation_in_dygraph
        with fluid.dygraph.guard():
813
            a = paddle.to_tensor(a_np)
814 815
            res1 = func(a, act="sigmoid", use_mkldnn=True, use_cudnn=True)
            res2 = fluid.layers.sigmoid(a)
816
            self.assertTrue(np.allclose(res1.numpy(), res2.numpy()))
817

818 819 820 821 822 823
    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):
824 825 826 827
        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():
828
            a = paddle.to_tensor(a_np)
829 830 831 832
            res1 = func(a, act="sigmoid", use_cudnn=True)
            res2 = fluid.layers.sigmoid(a)
            self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

833 834 835 836 837 838
    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):
839 840 841 842 843
        a_np = np.random.uniform(-2, 2, (10, 20, 30)).astype(np.float32)
        helper = LayerHelper(
            fluid.unique_name.generate("test"), act="relu", use_mkldnn=True)
        func = helper.append_activation
        with fluid.dygraph.guard():
844
            a = paddle.to_tensor(a_np)
845 846 847 848
            res1 = func(a)
            res2 = fluid.layers.relu(a)
            self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

849 850 851 852 853 854
    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):
855 856 857
        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
858
        with fluid.dygraph.guard(fluid.core.CPUPlace()):
859
            a = paddle.to_tensor(a_np)
860 861 862 863 864 865 866 867
            fluid.set_flags({'FLAGS_use_mkldnn': True})
            try:
                res1 = func(a)
            finally:
                fluid.set_flags({'FLAGS_use_mkldnn': False})
            res2 = fluid.layers.relu(a)
        self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

868 869 870 871 872 873
    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):
874 875 876 877 878 879
        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)

880 881 882 883 884 885
    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):
886 887 888
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_bias_in_dygraph
        with fluid.dygraph.guard():
889
            a = paddle.to_tensor(a_np)
890
            res1 = func(a, bias=a)
891
            res2 = paddle.add(a, a)
892 893
            self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

894 895 896 897 898
    def test_append_bias_in_dygraph(self):
        with _test_eager_guard():
            self.func_append_bias_in_dygraph()
        self.func_append_bias_in_dygraph()

899

900
class TestDygraphGuardWithError(unittest.TestCase):
901
    def func_without_guard(self):
902
        with fluid.dygraph.guard():
903
            x = paddle.to_tensor(np.zeros([10, 10]))
904 905 906 907
        with self.assertRaisesRegexp(TypeError,
                                     "Please use `with fluid.dygraph.guard()"):
            y = fluid.layers.matmul(x, x)

908 909 910 911 912
    def test_without_guard(self):
        with _test_eager_guard():
            self.func_without_guard()
        self.func_without_guard()

913

914
class TestMetaclass(unittest.TestCase):
915
    def func_metaclass(self):
916 917
        self.assertEqual(type(MyLayer).__name__, 'type')
        self.assertNotEqual(type(MyLayer).__name__, 'pybind11_type')
918 919 920 921 922 923 924 925 926 927 928
        if core._in_eager_mode():
            self.assertEqual(
                type(paddle.fluid.core.eager.EagerTensor).__name__, 'type')
        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()
929 930


931
if __name__ == '__main__':
932
    paddle.enable_static()
933
    unittest.main()