test_paddle_save_load.py 41.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# Copyright (c) 2020 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.

15
import os
16
import tempfile
17 18 19 20 21
import unittest
from io import BytesIO

import numpy as np
from test_imperative_base import new_program_scope
W
WeiXin 已提交
22

23
import paddle
24 25
import paddle.fluid as fluid
import paddle.fluid.framework as framework
26 27
import paddle.nn as nn
import paddle.optimizer as opt
28
from paddle.fluid.optimizer import Adam
29
from paddle.optimizer.lr import LRScheduler
30 31 32 33 34 35 36 37 38

BATCH_SIZE = 16
BATCH_NUM = 4
EPOCH_NUM = 4
SEED = 10

IMAGE_SIZE = 784
CLASS_NUM = 10

T
tianshuo78520a 已提交
39
LARGE_PARAM = 2**26
40

41

42 43
def random_batch_reader():
    def _get_random_inputs_and_labels():
44
        np.random.seed(SEED)
45
        image = np.random.random([BATCH_SIZE, IMAGE_SIZE]).astype('float32')
46 47 48 49 50 51 52 53
        label = np.random.randint(
            0,
            CLASS_NUM - 1,
            (
                BATCH_SIZE,
                1,
            ),
        ).astype('int64')
54 55
        return image, label

56 57 58 59 60 61 62 63
    def __reader__():
        for _ in range(BATCH_NUM):
            batch_image, batch_label = _get_random_inputs_and_labels()
            batch_image = paddle.to_tensor(batch_image)
            batch_label = paddle.to_tensor(batch_label)
            yield batch_image, batch_label

    return __reader__
64 65 66 67


class LinearNet(nn.Layer):
    def __init__(self):
68
        super().__init__()
69 70 71 72 73 74
        self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)

    def forward(self, x):
        return self._linear(x)


75 76
class LayerWithLargeParameters(paddle.nn.Layer):
    def __init__(self):
77
        super().__init__()
78 79 80 81 82 83 84
        self._l = paddle.nn.Linear(10, LARGE_PARAM)

    def forward(self, x):
        y = self._l(x)
        return y


85 86 87 88 89 90 91 92 93 94
def train(layer, loader, loss_fn, opt):
    for epoch_id in range(EPOCH_NUM):
        for batch_id, (image, label) in enumerate(loader()):
            out = layer(image)
            loss = loss_fn(out, label)
            loss.backward()
            opt.step()
            opt.clear_grad()


95 96
class TestSaveLoadLargeParameters(unittest.TestCase):
    def setUp(self):
97 98 99 100
        self.temp_dir = tempfile.TemporaryDirectory()

    def tearDown(self):
        self.temp_dir.cleanup()
101 102 103 104

    def test_large_parameters_paddle_save(self):
        # enable dygraph mode
        paddle.disable_static()
105
        paddle.set_device("cpu")
106 107 108 109
        # create network
        layer = LayerWithLargeParameters()
        save_dict = layer.state_dict()

110 111 112 113 114
        path = os.path.join(
            self.temp_dir.name,
            "test_paddle_save_load_large_param_save",
            "layer.pdparams",
        )
T
tianshuo78520a 已提交
115
        protocol = 4
116
        paddle.save(save_dict, path, protocol=protocol)
117
        dict_load = paddle.load(path, return_numpy=True)
118 119
        # compare results before and after saving
        for key, value in save_dict.items():
120
            np.testing.assert_array_equal(dict_load[key], value.numpy())
121 122


W
WeiXin 已提交
123
class TestSaveLoadPickle(unittest.TestCase):
124 125 126 127 128 129
    def setUp(self):
        self.temp_dir = tempfile.TemporaryDirectory()

    def tearDown(self):
        self.temp_dir.cleanup()

W
WeiXin 已提交
130
    def test_pickle_protocol(self):
131 132
        # enable dygraph mode
        paddle.disable_static()
W
WeiXin 已提交
133 134 135 136
        # create network
        layer = LinearNet()
        save_dict = layer.state_dict()

137 138 139 140 141
        path = os.path.join(
            self.temp_dir.name,
            "test_paddle_save_load_pickle_protocol",
            "layer.pdparams",
        )
W
WeiXin 已提交
142 143 144 145 146 147 148 149 150 151

        with self.assertRaises(ValueError):
            paddle.save(save_dict, path, 2.0)

        with self.assertRaises(ValueError):
            paddle.save(save_dict, path, 1)

        with self.assertRaises(ValueError):
            paddle.save(save_dict, path, 5)

152
        protocols = [2, 3, 4]
W
WeiXin 已提交
153
        for protocol in protocols:
154
            paddle.save(save_dict, path, pickle_protocol=protocol)
W
WeiXin 已提交
155 156 157
            dict_load = paddle.load(path)
            # compare results before and after saving
            for key, value in save_dict.items():
158 159 160
                np.testing.assert_array_equal(
                    dict_load[key].numpy(), value.numpy()
                )
161 162 163


