From e409c7cefd35660e1027fe9d98747dd8eb4fc5fe Mon Sep 17 00:00:00 2001 From: Aurelius84 Date: Thu, 20 May 2021 19:31:57 +0800 Subject: [PATCH] [Dy2Stat]Support convert sublayers in Sequential Container (#32978) * Support convert sublayers in Sequential Container * remove paddle.jit.set_code_level --- .../dygraph_to_static/convert_call_func.py | 8 ++ .../dygraph_to_static/test_container.py | 91 +++++++++++++++++++ .../unittests/dygraph_to_static/test_list.py | 3 - 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 python/paddle/fluid/tests/unittests/dygraph_to_static/test_container.py diff --git a/python/paddle/fluid/dygraph/dygraph_to_static/convert_call_func.py b/python/paddle/fluid/dygraph/dygraph_to_static/convert_call_func.py index 7604be2d838..a621f68c654 100644 --- a/python/paddle/fluid/dygraph/dygraph_to_static/convert_call_func.py +++ b/python/paddle/fluid/dygraph/dygraph_to_static/convert_call_func.py @@ -26,6 +26,7 @@ import types import numpy import six +from paddle.fluid.dygraph.container import Sequential from paddle.fluid.dygraph.dygraph_to_static.convert_operators import convert_len from paddle.fluid.dygraph.dygraph_to_static.logging_utils import TranslatorLogger from paddle.fluid.dygraph.dygraph_to_static.program_translator import StaticFunction @@ -40,6 +41,9 @@ __all__ = ["convert_call"] BUILTIN_LIKELY_MODULES = [ collections, pdb, copy, inspect, re, six, numpy, logging ] +# The api(s) should be considered as plain function and convert +# them into static layer code. +PADDLE_NEED_CONVERT_APIS = [Sequential] translator_logger = TranslatorLogger() @@ -92,6 +96,10 @@ def is_unsupported(func): format(func)) return True + # NOTE: should be placed before `is_paddle_func` + if type(func) in PADDLE_NEED_CONVERT_APIS: + return False + if is_paddle_func(func): translator_logger.log( 2, diff --git a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_container.py b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_container.py new file mode 100644 index 00000000000..647c9e9672c --- /dev/null +++ b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_container.py @@ -0,0 +1,91 @@ +# Copyright (c) 2021 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. + +import paddle +import unittest +import numpy as np + + +class BufferLayers(paddle.nn.Layer): + def __init__(self, out_channel): + super(BufferLayers, self).__init__() + self.out_channel = out_channel + + def forward(self, x): + mean = paddle.mean(x) + if mean < 0.: + x = x * self._mask() + + out = x - mean + return out + + def _mask(self): + return paddle.to_tensor(np.zeros([self.out_channel], 'float32')) + + +class SequentialNet(paddle.nn.Layer): + def __init__(self, sub_layer, in_channel, out_channel): + super(SequentialNet, self).__init__() + self.layer = paddle.nn.Sequential( + ('l1', paddle.nn.Linear(in_channel, in_channel)), + ('l2', paddle.nn.Linear(in_channel, out_channel)), + ('l3', sub_layer(out_channel))) + + def forward(self, x): + out = self.layer(x) + return out + + +class TestSequential(unittest.TestCase): + def setUp(self): + paddle.set_device('cpu') + self.seed = 2021 + + def _init_seed(self): + paddle.seed(self.seed) + np.random.seed(self.seed) + + def _run(self, to_static): + self._init_seed() + net = SequentialNet(BufferLayers, 10, 3) + if to_static: + net = paddle.jit.to_static(net) + x = paddle.rand([16, 10], 'float32') + out = net(x) + if to_static: + load_out = self._test_load(net, x) + self.assertTrue( + np.allclose(load_out, out), + msg='load_out is {}\st_out is {}'.format(load_out, out)) + + return out + + def test_train(self): + paddle.jit.set_code_level(100) + dy_out = self._run(to_static=False) + st_out = self._run(to_static=True) + self.assertTrue( + np.allclose(dy_out, st_out), + msg='dygraph_res is {}\nstatic_res is {}'.format(dy_out, st_out)) + + def _test_load(self, net, x): + model_path = './sequential_net' + paddle.jit.save(net, model_path) + load_net = paddle.jit.load(model_path) + out = load_net(x) + return out + + +if __name__ == '__main__': + unittest.main() diff --git a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_list.py b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_list.py index e630c2b9c6f..8da4e200cfc 100644 --- a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_list.py +++ b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_list.py @@ -62,9 +62,6 @@ def test_list_append_in_for_loop(x, iter_num): return a[0] -paddle.jit.set_code_level(100) - - def test_list_append_in_for_subscript(x): x = fluid.dygraph.to_variable(x) iter_num = paddle.shape(x)[0] -- GitLab