test_imperative_basic.py 37.6 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
    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
        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
    def __init__(self):
        super(SimpleRNN, self).__init__()
J
JiabinYang 已提交
110 111 112 113 114 115
        self.seq_len = 4
        self._cell = SimpleRNNCell(
            3,
            3,
            3,
            fluid.ParamAttr(initializer=fluid.initializer.Constant(value=0.1)))
J
JiabinYang 已提交
116 117

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

121
        init_hidden = self.create_parameter(
J
JiabinYang 已提交
122 123 124 125 126 127
            attr=fluid.ParamAttr(
                initializer=fluid.initializer.Constant(value=0.1)),
            shape=[1, 3],
            dtype='float32',
            is_bias=False)
        pre_hidden = init_hidden
J
JiabinYang 已提交
128
        for i in range(self.seq_len):
J
JiabinYang 已提交
129 130 131
            input = fluid.layers.slice(
                inputs, axes=[1], starts=[i], ends=[i + 1])
            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
    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 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())
        self.assertTrue(np.array_equal(dy_out1, dy_out2))
162 163
        self.assertTrue(np.array_equal(dy_grad1, dy_grad2))

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
        self.assertTrue(np.array_equal(dy_out1, dy_out2))
193 194
        self.assertTrue(np.array_equal(dy_grad1, dy_grad2))

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 223 224
        if not _in_legacy_dygraph():
            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

J
Jiabin Yang 已提交
231
            self.assertTrue(np.array_equal(x, egr_tmp.numpy()))
232 233 234
            self.assertTrue(np.array_equal(y, egr_tmp2.numpy()))
            self.assertTrue(np.array_equal(x, egr_tmp3.numpy()))
            self.assertTrue(np.array_equal(y, egr_tmp4.numpy()))
J
Jiabin Yang 已提交
235
            self.assertTrue(np.array_equal(x, egr_tmp5.numpy()))
236 237
            self.assertTrue(np.array_equal(x, egr_tmp6.numpy()))
        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

            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()))
250
            self.assertTrue(np.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
            self.assertTrue(np.allclose(ret.numpy(), x * 10))
            self.assertTrue(np.allclose(inputs[0].gradient(), x))
347 348 349
            self.assertTrue(np.allclose(ret2.numpy(), x * 10))
            a = inputs2[0].gradient()
            self.assertTrue(np.allclose(inputs2[0].gradient(), x))
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 365 366
                new_variable = cur_block.create_var(
                    name="X", shape=[-1, 23, 48], dtype='float32')
            else:
                new_variable = cur_block.create_var(
                    name="X", shape=[1, 23, 48], dtype='float32')
367 368 369
            try:
                new_variable.numpy()
            except Exception as e:
370
                assert type(e) == ValueError
371 372 373 374

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

381 382 383 384
    def test_empty_var(self):
        with _test_eager_guard():
            self.func_empty_var()
        self.func_empty_var()
385

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

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

411 412 413 414 415 416
    def test_empty_grad(self):
        with _test_eager_guard():
            self.func_empty_grad()
        self.func_empty_grad()

    def func_set_persistable(self):
417 418
        with fluid.dygraph.guard():
            x = np.ones([2, 2], np.float32)
419
            new_var = paddle.to_tensor(x)
420 421
            self.assertFalse(new_var.persistable)
            new_var.persistable = True
422
            self.assertTrue(new_var.persistable)
423

424 425 426 427 428 429
    def test_set_persistable(self):
        with _test_eager_guard():
            self.func_set_persistable()
        self.func_set_persistable()

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

434 435 436 437 438 439
    def test_layer(self):
        with _test_eager_guard():
            self.func_layer()
        self.func_layer()

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

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

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

476 477 478 479
        self.assertTrue(np.array_equal(dy_out, static_out))
        self.assertTrue(np.array_equal(dy_grad, static_grad))
        self.assertTrue(np.array_equal(dy_out2, static_out))
        self.assertTrue(np.array_equal(dy_grad2, static_grad))
M
minqiyang 已提交
480

481
    def test_layer_in_out(self):
482
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": True})
483 484 485
        with _test_eager_guard():
            self.func_layer_in_out()
        self.func_layer_in_out()
486
        fluid.set_flags({"FLAGS_retain_grad_for_all_tensor": False})
487 488

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

498
        with fluid.dygraph.guard():
499
            var_inp2 = paddle.to_tensor(np_inp)
500
            mlp2 = MLP(input_size=2)
501 502
            out2 = mlp2(var_inp2)
            dy_out2 = out2.numpy()
503 504
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            out2.backward()
505
            dy_grad2 = mlp2._linear1.weight.gradient()
506

M
minqiyang 已提交
507 508 509
        with new_program_scope():
            inp = fluid.layers.data(
                name="inp", shape=[2, 2], append_batch_size=False)
510
            mlp = MLP(input_size=2)
M
minqiyang 已提交
511 512
            out = mlp(inp)
            param_grads = fluid.backward.append_backward(
513
                out, parameter_list=[mlp._linear1.weight.name])[0]
M
minqiyang 已提交
514 515 516 517 518 519 520 521 522 523
            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))