class TestSaveLoadAny(unittest.TestCase):
164 165 166 167 168 169
    def setUp(self):
        self.temp_dir = tempfile.TemporaryDirectory()

    def tearDown(self):
        self.temp_dir.cleanup()

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    def set_zero(self, prog, place, scope=None):
        if scope is None:
            scope = fluid.global_scope()
        for var in prog.list_vars():
            if isinstance(var, framework.Parameter) or var.persistable:
                ten = scope.find_var(var.name).get_tensor()
                if ten is not None:
                    ten.set(np.zeros_like(np.array(ten)), place)
                    new_t = np.array(scope.find_var(var.name).get_tensor())
                    self.assertTrue(np.sum(np.abs(new_t)) == 0)

    def replace_static_save(self, program, model_path, pickle_protocol=2):
        with self.assertRaises(TypeError):
            program.state_dict(1)
        with self.assertRaises(TypeError):
            program.state_dict(scope=1)
        with self.assertRaises(ValueError):
            program.state_dict('x')
        state_dict_param = program.state_dict('param')
        paddle.save(state_dict_param, model_path + '.pdparams')
        state_dict_opt = program.state_dict('opt')
        paddle.save(state_dict_opt, model_path + '.pdopt')
        state_dict_all = program.state_dict()
        paddle.save(state_dict_opt, model_path + '.pdall')

    def replace_static_load(self, program, model_path):
        with self.assertRaises(TypeError):
            program.set_state_dict(1)
        state_dict_param = paddle.load(model_path + '.pdparams')
        state_dict_param['fake_var_name.@@'] = np.random.randn(1, 2)
        state_dict_param['static_x'] = 'UserWarning'
        program.set_state_dict(state_dict_param)
        state_dict_param['static_x'] = np.random.randn(1, 2)
        program.set_state_dict(state_dict_param)
        program.set_state_dict(state_dict_param)
        state_dict_opt = paddle.load(model_path + '.pdopt')
        program.set_state_dict(state_dict_opt)

    def test_replace_static_save_load(self):
        paddle.enable_static()
        with new_program_scope():
211 212 213
            x = paddle.static.data(
                name="static_x", shape=[None, IMAGE_SIZE], dtype='float32'
            )
214 215 216 217 218 219 220 221 222 223 224 225 226 227
            z = paddle.static.nn.fc(x, 10)
            z = paddle.static.nn.fc(z, 10, bias_attr=False)
            loss = fluid.layers.reduce_mean(z)
            opt = Adam(learning_rate=1e-3)
            opt.minimize(loss)
            place = paddle.CPUPlace()
            exe = paddle.static.Executor(place)
            exe.run(paddle.static.default_startup_program())
            prog = paddle.static.default_main_program()
            fake_inputs = np.random.randn(2, IMAGE_SIZE).astype('float32')
            exe.run(prog, feed={'static_x': fake_inputs}, fetch_list=[loss])
            base_map = {}
            for var in prog.list_vars():
                if isinstance(var, framework.Parameter) or var.persistable:
228 229 230
                    t = np.array(
                        fluid.global_scope().find_var(var.name).get_tensor()
                    )
231
                    base_map[var.name] = t
232 233 234
            path = os.path.join(
                self.temp_dir.name, "test_replace_static_save_load", "model"
            )
235 236 237 238 239 240
            # paddle.save, legacy paddle.fluid.load
            self.replace_static_save(prog, path)
            self.set_zero(prog, place)
            paddle.fluid.io.load(prog, path)
            for var in prog.list_vars():
                if isinstance(var, framework.Parameter) or var.persistable:
241 242 243
                    new_t = np.array(
                        fluid.global_scope().find_var(var.name).get_tensor()
                    )
244
                    base_t = base_map[var.name]
245
                    np.testing.assert_array_equal(new_t, np.array(base_t))
246
            # legacy paddle.fluid.save, paddle.load
247 248 249 250 251
            paddle.fluid.io.save(prog, path)
            self.set_zero(prog, place)
            self.replace_static_load(prog, path)
            for var in prog.list_vars():
                if isinstance(var, framework.Parameter) or var.persistable:
252 253 254
                    new_t = np.array(
                        fluid.global_scope().find_var(var.name).get_tensor()
                    )
255
                    base_t = base_map[var.name]
256
                    np.testing.assert_array_equal(new_t, base_t)
257 258 259 260 261
            # test for return tensor
            path_vars = 'test_replace_save_load_return_tensor_static/model'
            for var in prog.list_vars():
                if var.persistable:
                    tensor = var.get_value(fluid.global_scope())
262 263
                    paddle.save(
                        tensor,
264 265
                        os.path.join(self.temp_dir.name, path_vars, var.name),
                    )
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
            with self.assertRaises(TypeError):
                var.get_value('fluid.global_scope()')
            with self.assertRaises(ValueError):
                x.get_value()
            with self.assertRaises(TypeError):
                x.set_value('1')
            fake_data = np.zeros([3, 2, 1, 2, 3])
            with self.assertRaises(TypeError):
                x.set_value(fake_data, '1')
            with self.assertRaises(ValueError):
                x.set_value(fake_data)
            with self.assertRaises(ValueError):
                var.set_value(fake_data)
            # set var to zero
            self.set_zero(prog, place)
            for var in prog.list_vars():
                if var.persistable:
283 284 285 286
                    tensor = paddle.load(
                        os.path.join(self.temp_dir.name, path_vars, var.name),
                        return_numpy=False,
                    )
287
                    var.set_value(tensor)
288 289 290
                    new_t = np.array(
                        fluid.global_scope().find_var(var.name).get_tensor()
                    )
291
                    base_t = base_map[var.name]
292
                    np.testing.assert_array_equal(new_t, base_t)
293 294 295

    def test_paddle_save_load_v2(self):
        paddle.disable_static()
296 297

        class StepDecay(LRScheduler):
298 299 300 301 302 303 304 305
            def __init__(
                self,
                learning_rate,
                step_size,
                gamma=0.1,
                last_epoch=-1,
                verbose=False,
            ):
306 307
                self.step_size = step_size
                self.gamma = gamma
308
                super().__init__(learning_rate, last_epoch, verbose)
309 310 311 312 313

            def get_lr(self):
                i = self.last_epoch // self.step_size
                return self.base_lr * (self.gamma**i)

314
        layer = LinearNet()
315
        inps = paddle.randn([2, IMAGE_SIZE])
316 317 318
        adam = opt.Adam(
            learning_rate=StepDecay(0.1, 1), parameters=layer.parameters()
        )
