Add unified RNN APIs (#26588)

* Add RNN related apis in paddl.nn
test=develop

* new rnn api, cell almost done

* add new progresses in rnn APIs for 2.0

* refine rnn APIs and docstrings.

* add unittets

* disable gpu tests when paddle is not compiled with cuda support

* remove unnecessary imports

* fix docstring

* add to no_sample wlist

* backport to python2 to avoid yield from

* add **kwargs, fix typos

* update docstrings for birnn

* rename argument for SimpleRNN and SimpleRNNCell, fix sample code

* add default value for initial_states in fluid.layers.birnn

Co-authored-by: guosheng <guosheng@baidu.com>
revert-26856-strategy_example2
Feiyu Chan 5 years ago committed by GitHub
parent f311d3c1cf
commit f4083010a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

File diff suppressed because it is too large Load Diff

@ -542,6 +542,7 @@ endif()
add_subdirectory(sequence) add_subdirectory(sequence)
add_subdirectory(dygraph_to_static) add_subdirectory(dygraph_to_static)
add_subdirectory(rnn)
if (WITH_MKLDNN) if (WITH_MKLDNN)
add_subdirectory(mkldnn) add_subdirectory(mkldnn)

@ -0,0 +1,6 @@
file(GLOB TEST_OPS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "test_*.py")
string(REPLACE ".py" "" TEST_OPS "${TEST_OPS}")
foreach(TEST_OP ${TEST_OPS})
py_test_modules(${TEST_OP} MODULES ${TEST_OP})
endforeach(TEST_OP)

@ -0,0 +1,13 @@
# 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.

@ -0,0 +1,51 @@
# 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.
import paddle
import numpy as np
def convert_params_for_cell(np_cell, paddle_cell):
state = np_cell.parameters
for k, v in paddle_cell.named_parameters():
v.set_value(state[k])
def convert_params_for_cell_static(np_cell, paddle_cell, place):
state = np_cell.parameters
for k, v in paddle_cell.named_parameters():
scope = paddle.static.global_scope()
tensor = scope.find_var(v.name).get_tensor()
tensor.set(state[k], place)
def convert_params_for_net(np_net, paddle_net):
for np_layer, paddle_layer in zip(np_net, paddle_net):
if hasattr(np_layer, "cell"):
convert_params_for_cell(np_layer.cell, paddle_layer.cell)
else:
convert_params_for_cell(np_layer.cell_fw, paddle_layer.cell_fw)
convert_params_for_cell(np_layer.cell_bw, paddle_layer.cell_bw)
def convert_params_for_net_static(np_net, paddle_net, place):
for np_layer, paddle_layer in zip(np_net, paddle_net):
if hasattr(np_layer, "cell"):
convert_params_for_cell_static(np_layer.cell, paddle_layer.cell,
place)
else:
convert_params_for_cell_static(np_layer.cell_fw,
paddle_layer.cell_fw, place)
convert_params_for_cell_static(np_layer.cell_bw,
paddle_layer.cell_bw, place)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,166 @@
# 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.
import paddle
paddle.framework.set_default_dtype("float64")
import numpy as np
import unittest
from rnn_numpy import SimpleRNNCell, LSTMCell, GRUCell
from convert import convert_params_for_cell
class TestSimpleRNNCell(unittest.TestCase):
def __init__(self, bias=True, place="cpu"):
super(TestSimpleRNNCell, self).__init__(methodName="runTest")
self.bias = bias
self.place = paddle.CPUPlace() if place == "cpu" \
else paddle.CUDAPlace(0)
def setUp(self):
paddle.disable_static(self.place)
rnn1 = SimpleRNNCell(16, 32, bias=self.bias)
rnn2 = paddle.nn.SimpleRNNCell(
16, 32, bias_ih_attr=self.bias, bias_hh_attr=self.bias)
convert_params_for_cell(rnn1, rnn2)
self.rnn1 = rnn1
self.rnn2 = rnn2
def test_with_initial_state(self):
rnn1 = self.rnn1
rnn2 = self.rnn2
x = np.random.randn(4, 16)
prev_h = np.random.randn(4, 32)
y1, h1 = rnn1(x, prev_h)
y2, h2 = rnn2(paddle.to_variable(x), paddle.to_variable(prev_h))
np.testing.assert_allclose(h1, h2.numpy(), atol=1e-8, rtol=1e-5)
def test_with_zero_state(self):
rnn1 = self.rnn1
rnn2 = self.rnn2
x = np.random.randn(4, 16)
y1, h1 = rnn1(x)
y2, h2 = rnn2(paddle.to_variable(x))
np.testing.assert_allclose(h1, h2.numpy(), atol=1e-8, rtol=1e-5)
def runTest(self):
self.test_with_initial_state()
self.test_with_zero_state()
class TestGRUCell(unittest.TestCase):
def __init__(self, bias=True, place="cpu"):
super(TestGRUCell, self).__init__(methodName="runTest")
self.bias = bias
self.place = paddle.CPUPlace() if place == "cpu" \
else paddle.CUDAPlace(0)
def setUp(self):
paddle.disable_static(self.place)
rnn1 = GRUCell(16, 32, bias=self.bias)
rnn2 = paddle.nn.GRUCell(
16, 32, bias_ih_attr=self.bias, bias_hh_attr=self.bias)
convert_params_for_cell(rnn1, rnn2)
self.rnn1 = rnn1
self.rnn2 = rnn2
def test_with_initial_state(self):
rnn1 = self.rnn1
rnn2 = self.rnn2
x = np.random.randn(4, 16)
prev_h = np.random.randn(4, 32)
y1, h1 = rnn1(x, prev_h)
y2, h2 = rnn2(paddle.to_variable(x), paddle.to_variable(prev_h))
np.testing.assert_allclose(h1, h2.numpy(), atol=1e-8, rtol=1e-5)
def test_with_zero_state(self):
rnn1 = self.rnn1
rnn2 = self.rnn2
x = np.random.randn(4, 16)
y1, h1 = rnn1(x)
y2, h2 = rnn2(paddle.to_variable(x))
np.testing.assert_allclose(h1, h2.numpy(), atol=1e-8, rtol=1e-5)
def runTest(self):
self.test_with_initial_state()
self.test_with_zero_state()
class TestLSTMCell(unittest.TestCase):
def __init__(self, bias=True, place="cpu"):
super(TestLSTMCell, self).__init__(methodName="runTest")
self.bias = bias
self.place = paddle.CPUPlace() if place == "cpu" \
else paddle.CUDAPlace(0)
def setUp(self):
rnn1 = LSTMCell(16, 32, bias=self.bias)
rnn2 = paddle.nn.LSTMCell(
16, 32, bias_ih_attr=self.bias, bias_hh_attr=self.bias)
convert_params_for_cell(rnn1, rnn2)
self.rnn1 = rnn1
self.rnn2 = rnn2
def test_with_initial_state(self):
rnn1 = self.rnn1
rnn2 = self.rnn2
x = np.random.randn(4, 16)
prev_h = np.random.randn(4, 32)
prev_c = np.random.randn(4, 32)
y1, (h1, c1) = rnn1(x, (prev_h, prev_c))
y2, (h2, c2) = rnn2(
paddle.to_variable(x),
(paddle.to_variable(prev_h), paddle.to_variable(prev_c)))
np.testing.assert_allclose(h1, h2.numpy(), atol=1e-8, rtol=1e-5)
np.testing.assert_allclose(c1, c2.numpy(), atol=1e-8, rtol=1e-5)
def test_with_zero_state(self):
rnn1 = self.rnn1
rnn2 = self.rnn2
x = np.random.randn(4, 16)
y1, (h1, c1) = rnn1(x)
y2, (h2, c2) = rnn2(paddle.to_variable(x))
np.testing.assert_allclose(h1, h2.numpy(), atol=1e-8, rtol=1e-5)
np.testing.assert_allclose(c1, c2.numpy(), atol=1e-8, rtol=1e-5)
def runTest(self):
self.test_with_initial_state()
self.test_with_zero_state()
def load_tests(loader, tests, pattern):
suite = unittest.TestSuite()
devices = ["cpu", "gpu"] if paddle.fluid.is_compiled_with_cuda() \
else ["cpu"]
for bias in [True, False]:
for device in devices:
for test_class in [TestSimpleRNNCell, TestGRUCell, TestLSTMCell]:
suite.addTest(test_class(bias, device))
return suite

File diff suppressed because it is too large Load Diff

@ -18,6 +18,7 @@
from .layer import norm from .layer import norm
from .functional import extension from .functional import extension
from .layer import common from .layer import common
from .layer import rnn
from .utils import weight_norm_hook from .utils import weight_norm_hook
from . import initializer from . import initializer
@ -26,6 +27,7 @@ __all__ = []
__all__ += norm.__all__ __all__ += norm.__all__
__all__ += extension.__all__ __all__ += extension.__all__
__all__ += common.__all__ __all__ += common.__all__
__all__ += rnn.__all__
__all__ += weight_norm_hook.__all__ __all__ += weight_norm_hook.__all__
# TODO: define alias in nn directory # TODO: define alias in nn directory
@ -136,6 +138,7 @@ from .layer.norm import InstanceNorm3d #DEFINE_ALIAS
from .layer.norm import BatchNorm1d #DEFINE_ALIAS from .layer.norm import BatchNorm1d #DEFINE_ALIAS
from .layer.norm import BatchNorm2d #DEFINE_ALIAS from .layer.norm import BatchNorm2d #DEFINE_ALIAS
from .layer.norm import BatchNorm3d #DEFINE_ALIAS from .layer.norm import BatchNorm3d #DEFINE_ALIAS
from .layer.rnn import *
# from .layer.rnn import RNNCell #DEFINE_ALIAS # from .layer.rnn import RNNCell #DEFINE_ALIAS
# from .layer.rnn import GRUCell #DEFINE_ALIAS # from .layer.rnn import GRUCell #DEFINE_ALIAS
# from .layer.rnn import LSTMCell #DEFINE_ALIAS # from .layer.rnn import LSTMCell #DEFINE_ALIAS

@ -177,6 +177,8 @@ from .pooling import pool2d #DEFINE_ALIAS
from .pooling import pool3d #DEFINE_ALIAS from .pooling import pool3d #DEFINE_ALIAS
from .pooling import adaptive_pool2d #DEFINE_ALIAS from .pooling import adaptive_pool2d #DEFINE_ALIAS
from .pooling import adaptive_pool3d #DEFINE_ALIAS from .pooling import adaptive_pool3d #DEFINE_ALIAS
from .rnn import rnn #DEFINE_ALIAS
from .rnn import birnn #DEFINE_ALIAS
from .pooling import avg_pool2d #DEFINE_ALIAS from .pooling import avg_pool2d #DEFINE_ALIAS
from .pooling import max_pool2d #DEFINE_ALIAS from .pooling import max_pool2d #DEFINE_ALIAS
from .pooling import avg_pool3d #DEFINE_ALIAS from .pooling import avg_pool3d #DEFINE_ALIAS

@ -12,10 +12,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# TODO: define function of recurrent neural network from paddle.fluid.layers.rnn import rnn, birnn
__all__ = [ __all__ = ['rnn', 'birnn']
# 'gru_unit',
# 'lstm',
# 'lstm_unit'
]

@ -20,6 +20,7 @@ from . import conv
from . import extension from . import extension
from . import activation from . import activation
from . import norm from . import norm
from . import rnn
from . import vision from . import vision
from . import distance from . import distance
from . import transformer from . import transformer
@ -30,6 +31,7 @@ from .conv import *
from .extension import * from .extension import *
from .activation import * from .activation import *
from .norm import * from .norm import *
from .rnn import *
from .vision import * from .vision import *
from .transformer import * from .transformer import *

File diff suppressed because it is too large Load Diff

@ -148,7 +148,20 @@
"Callback.on_eval_batch_end", "Callback.on_eval_batch_end",
"Callback.on_test_batch_begin", "Callback.on_test_batch_begin",
"Callback.on_test_batch_end", "Callback.on_test_batch_end",
"Model.prepare" "Model.prepare",
"SimpleRNNCell",
"SimpleRNNCell.forward",
"LSTMCell",
"LSTMCell.forward",
"GRUCell",
"GRUCell.forward",
"SimpleRNN",
"GRU",
"LSTM",
"RNN",
"BiRNN",
"RNNCellBase",
"RNNCellBase.get_initial_states"
], ],
"wlist_no_op_pass":[ "wlist_no_op_pass":[
"gelu", "gelu",

Loading…
Cancel
Save