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

from __future__ import print_function

17
import os
18
import pickle
19 20
import unittest
import numpy as np
L
Leo Chen 已提交
21
import paddle
22
from paddle.static import InputSpec
23 24
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
25
from paddle.fluid.dygraph import declarative, ProgramTranslator
26
from paddle.fluid.dygraph.io import INFER_MODEL_SUFFIX, INFER_PARAMS_SUFFIX, INFER_PARAMS_INFO_SUFFIX
27 28

BATCH_SIZE = 32
29
BATCH_NUM = 10
30 31 32
SEED = 10


33 34
def random_batch_reader(input_size, label_size):
    def _get_random_inputs_and_labels(input_size, label_size):
35
        np.random.seed(SEED)
36 37 38
        input = np.random.random(size=input_size).astype('float32')
        label = np.random.random(size=label_size).astype('int64')
        return input, label
39 40 41

    def __reader__():
        for _ in range(BATCH_NUM):
42 43 44
            batch_input, batch_label = _get_random_inputs_and_labels(
                [BATCH_SIZE, input_size], [BATCH_SIZE, label_size])
            yield batch_input, batch_label
45 46 47 48 49 50 51 52 53 54 55 56 57 58

    return __reader__


class LinearNet(fluid.dygraph.Layer):
    def __init__(self, in_size, out_size):
        super(LinearNet, self).__init__()
        self._linear = Linear(in_size, out_size)

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


59 60 61 62 63 64 65 66 67 68
class LinearNetWithInputSpec(fluid.dygraph.Layer):
    def __init__(self, in_size, out_size):
        super(LinearNetWithInputSpec, self).__init__()
        self._linear = Linear(in_size, out_size)

    @declarative(input_spec=[InputSpec(shape=[None, 784], dtype='float32')])
    def forward(self, x):
        return self._linear(x)


69 70 71 72 73 74 75 76 77
class LinearNetNotDeclarative(fluid.dygraph.Layer):
    def __init__(self, in_size, out_size):
        super(LinearNetNotDeclarative, self).__init__()
        self._linear = Linear(in_size, out_size)

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


78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
class LinerNetWithLabel(paddle.nn.Layer):
    def __init__(self, in_size, out_size):
        super(LinerNetWithLabel, self).__init__()
        self._linear = Linear(in_size, out_size)

    @declarative(input_spec=[
        InputSpec(
            shape=[None, 784], dtype='float32', name="image"), InputSpec(
                shape=[None, 1], dtype='int64', name="label")
    ])
    def forward(self, x, label):
        out = self._linear(x)
        loss = fluid.layers.cross_entropy(out, label)
        avg_loss = fluid.layers.mean(loss)
        return out, avg_loss


95 96 97 98 99 100 101 102 103 104 105 106 107
class LinearNetReturnLoss(fluid.dygraph.Layer):
    def __init__(self, in_size, out_size):
        super(LinearNetReturnLoss, self).__init__()
        self._linear = Linear(in_size, out_size)

    @declarative
    def forward(self, x):
        y = self._linear(x)
        z = self._linear(y)
        loss = fluid.layers.mean(z)
        return z, loss


108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
class LinearNetMultiInput(fluid.dygraph.Layer):
    def __init__(self, in_size, out_size):
        super(LinearNetMultiInput, self).__init__()
        self._linear1 = Linear(in_size, out_size)
        self._linear2 = Linear(in_size, out_size)

    @declarative(input_spec=[
        InputSpec(
            [None, 8], dtype='float32'), InputSpec(
                [None, 8], dtype='float32')
    ])
    def forward(self, x, y):
        x_out = self._linear1(x)
        y_out = self._linear2(y)
        loss = fluid.layers.mean(x_out + y_out)
        return x_out, y_out, loss


class MultiLoadingLinearNet(fluid.dygraph.Layer):
    def __init__(self, size, model_path):
        super(MultiLoadingLinearNet, self).__init__()
        self._linear = Linear(size, size)
130 131
        self._load_linear1 = paddle.jit.load(model_path)
        self._load_linear2 = paddle.jit.load(model_path)
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

    @declarative
    def forward(self, x):
        tmp1 = self._linear(x)
        tmp2 = self._load_linear1(tmp1)
        tmp3 = self._load_linear2(tmp2)
        y = self._linear(tmp3)
        return y