319 320 321 322
        y = layer(inps)
        y.mean().backward()
        adam.step()
        state_dict = adam.state_dict()
323 324 325
        path = os.path.join(
            self.temp_dir.name, 'paddle_save_load_v2/model.pdparams'
        )
326 327 328 329 330 331 332 333 334
        with self.assertRaises(TypeError):
            paddle.save(state_dict, path, use_binary_format='False')
        # legacy paddle.save, paddle.load
        paddle.framework.io._legacy_save(state_dict, path)
        load_dict_tensor = paddle.load(path, return_numpy=False)
        # legacy paddle.load, paddle.save
        paddle.save(state_dict, path)
        load_dict_np = paddle.framework.io._legacy_load(path)
        for k, v in state_dict.items():
335 336 337
            if isinstance(v, dict):
                self.assertTrue(v == load_dict_tensor[k])
            else:
338 339 340
                np.testing.assert_array_equal(
                    v.numpy(), load_dict_tensor[k].numpy()
                )
341 342 343
                if not np.array_equal(v.numpy(), load_dict_np[k]):
                    print(v.numpy())
                    print(load_dict_np[k])
344
                np.testing.assert_array_equal(v.numpy(), load_dict_np[k])
345 346 347 348 349

    def test_single_pickle_var_dygraph(self):
        # enable dygraph mode
        paddle.disable_static()
        layer = LinearNet()
350 351 352
        path = os.path.join(
            self.temp_dir.name, 'paddle_save_load_v2/var_dygraph'
        )
353 354 355 356 357 358 359 360
        tensor = layer._linear.weight
        with self.assertRaises(ValueError):
            paddle.save(tensor, path, pickle_protocol='3')
        with self.assertRaises(ValueError):
            paddle.save(tensor, path, pickle_protocol=5)
        paddle.save(tensor, path)
        t_dygraph = paddle.load(path)
        np_dygraph = paddle.load(path, return_numpy=True)
H
hong 已提交
361
        self.assertTrue(
362 363
            isinstance(
                t_dygraph,
364 365 366
                (paddle.fluid.core.VarBase, paddle.fluid.core.eager.Tensor),
            )
        )
367 368
        np.testing.assert_array_equal(tensor.numpy(), np_dygraph)
        np.testing.assert_array_equal(tensor.numpy(), t_dygraph.numpy())
369 370 371 372
        paddle.enable_static()
        lod_static = paddle.load(path)
        np_static = paddle.load(path, return_numpy=True)
        self.assertTrue(isinstance(lod_static, paddle.fluid.core.LoDTensor))
373 374
        np.testing.assert_array_equal(tensor.numpy(), np_static)
        np.testing.assert_array_equal(tensor.numpy(), np.array(lod_static))
375 376 377 378 379 380

    def test_single_pickle_var_static(self):
        # enable static mode
        paddle.enable_static()
        with new_program_scope():
            # create network
381 382 383
            x = paddle.static.data(
                name="x", shape=[None, IMAGE_SIZE], dtype='float32'
            )
384 385
            z = paddle.static.nn.fc(x, 128)
            loss = fluid.layers.reduce_mean(z)
386 387 388 389 390
            place = (
                fluid.CPUPlace()
                if not paddle.fluid.core.is_compiled_with_cuda()
                else fluid.CUDAPlace(0)
            )
391 392 393 394 395 396 397 398 399
            exe = paddle.static.Executor(place)
            exe.run(paddle.static.default_startup_program())
            prog = paddle.static.default_main_program()
            for var in prog.list_vars():
                if list(var.shape) == [IMAGE_SIZE, 128]:
                    tensor = var.get_value()
                    break
            scope = fluid.global_scope()
        origin_tensor = np.array(tensor)
400 401 402
        path = os.path.join(
            self.temp_dir.name, 'test_single_pickle_var_static/var'
        )
403 404 405 406 407 408 409
        paddle.save(tensor, path)
        self.set_zero(prog, place, scope)
        # static load
        lod_static = paddle.load(path)
        np_static = paddle.load(path, return_numpy=True)
        # set_tensor(np.ndarray)
        var.set_value(np_static, scope)
410
        np.testing.assert_array_equal(origin_tensor, np.array(tensor))
411 412 413
        # set_tensor(LoDTensor)
        self.set_zero(prog, place, scope)
        var.set_value(lod_static, scope)
414
        np.testing.assert_array_equal(origin_tensor, np.array(tensor))
415 416 417 418
        # enable dygraph mode
        paddle.disable_static()
        var_dygraph = paddle.load(path)
        np_dygraph = paddle.load(path, return_numpy=True)
419 420
        np.testing.assert_array_equal(np.array(tensor), np_dygraph)
        np.testing.assert_array_equal(np.array(tensor), var_dygraph.numpy())
421 422 423

    def test_dygraph_save_static_load(self):
        inps = np.random.randn(1, IMAGE_SIZE).astype('float32')
424 425 426 427
        path = os.path.join(
            self.temp_dir.name,
            'test_dygraph_save_static_load/dy-static.pdparams',
        )
428 429 430 431 432 433 434 435
        paddle.disable_static()
        with paddle.utils.unique_name.guard():
            layer = LinearNet()
            state_dict_dy = layer.state_dict()
            paddle.save(state_dict_dy, path)
        paddle.enable_static()
        with new_program_scope():
            layer = LinearNet()
436 437 438
            data = paddle.static.data(
                name='x_static_save', shape=(None, IMAGE_SIZE), dtype='float32'
            )
439 440
            y_static = layer(data)
            program = paddle.static.default_main_program()
441 442 443 444 445
            place = (
                fluid.CPUPlace()
                if not paddle.fluid.core.is_compiled_with_cuda()
                else fluid.CUDAPlace(0)
            )