524 525
        self.assertTrue(np.allclose(dy_out2, static_out))
        self.assertTrue(np.allclose(dy_grad2, static_grad))
M
minqiyang 已提交
526 527

        params = mlp.parameters(True)
528 529 530 531
        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 已提交
532 533
        self.assertEqual(len(params), 4)

J
Jiabin Yang 已提交
534
        sublayers = mlp.sublayers()
535 536
        self.assertEqual(mlp._linear1, sublayers[0])
        self.assertEqual(mlp._linear2, sublayers[1])
M
minqiyang 已提交
537 538
        self.assertEqual(len(sublayers), 2)

539 540 541 542 543
    def test_mlp(self):
        with _test_eager_guard():
            self.func_mlp()
        self.func_mlp()

544 545 546 547 548 549 550
    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()
551
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
552
            x.clear_gradient()
553
            self.assertEqual(x.grad.numpy(), 0.)
554
            for i in range(10):
555 556
                y = paddle.pow(x, 4.0)
                y.backward()
557
                self.assertEqual(x.grad.numpy(), (i + 1) * 500)
558
            x.clear_grad()
559
            self.assertEqual(x.grad.numpy(), 0.)
560 561 562 563 564 565 566 567 568 569

        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
570 571
                loss1.backward(retain_graph=True)
                loss2.backward(retain_graph=True)
572 573 574
                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.]))
575 576 577 578
                x.clear_grad()
                y.clear_grad()
                z.clear_grad()

579 580
                dx = paddle.grad([loss1], x, create_graph=True)[0]
                loss = loss1 + loss2 + dx
581
                # loss = x*x*y + x*z + 2*x*y
582 583 584 585 586
                return loss

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

            loss.backward(retain_graph=True)
590
            self.assertTrue(np.array_equal(x.grad.numpy(), [54]))
591 592

            loss.backward()
593
            self.assertTrue(np.array_equal(x.grad.numpy(), [81]))
594 595 596 597 598 599 600 601 602

            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()
603 604
            self.assertTrue(np.array_equal(dx.grad.numpy(), [1]))
            self.assertTrue(np.array_equal(x.grad.numpy(), [108]))
605 606 607 608 609 610 611 612 613

        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)

614 615 616 617
            expected_weight1_grad = 0.
            expected_bias1_grad = 0.
            expected_weight2_grad = 0.
            expected_bias2_grad = 0.
618

619
            for batch_id in range(100):
620 621 622 623
                x = paddle.uniform([10, input_size])
                detach_x = x.detach()
                clear_loss = mlp2(detach_x)
                clear_loss.backward()
624 625 626 627 628 629 630 631
                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())
632 633 634 635

                loss = mlp1(x)
                loss.backward()

636
                self.assertTrue(np.array_equal(loss.grad.numpy(), [1]))