class LinearNetReturnHidden(fluid.dygraph.Layer):
    def __init__(self, in_size, out_size):
        super(LinearNetReturnHidden, self).__init__()
        self._linear_1 = Linear(in_size, out_size)
        self._linear_2 = Linear(in_size, out_size)

    @declarative
    def forward(self, x):
        y = self._linear_1(x)
        z = self._linear_2(y)
        loss = fluid.layers.mean(z)
        return y, loss


156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
class EmptyLayer(paddle.nn.Layer):
    def __init__(self):
        super(EmptyLayer, self).__init__()

    @paddle.jit.to_static
    def forward(self, x):
        return x


class NoParamLayer(paddle.nn.Layer):
    def __init__(self):
        super(NoParamLayer, self).__init__()

    @paddle.jit.to_static
    def forward(self, x, y):
        return x + y


174
def train(layer, input_size=784, label_size=1):
175
    # create optimizer
L
Leo Chen 已提交
176
    sgd = fluid.optimizer.SGDOptimizer(
177
        learning_rate=0.01, parameter_list=layer.parameters())
178 179
    # create data loader
    train_loader = fluid.io.DataLoader.from_generator(capacity=5)
180 181
    train_loader.set_batch_generator(
        random_batch_reader(input_size, label_size))
182 183 184 185 186 187 188 189 190 191 192
    # train
    for data in train_loader():
        img, label = data
        label.stop_gradient = True

        cost = layer(img)

        loss = fluid.layers.cross_entropy(cost, label)
        avg_loss = fluid.layers.mean(loss)

        avg_loss.backward()
L
Leo Chen 已提交
193
        sgd.minimize(avg_loss)
194 195 196 197
        layer.clear_gradients()
    return [img], layer, avg_loss


198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
def train_with_label(layer, input_size=784, label_size=1):
    # create optimizer
    sgd = fluid.optimizer.SGDOptimizer(
        learning_rate=0.01, parameter_list=layer.parameters())
    # create data loader
    train_loader = fluid.io.DataLoader.from_generator(capacity=5)
    train_loader.set_batch_generator(
        random_batch_reader(input_size, label_size))
    # train
    for data in train_loader():
        img, label = data
        label.stop_gradient = True

        out, avg_loss = layer(img, label)

        avg_loss.backward()
        sgd.minimize(avg_loss)
        layer.clear_gradients()
    return out


219 220
class TestJitSaveLoad(unittest.TestCase):
    def setUp(self):
221
        self.model_path = "test_jit_save_load/model"
222 223 224
        # enable dygraph mode
        fluid.enable_dygraph()
        # config seed
L
Leo Chen 已提交
225 226
        paddle.manual_seed(SEED)
        paddle.framework.random._manual_program_seed(SEED)
227

228
    def train_and_save_model(self, model_path=None):
229 230
        layer = LinearNet(784, 1)
        example_inputs, layer, _ = train(layer)
231
        final_model_path = model_path if model_path else self.model_path
232
        orig_input_types = [type(x) for x in example_inputs]
233 234
        paddle.jit.save(
            layer=layer, path=final_model_path, input_spec=example_inputs)
235 236
        new_input_types = [type(x) for x in example_inputs]
        self.assertEqual(orig_input_types, new_input_types)
237 238
        return layer

239
    def test_save_load(self):
240 241 242
        # train and save model
        train_layer = self.train_and_save_model()
        # load model
243
        loaded_layer = paddle.jit.load(self.model_path)
244 245 246 247 248
        self.load_and_inference(train_layer, loaded_layer)
        self.load_dygraph_state_dict(train_layer)
        self.load_and_finetune(train_layer, loaded_layer)

    def load_and_inference(self, train_layer, infer_layer):
249
        train_layer.eval()
250
        infer_layer.eval()
251 252 253 254 255 256
        # inference & compare
        x = fluid.dygraph.to_variable(
            np.random.random((1, 784)).astype('float32'))
        self.assertTrue(
            np.array_equal(train_layer(x).numpy(), infer_layer(x).numpy()))

257 258
    def load_and_finetune(self, train_layer, load_train_layer):
        train_layer.train()
259 260
        load_train_layer.train()
        # train & compare
L
Leo Chen 已提交
261 262
        img0, _, train_loss = train(train_layer)
        img1, _, load_train_loss = train(load_train_layer)
263 264 265
        self.assertTrue(
            np.array_equal(train_loss.numpy(), load_train_loss.numpy()))

266 267
    def load_dygraph_state_dict(self, train_layer):
        train_layer.eval()
268
        # construct new model