446 447 448 449 450 451
            exe = paddle.static.Executor(paddle.CPUPlace())
            exe.run(paddle.static.default_startup_program())
            state_dict = paddle.load(path, keep_name_table=True)
            program.set_state_dict(state_dict)
            state_dict_param = program.state_dict("param")
            for name, tensor in state_dict_dy.items():
452
                np.testing.assert_array_equal(
453 454
                    tensor.numpy(), np.array(state_dict_param[tensor.name])
                )
W
WeiXin 已提交
455

456 457 458 459 460
    def test_save_load_complex_object_dygraph_save(self):
        paddle.disable_static()
        layer = paddle.nn.Linear(3, 4)
        state_dict = layer.state_dict()
        obj1 = [
461 462
            paddle.randn([3, 4], dtype='float32'),
            np.random.randn(5, 6),
463
            ('fake_weight', np.ones([7, 8], dtype='float32')),
464 465
        ]
        obj2 = {'k1': obj1, 'k2': state_dict, 'epoch': 123}
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
        obj3 = (
            paddle.randn([5, 4], dtype='float32'),
            np.random.randn(3, 4).astype("float32"),
            {"state_dict": state_dict, "opt": state_dict},
        )
        obj4 = (np.random.randn(5, 6), (123,))

        path1 = os.path.join(
            self.temp_dir.name, "test_save_load_any_complex_object_dygraph/obj1"
        )
        path2 = os.path.join(
            self.temp_dir.name, "test_save_load_any_complex_object_dygraph/obj2"
        )
        path3 = os.path.join(
            self.temp_dir.name, "test_save_load_any_complex_object_dygraph/obj3"
        )
        path4 = os.path.join(
            self.temp_dir.name, "test_save_load_any_complex_object_dygraph/obj4"
        )
485 486 487 488 489 490 491 492 493 494
        paddle.save(obj1, path1)
        paddle.save(obj2, path2)
        paddle.save(obj3, path3)
        paddle.save(obj4, path4)

        load_tensor1 = paddle.load(path1, return_numpy=False)
        load_tensor2 = paddle.load(path2, return_numpy=False)
        load_tensor3 = paddle.load(path3, return_numpy=False)
        load_tensor4 = paddle.load(path4, return_numpy=False)

495 496 497
        np.testing.assert_array_equal(load_tensor1[0].numpy(), obj1[0].numpy())
        np.testing.assert_array_equal(load_tensor1[1], obj1[1])
        np.testing.assert_array_equal(load_tensor1[2].numpy(), obj1[2][1])
498 499
        for i in range(len(load_tensor1)):
            self.assertTrue(
500 501
                type(load_tensor1[i]) == type(load_tensor2['k1'][i])
            )
502
        for k, v in state_dict.items():
503 504 505
            np.testing.assert_array_equal(
                v.numpy(), load_tensor2['k2'][k].numpy()
            )
506 507
        self.assertTrue(load_tensor2['epoch'] == 123)

508 509
        np.testing.assert_array_equal(load_tensor3[0].numpy(), obj3[0].numpy())
        np.testing.assert_array_equal(np.array(load_tensor3[1]), obj3[1])
510 511

        for k, v in state_dict.items():
512
            np.testing.assert_array_equal(
513 514
                load_tensor3[2]['state_dict'][k].numpy(), v.numpy()
            )
515 516

        for k, v in state_dict.items():
517 518 519
            np.testing.assert_array_equal(
                load_tensor3[2]['opt'][k].numpy(), v.numpy()
            )
520

521
        np.testing.assert_array_equal(load_tensor4[0].numpy(), obj4[0])
522 523 524 525 526 527

        load_array1 = paddle.load(path1, return_numpy=True)
        load_array2 = paddle.load(path2, return_numpy=True)
        load_array3 = paddle.load(path3, return_numpy=True)
        load_array4 = paddle.load(path4, return_numpy=True)

528 529 530
        np.testing.assert_array_equal(load_array1[0], obj1[0].numpy())
        np.testing.assert_array_equal(load_array1[1], obj1[1])
        np.testing.assert_array_equal(load_array1[2], obj1[2][1])
531 532 533
        for i in range(len(load_array1)):
            self.assertTrue(type(load_array1[i]) == type(load_array2['k1'][i]))
        for k, v in state_dict.items():
534
            np.testing.assert_array_equal(v.numpy(), load_array2['k2'][k])
535 536
        self.assertTrue(load_array2['epoch'] == 123)

537 538
        np.testing.assert_array_equal(load_array3[0], obj3[0].numpy())
        np.testing.assert_array_equal(load_array3[1], obj3[1])
539 540

        for k, v in state_dict.items():
541 542 543
            np.testing.assert_array_equal(
                load_array3[2]['state_dict'][k], v.numpy()
            )
544 545

        for k, v in state_dict.items():
546
            np.testing.assert_array_equal(load_array3[2]['opt'][k], v.numpy())
547

548
        np.testing.assert_array_equal(load_array4[0], obj4[0])
549 550 551 552 553 554 555 556 557

        # static mode
        paddle.enable_static()

        load_tensor1 = paddle.load(path1, return_numpy=False)
        load_tensor2 = paddle.load(path2, return_numpy=False)
        load_tensor3 = paddle.load(path3, return_numpy=False)
        load_tensor4 = paddle.load(path4, return_numpy=False)

558 559 560
        np.testing.assert_array_equal(
            np.array(load_tensor1[0]), obj1[0].numpy()
        )
561 562
        np.testing.assert_array_equal(np.array(load_tensor1[1]), obj1[1])
        np.testing.assert_array_equal(np.array(load_tensor1[2]), obj1[2][1])
563 564 565

        for i in range(len(load_tensor1)):
            self.assertTrue(
566 567
                type(load_tensor1[i]) == type(load_tensor2['k1'][i])
            )