637
                self.assertTrue(
638
                    np.allclose(mlp1._linear1.weight.grad.numpy(),
639 640
                                expected_weight1_grad))
                self.assertTrue(
641 642
                    np.allclose(mlp1._linear1.bias.grad.numpy(),
                                expected_bias1_grad))
643
                self.assertTrue(
644
                    np.allclose(mlp1._linear2.weight.grad.numpy(),
645 646
                                expected_weight2_grad))
                self.assertTrue(
647 648
                    np.allclose(mlp1._linear2.bias.grad.numpy(),
                                expected_bias2_grad))
649 650

                mlp2.clear_gradients()
651
                self.assertTrue(np.array_equal(clear_loss.grad.numpy(), [1]))
652
                if ((batch_id + 1) % 10) % 2 == 0:
653
                    mlp1.clear_gradients()
654 655 656 657
                    expected_weight1_grad = 0.
                    expected_bias1_grad = 0.
                    expected_weight2_grad = 0.
                    expected_bias2_grad = 0.
658 659 660 661 662 663 664 665 666
                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.
667 668 669 670 671 672 673 674 675

        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)

676
    def func_dygraph_vs_static(self):
677 678
        np_inp1 = np.random.rand(4, 3, 3)
        np_inp2 = np.random.rand(4, 3, 3)
X
Xin Pan 已提交
679 680 681

        # dynamic graph
        with fluid.dygraph.guard():
682 683
            inp1 = paddle.to_tensor(np_inp1)
            inp2 = paddle.to_tensor(np_inp2)
684
            if np.sum(np_inp1) < np.sum(np_inp2):
X
Xin Pan 已提交
685 686 687
                x = fluid.layers.elementwise_add(inp1, inp2)
            else:
                x = fluid.layers.elementwise_sub(inp1, inp2)
L
lujun 已提交
688
            dygraph_result = x.numpy()
X
Xin Pan 已提交
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721

        # 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(),
722 723
                                    feed={'inp1': np_inp1,
                                          'inp2': np_inp2},
X
Xin Pan 已提交
724 725 726
                                    fetch_list=out)[0]
        self.assertTrue(np.allclose(dygraph_result, static_result))

727 728 729 730 731 732
    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 已提交
733 734 735 736
        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 已提交
737
        with fluid.dygraph.guard():
738
            var_inp = paddle.to_tensor(np_inp)
M
minqiyang 已提交
739
            var_inp = fluid.layers.reshape(var_inp, shape=[1, 4, 3])
740
            simple_rnn = SimpleRNN()
M
minqiyang 已提交
741
            outs, pre_hiddens = simple_rnn.forward(var_inp)
742
            dy_out = outs[3].numpy()
L
lujun 已提交
743
            outs[3].backward()
744 745 746
            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 已提交
747

748
        with fluid.dygraph.guard():
749
            var_inp2 = paddle.to_tensor(np_inp)
750
            var_inp2 = fluid.layers.reshape(var_inp2, shape=[1, 4, 3])
751
            simple_rnn2 = SimpleRNN()
752 753
            outs2, pre_hiddens2 = simple_rnn2.forward(var_inp2)
            dy_out2 = outs2[3].numpy()
754 755
            fluid.set_flags({'FLAGS_sort_sum_gradient': True})
            outs2[3].backward()
756 757 758 759
            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 已提交
760 761 762
        with new_program_scope():
            inp = fluid.layers.data(
                name="inp", shape=[1, 4, 3], append_batch_size=False)
763
            simple_rnn = SimpleRNN()
M
minqiyang 已提交
764 765 766 767 768 769 770 771 772 773
            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
                ])
774

775 776 777 778 779 780 781 782 783 784 785 786 787
        self.assertTrue(np.array_equal(dy_out, static_out))
        self.assertTrue(np.array_equal(dy_grad_h2o, static_grad_h2o))
        self.assertTrue(np.array_equal(dy_grad_h2h, static_grad_h2h))
        self.assertTrue(np.array_equal(dy_grad_i2h, static_grad_i2h))
        self.assertTrue(np.array_equal(dy_out2, static_out))
        self.assertTrue(np.array_equal(dy_grad_h2o2, static_grad_h2o))
        self.assertTrue(np.array_equal(dy_grad_h2h2, static_grad_h2h))
        self.assertTrue(np.array_equal(dy_grad_i2h2, static_grad_i2h))

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

