test_imperative_basic.py 39.1 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
J
Jiabin Yang 已提交
27
from paddle.fluid.framework import _test_eager_guard, _in_legacy_dygraph, _non_static_mode
28 29


30
class MyLayer(fluid.Layer):
31

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

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


43
class MLP(fluid.Layer):
44

45 46 47 48 49
    def __init__(self, input_size):
        super(MLP, self).__init__()
        self._linear1 = Linear(
            input_size,
            3,
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
            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 已提交
61 62

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


69
class SimpleRNNCell(fluid.Layer):
70

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

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

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


107
class SimpleRNN(fluid.Layer):
108

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

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

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

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


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

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

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

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

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

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

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

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

259 260 261 262 263 264 265 266 267 268
    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)
269
            x = paddle.to_tensor(data)
270
            y = paddle.add(l0(x), tmp)
271 272 273 274 275 276
            o = l1(y)
            o.backward()

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

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

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

295 296 297 298 299 300 301 302 303 304 305 306 307
    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)
308
            x = paddle.to_tensor(data)
309
            y = paddle.add(l0(x), tmp2)
310 311 312 313 314 315 316
            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 已提交
317 318 319 320 321 322 323
    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())

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

M
minqiyang 已提交
513
        with new_program_scope():
514 515 516
            inp = fluid.layers.data(name="inp",
                                    shape=[2, 2],
                                    append_batch_size=False)
517
            mlp = MLP(input_size=2)
M
minqiyang 已提交
518 519
            out = mlp(inp)
            param_grads = fluid.backward.append_backward(
520
                out, parameter_list=[mlp._linear1.weight.name])[0]
M
minqiyang 已提交
521 522 523 524 525 526 527 528
            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])

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

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

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

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

551
    def test_gradient_accumulation(self):
552

553 554 555 556 557 558
        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()
559
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
560
            x.clear_gradient()
561
            self.assertEqual(x.grad.numpy(), 0.)
562
            for i in range(10):
563 564
                y = paddle.pow(x, 4.0)
                y.backward()
565
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
566
            x.clear_grad()
567
            self.assertEqual(x.grad.numpy(), 0.)
568 569 570 571 572 573 574 575 576 577

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

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

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

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

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

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

        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)

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

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

                loss = mlp1(x)
                loss.backward()

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

                mlp2.clear_gradients()
659
                np.testing.assert_array_equal(clear_loss.grad.numpy(), [1])
660
                if ((batch_id + 1) % 10) % 2 == 0:
661
                    mlp1.clear_gradients()
662 663 664 665
                    expected_weight1_grad = 0.
                    expected_bias1_grad = 0.
                    expected_weight2_grad = 0.
                    expected_bias2_grad = 0.
666 667 668 669 670 671 672 673 674
                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.
675 676 677 678 679 680 681 682 683

        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)

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

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

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

            a = fluid.layers.expand(
708 709
                fluid.layers.reshape(fluid.layers.reduce_sum(inp_data1),
                                     [1, 1]), [4, 1])
X
Xin Pan 已提交
710
            b = fluid.layers.expand(
711 712
                fluid.layers.reshape(fluid.layers.reduce_sum(inp_data2),
                                     [1, 1]), [4, 1])
X
Xin Pan 已提交
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
            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(),
732 733 734 735
                                    feed={
                                        'inp1': np_inp1,
                                        'inp2': np_inp2
                                    },
X
Xin Pan 已提交
736
                                    fetch_list=out)[0]
737
        np.testing.assert_allclose(dygraph_result, static_result, rtol=1e-05)
X
Xin Pan 已提交
738

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

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

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

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

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

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

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

827

828
class TestDygraphUtils(unittest.TestCase):
829

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

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

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

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

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

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

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

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

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

947

948
class TestDygraphGuardWithError(unittest.TestCase):
949

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

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

962

963
class TestMetaclass(unittest.TestCase):
964

965
    def func_metaclass(self):
966 967
        self.assertEqual(type(MyLayer).__name__, 'type')
        self.assertNotEqual(type(MyLayer).__name__, 'pybind11_type')
J
Jiabin Yang 已提交
968
        if not _in_legacy_dygraph():
969
            self.assertEqual(
970
                type(paddle.fluid.core.eager.Tensor).__name__, 'type')
971 972 973 974 975 976 977 978
        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()
979 980


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