568
        for k, v in state_dict.items():
569 570 571
            np.testing.assert_array_equal(
                v.numpy(), np.array(load_tensor2['k2'][k])
            )
572 573
        self.assertTrue(load_tensor2['epoch'] == 123)

574 575 576 577 578 579
        self.assertTrue(
            isinstance(load_tensor3[0], paddle.fluid.core.LoDTensor)
        )
        np.testing.assert_array_equal(
            np.array(load_tensor3[0]), obj3[0].numpy()
        )
580
        np.testing.assert_array_equal(np.array(load_tensor3[1]), obj3[1])
581 582 583

        for k, v in state_dict.items():
            self.assertTrue(
584 585 586 587 588
                isinstance(
                    load_tensor3[2]["state_dict"][k],
                    paddle.fluid.core.LoDTensor,
                )
            )
589
            np.testing.assert_array_equal(
590 591
                np.array(load_tensor3[2]['state_dict'][k]), v.numpy()
            )
592 593 594

        for k, v in state_dict.items():
            self.assertTrue(
595 596 597 598 599 600 601
                isinstance(
                    load_tensor3[2]["opt"][k], paddle.fluid.core.LoDTensor
                )
            )
            np.testing.assert_array_equal(
                np.array(load_tensor3[2]['opt'][k]), v.numpy()
            )
602 603

        self.assertTrue(load_tensor4[0], paddle.fluid.core.LoDTensor)
604
        np.testing.assert_array_equal(np.array(load_tensor4[0]), obj4[0])
605 606 607 608 609 610

        load_array1 = paddle.load(path1, return_numpy=True)
        load_array2 = paddle.load(path2, return_numpy=True)
        load_array3 = paddle.load(path3, return_numpy=True)
        load_array4 = paddle.load(path4, return_numpy=True)

611 612 613
        np.testing.assert_array_equal(load_array1[0], obj1[0].numpy())
        np.testing.assert_array_equal(load_array1[1], obj1[1])
        np.testing.assert_array_equal(load_array1[2], obj1[2][1])
614 615 616
        for i in range(len(load_array1)):
            self.assertTrue(type(load_array1[i]) == type(load_array2['k1'][i]))
        for k, v in state_dict.items():
617
            np.testing.assert_array_equal(v.numpy(), load_array2['k2'][k])
618 619 620
        self.assertTrue(load_array2['epoch'] == 123)

        self.assertTrue(isinstance(load_array3[0], np.ndarray))
621 622
        np.testing.assert_array_equal(load_array3[0], obj3[0].numpy())
        np.testing.assert_array_equal(load_array3[1], obj3[1])
623 624

        for k, v in state_dict.items():
625 626 627
            np.testing.assert_array_equal(
                load_array3[2]['state_dict'][k], v.numpy()
            )
628 629

        for k, v in state_dict.items():
630
            np.testing.assert_array_equal(load_array3[2]['opt'][k], v.numpy())
631

632
        np.testing.assert_array_equal(load_array4[0], obj4[0])
633 634 635 636 637

    def test_save_load_complex_object_static_save(self):
        paddle.enable_static()
        with new_program_scope():
            # create network
638 639 640
            x = paddle.static.data(
                name="x", shape=[None, IMAGE_SIZE], dtype='float32'
            )
641 642 643
            z = paddle.static.nn.fc(x, 10, bias_attr=False)
            z = paddle.static.nn.fc(z, 128, bias_attr=False)
            loss = fluid.layers.reduce_mean(z)
644 645 646 647 648
            place = (
                fluid.CPUPlace()
                if not paddle.fluid.core.is_compiled_with_cuda()
                else fluid.CUDAPlace(0)
            )
649 650 651 652 653 654 655
            prog = paddle.static.default_main_program()
            exe = paddle.static.Executor(place)
            exe.run(paddle.static.default_startup_program())

            state_dict = prog.state_dict()
            keys = list(state_dict.keys())
            obj1 = [
656 657
                state_dict[keys[0]],
                np.random.randn(5, 6),
658
                ('fake_weight', np.ones([7, 8], dtype='float32')),
659 660
            ]
            obj2 = {'k1': obj1, 'k2': state_dict, 'epoch': 123}
661 662 663 664 665 666
            obj3 = (
                state_dict[keys[0]],
                np.ndarray([3, 4], dtype="float32"),
                {"state_dict": state_dict, "opt": state_dict},
            )
            obj4 = (np.ndarray([3, 4], dtype="float32"),)
667

668 669
            path1 = os.path.join(
                self.temp_dir.name,
670 671
                "test_save_load_any_complex_object_static/obj1",
            )
672 673
            path2 = os.path.join(
                self.temp_dir.name,
674 675
                "test_save_load_any_complex_object_static/obj2",
            )
676 677
            path3 = os.path.join(
                self.temp_dir.name,
678 679
                "test_save_load_any_complex_object_static/obj3",
            )
680 681
            path4 = os.path.join(
                self.temp_dir.name,
682 683
                "test_save_load_any_complex_object_static/obj4",
            )
684 685 686 687 688 689 690 691 692 693
            paddle.save(obj1, path1)
            paddle.save(obj2, path2)
            paddle.save(obj3, path3)
            paddle.save(obj4, path4)

            load_tensor1 = paddle.load(path1, return_numpy=False)
            load_tensor2 = paddle.load(path2, return_numpy=False)
            load_tensor3 = paddle.load(path3, return_numpy=False)
            load_tensor4 = paddle.load(path4, return_numpy=False)

694 695 696
            np.testing.assert_array_equal(
                np.array(load_tensor1[0]), np.array(obj1[0])
            )