789
    def func_layer_attrs(self):
790 791 792 793 794 795
        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)

796 797 798 799 800 801 802 803 804 805 806 807 808
        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)

809 810 811 812 813
    def test_layer_attrs(self):
        with _test_eager_guard():
            self.func_layer_attrs()
        self.func_layer_attrs()

814

815
class TestDygraphUtils(unittest.TestCase):
816
    def func_append_activation_in_dygraph_exception(self):
817 818 819 820 821 822
        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")

823 824 825 826 827 828
    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):
829 830 831
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_activation_in_dygraph
        with fluid.dygraph.guard():
832
            a = paddle.to_tensor(a_np)
833 834 835 836
            res1 = func(a, act="hard_sigmoid")
            res2 = fluid.layers.hard_sigmoid(a)
            self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

837 838 839 840 841 842
    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):
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="sigmoid", use_mkldnn=True, use_cudnn=True)
            res2 = fluid.layers.sigmoid(a)
849
            self.assertTrue(np.allclose(res1.numpy(), res2.numpy()))
850

851 852 853 854 855 856
    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):
857 858 859 860
        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():
861
            a = paddle.to_tensor(a_np)
862 863 864 865
            res1 = func(a, act="sigmoid", use_cudnn=True)
            res2 = fluid.layers.sigmoid(a)
            self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

866 867 868 869 870 871
    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):
872 873 874 875 876
        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():
877
            a = paddle.to_tensor(a_np)
878 879 880 881
            res1 = func(a)
            res2 = fluid.layers.relu(a)
            self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

882 883 884 885 886 887
    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):
888 889 890
        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
891
        with fluid.dygraph.guard(fluid.core.CPUPlace()):
892
            a = paddle.to_tensor(a_np)
893 894 895 896 897 898 899 900
            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()))

901 902 903 904 905 906
    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):
907 908 909 910 911 912
        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)

913 914 915 916 917 918
    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):
919 920 921
        a_np = np.random.random(size=(10, 20, 30)).astype(np.float32)
        func = dygraph_utils._append_bias_in_dygraph
        with fluid.dygraph.guard():
922
            a = paddle.to_tensor(a_np)
923
            res1 = func(a, bias=a)
924
            res2 = paddle.add(a, a)
925 926
            self.assertTrue(np.array_equal(res1.numpy(), res2.numpy()))

927 928 929 930 931
    def test_append_bias_in_dygraph(self):
        with _test_eager_guard():
            self.func_append_bias_in_dygraph()
        self.func_append_bias_in_dygraph()

932

933
class TestDygraphGuardWithError(unittest.TestCase):
934
    def func_without_guard(self):
935
        with fluid.dygraph.guard():
936
            x = paddle.to_tensor(np.zeros([10, 10]))
937 938 939 940
        with self.assertRaisesRegexp(TypeError,
                                     "Please use `with fluid.dygraph.guard()"):
            y = fluid.layers.matmul(x, x)

941 942 943 944 945
    def test_without_guard(self):
        with _test_eager_guard():
            self.func_without_guard()
        self.func_without_guard()

946

947
class TestMetaclass(unittest.TestCase):
948
    def func_metaclass(self):
949 950
        self.assertEqual(type(MyLayer).__name__, 'type')
        self.assertNotEqual(type(MyLayer).__name__, 'pybind11_type')
J
Jiabin Yang 已提交
951
        if not _in_legacy_dygraph():
952
            self.assertEqual(
953
                type(paddle.fluid.core.eager.Tensor).__name__, 'type')
954 955 956 957 958 959 960 961
        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()
962 963


964
if __name__ == '__main__':
965
    paddle.enable_static()
966
    unittest.main()