269
        new_layer = LinearNet(784, 1)
270
        orig_state_dict = new_layer.state_dict()
271
        load_state_dict = paddle.load(self.model_path)
272 273 274
        for structured_name in orig_state_dict:
            self.assertTrue(structured_name in load_state_dict)
        new_layer.set_state_dict(load_state_dict)
275 276 277 278 279 280 281
        new_layer.eval()
        # inference & compare
        x = fluid.dygraph.to_variable(
            np.random.random((1, 784)).astype('float32'))
        self.assertTrue(
            np.array_equal(train_layer(x).numpy(), new_layer(x).numpy()))

282
    def test_load_dygraph_no_path(self):
283
        model_path = "test_jit_save_load.no_path/model_path"
284 285 286
        with self.assertRaises(ValueError):
            model_dict, _ = fluid.dygraph.load_dygraph(model_path)

287
    def test_jit_load_model_incomplete(self):
288 289 290 291
        model_path = "test_jit_save_load.remove_variables/model"
        self.train_and_save_model(model_path)
        # remove `.pdiparams`	
        var_path = model_path + INFER_PARAMS_SUFFIX
292 293 294 295
        os.remove(var_path)
        with self.assertRaises(ValueError):
            paddle.jit.load(model_path)

296 297 298 299 300
    def test_jit_load_no_path(self):
        path = "test_jit_save_load.no_path/model_path"
        with self.assertRaises(ValueError):
            loaded_layer = paddle.jit.load(path)

301

302 303 304 305 306 307 308 309 310 311 312 313
class TestSaveLoadWithInputSpec(unittest.TestCase):
    def setUp(self):
        # enable dygraph mode
        fluid.enable_dygraph()

    def test_with_input_spec(self):
        net = LinearNetReturnLoss(8, 8)
        # set x.shape = [None, 8]
        net.forward = declarative(
            net.forward, input_spec=[InputSpec(
                [None, 8], name='x')])

314
        model_path = "input_spec.output_spec/model"
315 316 317 318 319 320 321
        # check inputs and outputs
        self.assertTrue(len(net.forward.inputs) == 1)
        input_x = net.forward.inputs[0]
        self.assertTrue(input_x.shape == (-1, 8))
        self.assertTrue(input_x.name == 'x')

        # 1. prune loss
322 323
        output_spec = net.forward.outputs[:1]
        paddle.jit.save(net, model_path, output_spec=output_spec)
324 325

        # 2. load to infer
326
        infer_layer = paddle.jit.load(model_path)
327 328 329 330 331 332 333
        x = fluid.dygraph.to_variable(
            np.random.random((4, 8)).astype('float32'))
        pred = infer_layer(x)

    def test_multi_in_out(self):
        net = LinearNetMultiInput(8, 8)

334
        model_path = "multi_inout.output_spec1/model"
335 336 337 338 339 340 341 342
        # 1. check inputs and outputs
        self.assertTrue(len(net.forward.inputs) == 2)
        input_x = net.forward.inputs[0]
        input_y = net.forward.inputs[1]
        self.assertTrue(input_x.shape == (-1, 8))
        self.assertTrue(input_y.shape == (-1, 8))

        # 2. prune loss
343 344
        output_spec = net.forward.outputs[:2]
        paddle.jit.save(net, model_path, output_spec=output_spec)
345 346

        # 3. load to infer
347
        infer_layer = paddle.jit.load(model_path)
348 349 350 351 352 353 354 355
        x = fluid.dygraph.to_variable(
            np.random.random((4, 8)).astype('float32'))
        y = fluid.dygraph.to_variable(
            np.random.random((4, 8)).astype('float32'))
        # 4. predict
        pred_x, pred_y = infer_layer(x, y)

        # 1. prune y and loss
356 357 358
        model_path = "multi_inout.output_spec2/model"
        output_spec = net.forward.outputs[:1]
        paddle.jit.save(net, model_path, [input_x], output_spec=output_spec)
359
        # 2. load again
360
        infer_layer2 = paddle.jit.load(model_path)
361 362 363 364 365 366 367
        # 3. predict
        pred_xx = infer_layer2(x)

        # 4. assert pred_x == pred_xx
        self.assertTrue(np.allclose(pred_x.numpy(), pred_xx.numpy()))


368 369 370 371 372
class TestJitSaveLoadConfig(unittest.TestCase):
    def setUp(self):
        # enable dygraph mode
        fluid.enable_dygraph()
        # config seed