697 698
            np.testing.assert_array_equal(np.array(load_tensor1[1]), obj1[1])
            np.testing.assert_array_equal(np.array(load_tensor1[2]), obj1[2][1])
699 700
            for i in range(len(load_tensor1)):
                self.assertTrue(
701 702
                    type(load_tensor1[i]) == type(load_tensor2['k1'][i])
                )
703
            for k, v in state_dict.items():
704 705 706
                np.testing.assert_array_equal(
                    np.array(v), np.array(load_tensor2['k2'][k])
                )
707 708 709
            self.assertTrue(load_tensor2['epoch'] == 123)

            self.assertTrue(isinstance(load_tensor3[0], fluid.core.LoDTensor))
710
            np.testing.assert_array_equal(np.array(load_tensor3[0]), obj3[0])
711
            self.assertTrue(isinstance(load_tensor3[1], fluid.core.LoDTensor))
712
            np.testing.assert_array_equal(np.array(load_tensor3[1]), obj3[1])
713 714 715

            for k, v in state_dict.items():
                self.assertTrue(
716 717 718 719
                    isinstance(
                        load_tensor3[2]["state_dict"][k], fluid.core.LoDTensor
                    )
                )
720
                np.testing.assert_array_equal(
721 722
                    np.array(load_tensor3[2]['state_dict'][k]), np.array(v)
                )
723 724 725

            for k, v in state_dict.items():
                self.assertTrue(
726 727
                    isinstance(load_tensor3[2]["opt"][k], fluid.core.LoDTensor)
                )
728
                np.testing.assert_array_equal(
729 730
                    np.array(load_tensor3[2]['opt'][k]), np.array(v)
                )
731 732

            self.assertTrue(isinstance(load_tensor4[0], fluid.core.LoDTensor))
733
            np.testing.assert_array_equal(np.array(load_tensor4[0]), obj4[0])
734 735 736 737 738 739

            load_array1 = paddle.load(path1, return_numpy=True)
            load_array2 = paddle.load(path2, return_numpy=True)
            load_array3 = paddle.load(path3, return_numpy=True)
            load_array4 = paddle.load(path4, return_numpy=True)

740 741 742
            np.testing.assert_array_equal(load_array1[0], np.array(obj1[0]))
            np.testing.assert_array_equal(load_array1[1], obj1[1])
            np.testing.assert_array_equal(load_array1[2], obj1[2][1])
743 744
            for i in range(len(load_array1)):
                self.assertTrue(
745 746
                    type(load_array1[i]) == type(load_array2['k1'][i])
                )
747
            for k, v in state_dict.items():
748
                np.testing.assert_array_equal(np.array(v), load_array2['k2'][k])
749 750
            self.assertTrue(load_array2['epoch'] == 123)

751 752
            np.testing.assert_array_equal(load_array3[0], np.array(obj3[0]))
            np.testing.assert_array_equal(load_array3[1], obj3[1])
753 754

            for k, v in state_dict.items():
755 756 757
                np.testing.assert_array_equal(
                    load_array3[2]['state_dict'][k], np.array(v)
                )
758 759

            for k, v in state_dict.items():
760 761 762
                np.testing.assert_array_equal(
                    load_array3[2]['opt'][k], np.array(v)
                )
763

764
            np.testing.assert_array_equal(load_array4[0], obj4[0])
765 766 767 768 769 770 771 772 773

            # dygraph mode
            paddle.disable_static()

            load_tensor1 = paddle.load(path1, return_numpy=False)
            load_tensor2 = paddle.load(path2, return_numpy=False)
            load_tensor3 = paddle.load(path3, return_numpy=False)
            load_tensor4 = paddle.load(path4, return_numpy=False)

774 775 776
            np.testing.assert_array_equal(
                np.array(load_tensor1[0]), np.array(obj1[0])
            )
777 778
            np.testing.assert_array_equal(np.array(load_tensor1[1]), obj1[1])
            np.testing.assert_array_equal(load_tensor1[2].numpy(), obj1[2][1])
779 780
            for i in range(len(load_tensor1)):
                self.assertTrue(
781 782
                    type(load_tensor1[i]) == type(load_tensor2['k1'][i])
                )
783
            for k, v in state_dict.items():
784 785 786
                np.testing.assert_array_equal(
                    np.array(v), np.array(load_tensor2['k2'][k])
                )
787 788
            self.assertTrue(load_tensor2['epoch'] == 123)

H
hong 已提交
789
            self.assertTrue(
790 791 792 793 794
                isinstance(
                    load_tensor3[0],
                    (fluid.core.VarBase, fluid.core.eager.Tensor),
                )
            )
795
            np.testing.assert_array_equal(load_tensor3[0].numpy(), obj3[0])
H
hong 已提交
796
            self.assertTrue(
797 798 799 800 801
                isinstance(
                    load_tensor3[1],
                    (fluid.core.VarBase, fluid.core.eager.Tensor),
                )
            )
802
            np.testing.assert_array_equal(load_tensor3[1].numpy(), obj3[1])
803 804 805

            for k, v in state_dict.items():
                self.assertTrue(
806 807 808 809 810
                    isinstance(
                        load_tensor3[2]["state_dict"][k],
                        (fluid.core.VarBase, fluid.core.eager.Tensor),
                    )
                )
811
                np.testing.assert_array_equal(
812 813
                    load_tensor3[2]['state_dict'][k].numpy(), np.array(v)
                )
814 815 816

            for k, v in state_dict.items():
                self.assertTrue(
817 818 819 820 821 822 823 824
                    isinstance(
                        load_tensor3[2]["opt"][k],
                        (fluid.core.VarBase, fluid.core.eager.Tensor),
                    )
                )
                np.testing.assert_array_equal(
                    load_tensor3[2]['opt'][k].numpy(), np.array(v)
                )
825