L
Leo Chen 已提交
373 374
        paddle.manual_seed(SEED)
        paddle.framework.random._manual_program_seed(SEED)
375 376 377 378 379 380 381 382 383 384 385 386 387

    def test_output_spec(self):
        train_layer = LinearNetReturnLoss(8, 8)
        adam = fluid.optimizer.AdamOptimizer(
            learning_rate=0.1, parameter_list=train_layer.parameters())
        x = fluid.dygraph.to_variable(
            np.random.random((4, 8)).astype('float32'))
        for i in range(10):
            out, loss = train_layer(x)
            loss.backward()
            adam.minimize(loss)
            train_layer.clear_gradients()

388 389 390
        model_path = "save_load_config.output_spec"
        output_spec = [out]
        paddle.jit.save(
391
            layer=train_layer,
392
            path=model_path,
393
            input_spec=[x],
394
            output_spec=output_spec)
395 396

        train_layer.eval()
397
        infer_layer = paddle.jit.load(model_path)
398 399 400 401 402
        x = fluid.dygraph.to_variable(
            np.random.random((4, 8)).astype('float32'))
        self.assertTrue(
            np.array_equal(train_layer(x)[0].numpy(), infer_layer(x).numpy()))

403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
    def test_save_no_support_config_error(self):
        layer = LinearNet(784, 1)
        path = "no_support_config_test"
        with self.assertRaises(ValueError):
            paddle.jit.save(layer=layer, path=path, model_filename="")

    def test_load_empty_model_filename_error(self):
        path = "error_model_filename_test"
        with self.assertRaises(ValueError):
            paddle.jit.load(path, model_filename="")

    def test_load_empty_params_filename_error(self):
        path = "error_params_filename_test"
        with self.assertRaises(ValueError):
            paddle.jit.load(path, params_filename="")

    def test_load_with_no_support_config(self):
        path = "no_support_config_test"
        with self.assertRaises(ValueError):
            paddle.jit.load(path, separate_params=True)

424

425 426 427
class TestJitMultipleLoading(unittest.TestCase):
    def setUp(self):
        self.linear_size = 4
428
        self.model_path = "jit_multi_load/model"
429 430 431
        # enable dygraph mode
        fluid.enable_dygraph()
        # config seed
L
Leo Chen 已提交
432 433
        paddle.manual_seed(SEED)
        paddle.framework.random._manual_program_seed(SEED)
434 435 436 437 438 439
        # train and save base model
        self.train_and_save_orig_model()

    def train_and_save_orig_model(self):
        layer = LinearNet(self.linear_size, self.linear_size)
        example_inputs, layer, _ = train(layer, self.linear_size, 1)
440 441
        paddle.jit.save(
            layer=layer, path=self.model_path, input_spec=example_inputs)
442 443 444 445 446 447 448 449 450 451 452

    def test_load_model_retransform_inference(self):
        multi_loaded_layer = MultiLoadingLinearNet(self.linear_size,
                                                   self.model_path)
        state_dict = multi_loaded_layer.state_dict()
        name_set = set()
        for _, var in state_dict.items():
            self.assertTrue(var.name not in name_set)
            name_set.add(var.name)


453 454 455
class TestJitPruneModelAndLoad(unittest.TestCase):
    def setUp(self):
        self.linear_size = 4
456
        self.model_path = "jit_prune_model_and_load/model"
457 458 459
        # enable dygraph mode
        fluid.enable_dygraph()
        # config seed
L
Leo Chen 已提交
460 461
        paddle.manual_seed(SEED)
        paddle.framework.random._manual_program_seed(SEED)
462 463 464 465 466 467 468 469 470 471 472 473 474

    def train_and_save(self):
        train_layer = LinearNetReturnHidden(8, 8)
        adam = fluid.optimizer.AdamOptimizer(
            learning_rate=0.1, parameter_list=train_layer.parameters())
        x = fluid.dygraph.to_variable(
            np.random.random((4, 8)).astype('float32'))
        for i in range(10):
            hidden, loss = train_layer(x)
            loss.backward()
            adam.minimize(loss)
            train_layer.clear_gradients()

475 476
        output_spec = [hidden]
        paddle.jit.save(
477
            layer=train_layer,
478
            path=self.model_path,
479
            input_spec=[x],
480
            output_spec=output_spec)
481 482 483 484 485 486 487

        return train_layer

    def test_load_pruned_model(self):
        train_layer = self.train_and_save()
        train_layer.eval()