H
hong 已提交
826
            self.assertTrue(
827 828 829 830 831
                isinstance(
                    load_tensor4[0],
                    (fluid.core.VarBase, fluid.core.eager.Tensor),
                )
            )
832
            np.testing.assert_array_equal(load_tensor4[0].numpy(), obj4[0])
833 834 835 836 837 838

            load_array1 = paddle.load(path1, return_numpy=True)
            load_array2 = paddle.load(path2, return_numpy=True)
            load_array3 = paddle.load(path3, return_numpy=True)
            load_array4 = paddle.load(path4, return_numpy=True)

839 840 841
            np.testing.assert_array_equal(load_array1[0], np.array(obj1[0]))
            np.testing.assert_array_equal(load_array1[1], obj1[1])
            np.testing.assert_array_equal(load_array1[2], obj1[2][1])
842 843
            for i in range(len(load_array1)):
                self.assertTrue(
844 845
                    type(load_array1[i]) == type(load_array2['k1'][i])
                )
846
            for k, v in state_dict.items():
847
                np.testing.assert_array_equal(np.array(v), load_array2['k2'][k])
848 849
            self.assertTrue(load_array2['epoch'] == 123)

850 851
            np.testing.assert_array_equal(load_array3[0], np.array(obj3[0]))
            np.testing.assert_array_equal(load_array3[1], obj3[1])
852 853

            for k, v in state_dict.items():
854 855 856
                np.testing.assert_array_equal(
                    load_array3[2]['state_dict'][k], np.array(v)
                )
857 858

            for k, v in state_dict.items():
859 860 861
                np.testing.assert_array_equal(
                    load_array3[2]['opt'][k], np.array(v)
                )
862 863

            self.assertTrue(isinstance(load_array4[0], np.ndarray))
864
            np.testing.assert_array_equal(load_array4[0], obj4[0])
865 866 867 868

    def test_varbase_binary_var(self):
        paddle.disable_static()
        varbase = paddle.randn([3, 2], dtype='float32')
869 870 871 872
        path = os.path.join(
            self.temp_dir.name,
            'test_paddle_save_load_varbase_binary_var/varbase',
        )
873 874 875 876 877 878 879
        paddle.save(varbase, path, use_binary_format=True)
        load_array = paddle.load(path, return_numpy=True)
        load_tensor = paddle.load(path, return_numpy=False)
        origin_array = varbase.numpy()
        load_tensor_array = load_tensor.numpy()
        if paddle.fluid.core.is_compiled_with_cuda():
            fluid.core._cuda_synchronize(paddle.CUDAPlace(0))
880 881
        np.testing.assert_array_equal(origin_array, load_array)
        np.testing.assert_array_equal(origin_array, load_tensor_array)
882

W
WeiXin 已提交
883

884 885 886 887 888 889 890 891 892 893 894 895 896
class TestSaveLoadToMemory(unittest.TestCase):
    def test_dygraph_save_to_memory(self):
        paddle.disable_static()
        linear = LinearNet()
        state_dict = linear.state_dict()
        byio = BytesIO()
        paddle.save(state_dict, byio)
        tensor = paddle.randn([2, 3], dtype='float32')
        paddle.save(tensor, byio)
        byio.seek(0)
        # load state_dict
        dict_load = paddle.load(byio, return_numpy=True)
        for k, v in state_dict.items():
897
            np.testing.assert_array_equal(v.numpy(), dict_load[k])
898 899
        # load tensor
        tensor_load = paddle.load(byio, return_numpy=True)
900
        np.testing.assert_array_equal(tensor_load, tensor.numpy())
901 902 903 904 905 906 907 908 909 910 911 912

        with self.assertRaises(ValueError):
            paddle.save(4, 3)
        with self.assertRaises(ValueError):
            paddle.save(state_dict, '')
        with self.assertRaises(ValueError):
            paddle.fluid.io._open_file_buffer('temp', 'b')

    def test_static_save_to_memory(self):
        paddle.enable_static()
        with new_program_scope():
            # create network
913 914 915
            x = paddle.static.data(
                name="x", shape=[None, IMAGE_SIZE], dtype='float32'
            )
916 917 918
            z = paddle.static.nn.fc(x, 10, bias_attr=False)
            z = paddle.static.nn.fc(z, 128, bias_attr=False)
            loss = fluid.layers.reduce_mean(z)
919 920 921 922 923
            place = (
                fluid.CPUPlace()
                if not paddle.fluid.core.is_compiled_with_cuda()
                else fluid.CUDAPlace(0)
            )
924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
            prog = paddle.static.default_main_program()
            exe = paddle.static.Executor(place)
            exe.run(paddle.static.default_startup_program())

            state_dict = prog.state_dict()
            keys = list(state_dict.keys())
            tensor = state_dict[keys[0]]

            byio = BytesIO()
            byio2 = BytesIO()
            paddle.save(prog, byio2)
            paddle.save(tensor, byio)
            paddle.save(state_dict, byio)
            byio.seek(0)
            byio2.seek(0)

            prog_load = paddle.load(byio2)
941 942 943 944
            self.assertTrue(
                prog.desc.serialize_to_string()
                == prog_load.desc.serialize_to_string()
            )
945 946

            tensor_load = paddle.load(byio, return_numpy=True)
947
            np.testing.assert_array_equal(tensor_load, np.array(tensor))
948 949 950

            state_dict_load = paddle.load(byio, return_numpy=True)
            for k, v in state_dict.items():
951
                np.testing.assert_array_equal(np.array(v), state_dict_load[k])
952 953


954 955 956
class TestSaveLoad(unittest.TestCase):
    def setUp(self):
        # enable dygraph mode
957
        paddle.disable_static()
958 959

        # config seed
C
cnn 已提交
960
        paddle.seed(SEED)