488
        infer_layer = paddle.jit.load(self.model_path)
489 490 491 492 493 494 495 496 497 498

        x = fluid.dygraph.to_variable(
            np.random.random((4, 8)).astype('float32'))
        self.assertTrue(
            np.array_equal(train_layer(x)[0].numpy(), infer_layer(x).numpy()))

    def test_load_var_not_in_extra_var_info(self):
        self.train_and_save()

        # chage extra var info
499
        var_info_path = self.model_path + INFER_PARAMS_INFO_SUFFIX
500 501 502 503 504 505 506
        with open(var_info_path, 'rb') as f:
            extra_var_info = pickle.load(f)
            extra_var_info.clear()
        with open(var_info_path, 'wb') as f:
            pickle.dump(extra_var_info, f, protocol=2)

        with self.assertRaises(RuntimeError):
507
            paddle.jit.load(self.model_path)
508 509


510 511 512 513 514 515 516 517 518 519 520 521 522
class TestJitSaveMultiCases(unittest.TestCase):
    def setUp(self):
        # enable dygraph mode
        fluid.enable_dygraph()
        # config seed
        paddle.manual_seed(SEED)
        paddle.framework.random._manual_program_seed(SEED)

    def verify_inference_correctness(self, layer, model_path, with_label=False):
        layer.eval()
        loaded_layer = paddle.jit.load(model_path)
        loaded_layer.eval()
        # inference & compare
Z
Zhou Wei 已提交
523
        x = paddle.to_tensor(np.random.random((1, 784)).astype('float32'))
524
        if with_label:
Z
Zhou Wei 已提交
525
            y = paddle.to_tensor(np.random.random((1, 1)).astype('int64'))
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
            pred, _ = layer(x, y)
            pred = pred.numpy()
        else:
            pred = layer(x).numpy()
        loaded_pred = loaded_layer(x).numpy()
        self.assertTrue(
            np.array_equal(pred, loaded_pred),
            msg="Result diff when load and inference:\nlayer result:\n{}\n" \
                "loaded layer result:\n{}".format(pred, loaded_pred))

    def test_no_prune_to_static_after_train(self):
        layer = LinearNet(784, 1)

        train(layer)

541
        model_path = "test_no_prune_to_static_after_train/model"
542 543 544 545 546 547 548
        paddle.jit.save(layer, model_path)

        self.verify_inference_correctness(layer, model_path)

    def test_no_prune_to_static_no_train(self):
        layer = LinearNetWithInputSpec(784, 1)

549
        model_path = "test_no_prune_to_static_no_train/model"
550 551 552 553 554 555 556 557 558
        paddle.jit.save(layer, model_path)

        self.verify_inference_correctness(layer, model_path)

    def test_no_prune_no_to_static_after_train(self):
        layer = LinearNetNotDeclarative(784, 1)

        train(layer)

559
        model_path = "test_no_prune_no_to_static_after_train/model"
560 561 562 563 564 565 566 567 568 569 570 571 572
        paddle.jit.save(
            layer,
            model_path,
            input_spec=[InputSpec(
                shape=[None, 784], dtype='float32')])

        self.verify_inference_correctness(layer, model_path)

    def test_no_prune_no_to_static_after_train_with_examples(self):
        layer = LinearNetNotDeclarative(784, 1)

        example_inputs, _, _ = train(layer)

573 574
        model_path = "test_no_prune_no_to_static_after_train_with_examples/model"
        paddle.jit.save(layer=layer, path=model_path, input_spec=example_inputs)
575 576 577 578 579 580

        self.verify_inference_correctness(layer, model_path)

    def test_no_prune_no_to_static_no_train(self):
        layer = LinearNetNotDeclarative(784, 1)

581
        model_path = "test_no_prune_no_to_static_no_train/model"
582 583 584 585 586 587 588 589 590 591 592 593 594
        paddle.jit.save(
            layer,
            model_path,
            input_spec=[InputSpec(
                shape=[None, 784], dtype='float32')])

        self.verify_inference_correctness(layer, model_path)

    def test_prune_to_static_after_train(self):
        layer = LinerNetWithLabel(784, 1)

        out = train_with_label(layer)

595
        model_path = "test_prune_to_static_after_train/model"
596 597 598 599 600 601 602
        paddle.jit.save(
            layer,
            model_path,
            input_spec=[
                InputSpec(
                    shape=[None, 784], dtype='float32', name="image")
            ],
603
            output_spec=[out])
604 605 606 607 608 609

        self.verify_inference_correctness(layer, model_path, True)

    def test_prune_to_static_no_train(self):
        layer = LinerNetWithLabel(784, 1)

610
        model_path = "test_prune_to_static_no_train/model"
611 612
        # TODO: no train, cannot get output_spec var here
        # now only can use index
613
        output_spec = layer.forward.outputs[:1]
614 615 616 617 618 619 620
        paddle.jit.save(
            layer,
            model_path,
            input_spec=[
                InputSpec(
                    shape=[None, 784], dtype='float32', name="image")
            ],
621
            output_spec=output_spec)
622 623 624 625 626 627 628 629

        self.verify_inference_correctness(layer, model_path, True)

    def test_no_prune_input_spec_name_warning(self):
        layer = LinearNetWithInputSpec(784, 1)

        train(layer)

630
        model_path = "test_no_prune_input_spec_name_warning/model"
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
        paddle.jit.save(
            layer,
            model_path,
            input_spec=[InputSpec(
                shape=[None, 784], dtype='float32')])
        paddle.jit.save(
            layer,
            model_path,
            input_spec=[
                InputSpec(
                    shape=[None, 784], dtype='float32', name='feed_input')
            ])

        self.verify_inference_correctness(layer, model_path)

    def test_not_prune_output_spec_name_warning(self):
        layer = LinearNet(784, 1)

        train(layer)

651
        model_path = "test_not_prune_output_spec_name_warning/model"
Z
Zhou Wei 已提交
652
        out = paddle.to_tensor(np.random.random((1, 1)).astype('float'))
653
        paddle.jit.save(layer, model_path, output_spec=[out])
654 655 656 657 658 659

        self.verify_inference_correctness(layer, model_path)

    def test_prune_input_spec_name_error(self):
        layer = LinerNetWithLabel(784, 1)

660
        model_path = "test_prune_input_spec_name_error/model"
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
        with self.assertRaises(ValueError):
            paddle.jit.save(
                layer,
                model_path,
                input_spec=[InputSpec(
                    shape=[None, 784], dtype='float32')])
        with self.assertRaises(ValueError):
            paddle.jit.save(
                layer,
                model_path,
                input_spec=[
                    InputSpec(
                        shape=[None, 784], dtype='float32', name='feed_input')
                ])

    def test_prune_output_spec_name_error(self):
        layer = LinerNetWithLabel(784, 1)

        train_with_label(layer)

681
        model_path = "test_prune_to_static_after_train/model"
Z
Zhou Wei 已提交
682
        out = paddle.to_tensor(np.random.random((1, 1)).astype('float'))
683 684 685 686 687 688 689 690
        with self.assertRaises(ValueError):
            paddle.jit.save(
                layer,
                model_path,
                input_spec=[
                    InputSpec(
                        shape=[None, 784], dtype='float32', name="image")
                ],
691
                output_spec=[out])
692 693


694 695
class TestJitSaveLoadEmptyLayer(unittest.TestCase):
    def setUp(self):
696
        self.model_path = "jit_save_load_empty_layer/model"
697 698 699 700 701
        # enable dygraph mode
        paddle.disable_static()

    def test_save_load_empty_layer(self):
        layer = EmptyLayer()
Z
Zhou Wei 已提交
702
        x = paddle.to_tensor(np.random.random((10)).astype('float32'))
703 704 705 706 707 708 709 710 711
        out = layer(x)
        paddle.jit.save(layer, self.model_path)
        load_layer = paddle.jit.load(self.model_path)
        load_out = load_layer(x)
        self.assertTrue(np.array_equal(out, load_out))


class TestJitSaveLoadNoParamLayer(unittest.TestCase):
    def setUp(self):
712
        self.model_path = "jit_save_load_no_param_layer/model"
713 714 715 716 717
        # enable dygraph mode
        paddle.disable_static()

    def test_save_load_no_param_layer(self):
        layer = NoParamLayer()
Z
Zhou Wei 已提交
718 719
        x = paddle.to_tensor(np.random.random((5)).astype('float32'))
        y = paddle.to_tensor(np.random.random((5)).astype('float32'))
720 721 722 723 724 725 726
        out = layer(x, y)
        paddle.jit.save(layer, self.model_path)
        load_layer = paddle.jit.load(self.model_path)
        load_out = load_layer(x, y)
        self.assertTrue(np.array_equal(out, load_out))


727 728
if __name__ == '__main__':
    unittest.main()