961
        paddle.framework.random._manual_program_seed(SEED)
962 963 964 965
        self.temp_dir = tempfile.TemporaryDirectory()

    def tearDown(self):
        self.temp_dir.cleanup()
966 967 968 969 970 971 972 973 974

    def build_and_train_model(self):
        # create network
        layer = LinearNet()
        loss_fn = nn.CrossEntropyLoss()

        adam = opt.Adam(learning_rate=0.001, parameters=layer.parameters())

        # create data loader
975 976
        # TODO: using new DataLoader cause unknown Timeout on windows, replace it
        loader = random_batch_reader()
977 978 979 980 981 982 983 984

        # train
        train(layer, loader, loss_fn, adam)

        return layer, adam

    def check_load_state_dict(self, orig_dict, load_dict):
        for var_name, value in orig_dict.items():
985 986 987 988 989
            load_value = (
                load_dict[var_name].numpy()
                if hasattr(load_dict[var_name], 'numpy')
                else np.array(load_dict[var_name])
            )
990
            np.testing.assert_array_equal(value.numpy(), load_value)
991 992 993 994 995

    def test_save_load(self):
        layer, opt = self.build_and_train_model()

        # save
996 997 998 999 1000 1001
        layer_save_path = os.path.join(
            self.temp_dir.name, "test_paddle_save_load.linear.pdparams"
        )
        opt_save_path = os.path.join(
            self.temp_dir.name, "test_paddle_save_load.linear.pdopt"
        )
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
        layer_state_dict = layer.state_dict()
        opt_state_dict = opt.state_dict()

        paddle.save(layer_state_dict, layer_save_path)
        paddle.save(opt_state_dict, opt_save_path)

        # load
        load_layer_state_dict = paddle.load(layer_save_path)
        load_opt_state_dict = paddle.load(opt_save_path)

        self.check_load_state_dict(layer_state_dict, load_layer_state_dict)
        self.check_load_state_dict(opt_state_dict, load_opt_state_dict)

        # test save load in static mode
        paddle.enable_static()
1017 1018
        static_save_path = os.path.join(
            self.temp_dir.name,
1019 1020
            "static_mode_test/test_paddle_save_load.linear.pdparams",
        )
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
        paddle.save(layer_state_dict, static_save_path)
        load_static_state_dict = paddle.load(static_save_path)
        self.check_load_state_dict(layer_state_dict, load_static_state_dict)

        # error test cases, some tests relay base test above
        # 1. test save obj not dict error
        test_list = [1, 2, 3]

        # 2. test save path format error
        with self.assertRaises(ValueError):
1031 1032
            paddle.save(
                layer_state_dict,
1033 1034 1035 1036
                os.path.join(
                    self.temp_dir.name, "test_paddle_save_load.linear.model/"
                ),
            )
1037 1038 1039

        # 3. test load path not exist error
        with self.assertRaises(ValueError):
1040
            paddle.load(
1041 1042 1043 1044
                os.path.join(
                    self.temp_dir.name, "test_paddle_save_load.linear.params"
                )
            )
1045 1046 1047

        # 4. test load old save path error
        with self.assertRaises(ValueError):
1048
            paddle.load(
1049 1050
                os.path.join(self.temp_dir.name, "test_paddle_save_load.linear")
            )
1051 1052


W
WeiXin 已提交
1053 1054 1055
class TestSaveLoadProgram(unittest.TestCase):
    def test_save_load_program(self):
        paddle.enable_static()
1056 1057
        temp_dir = tempfile.TemporaryDirectory()

W
WeiXin 已提交
1058 1059
        with new_program_scope():
            layer = LinearNet()
1060 1061 1062
            data = paddle.static.data(
                name='x_static_save', shape=(None, IMAGE_SIZE), dtype='float32'
            )
W
WeiXin 已提交
1063 1064 1065 1066 1067
            y_static = layer(data)
            main_program = paddle.static.default_main_program()
            startup_program = paddle.static.default_startup_program()
            origin_main = main_program.desc.serialize_to_string()
            origin_startup = startup_program.desc.serialize_to_string()
1068 1069
            path1 = os.path.join(
                temp_dir.name,
1070 1071
                "test_paddle_save_load_program/main_program.pdmodel",
            )
1072 1073
            path2 = os.path.join(
                temp_dir.name,
1074 1075
                "test_paddle_save_load_program/startup_program.pdmodel",
            )
W
WeiXin 已提交
1076 1077 1078 1079 1080 1081 1082 1083
            paddle.save(main_program, path1)
            paddle.save(startup_program, path2)

        with new_program_scope():
            load_main = paddle.load(path1).desc.serialize_to_string()
            load_startup = paddle.load(path2).desc.serialize_to_string()
            self.assertTrue(origin_main == load_main)
            self.assertTrue(origin_startup == load_startup)
1084
        temp_dir.cleanup()
W
WeiXin 已提交
1085 1086


1087 1088 1089
class TestSaveLoadLayer(unittest.TestCase):
    def test_save_load_layer(self):
        paddle.disable_static()
1090
        temp_dir = tempfile.TemporaryDirectory()
1091 1092 1093 1094 1095
        inps = paddle.randn([1, IMAGE_SIZE], dtype='float32')
        layer1 = LinearNet()
        layer2 = LinearNet()
        layer1.eval()
        layer2.eval()
1096
        origin_layer = (layer1, layer2)
1097
        origin = (layer1(inps), layer2(inps))
1098 1099 1100
        path = os.path.join(
            temp_dir.name, "test_save_load_layer_/layer.pdmodel"
        )
1101 1102
        with self.assertRaises(ValueError):
            paddle.save(origin_layer, path)
1103
        temp_dir.cleanup()
1104 1105


1106 1107
if __name__ == '__main__':
    unittest.main()