未验证 提交 1e59cf97 编写于 作者: Y Yiqun Liu 提交者: GitHub

Polish the English documentation DynamicRNN (#20453)

* Refine the main comment of DynamicRNN.

* Refine the documentation of DynamicRNN's step_input function.

* Refine the documentation of DynamicRNN's static_input function.

* Refine the documentation of DynamicRNN's block function.

* Refine the documentation of DynamicRNN's memory function.

* Refine the documentation of DynamicRNN's update_memory and output function.

* Refine the code format and remove the method list.

* Refine the documentation of DynamicRNN's __call__ function.
test=develop
test=document_fix

* Minor modification.
test=develop
test=document_fix

* Fix some typo.

* Update API.spec.
test=develop
test=document_fix

* Refine the English according to the comments.

* Update API.spec.
test=develop
test=document_fix

* Fix some typo.

* Update API.spec.
上级 2213ae6b
...@@ -363,14 +363,14 @@ paddle.fluid.layers.IfElse.false_block (ArgSpec(args=['self'], varargs=None, key ...@@ -363,14 +363,14 @@ paddle.fluid.layers.IfElse.false_block (ArgSpec(args=['self'], varargs=None, key
paddle.fluid.layers.IfElse.input (ArgSpec(args=['self', 'x'], varargs=None, keywords=None, defaults=None), ('document', '6adf97f83acf6453d4a6a4b1070f3754')) paddle.fluid.layers.IfElse.input (ArgSpec(args=['self', 'x'], varargs=None, keywords=None, defaults=None), ('document', '6adf97f83acf6453d4a6a4b1070f3754'))
paddle.fluid.layers.IfElse.output (ArgSpec(args=['self'], varargs='outs', keywords=None, defaults=None), ('document', '6adf97f83acf6453d4a6a4b1070f3754')) paddle.fluid.layers.IfElse.output (ArgSpec(args=['self'], varargs='outs', keywords=None, defaults=None), ('document', '6adf97f83acf6453d4a6a4b1070f3754'))
paddle.fluid.layers.IfElse.true_block (ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None), ('document', '6adf97f83acf6453d4a6a4b1070f3754')) paddle.fluid.layers.IfElse.true_block (ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None), ('document', '6adf97f83acf6453d4a6a4b1070f3754'))
paddle.fluid.layers.DynamicRNN ('paddle.fluid.layers.control_flow.DynamicRNN', ('document', 'b71e87285dbd4a43a6cc4f8a473245e6')) paddle.fluid.layers.DynamicRNN ('paddle.fluid.layers.control_flow.DynamicRNN', ('document', 'cc7209c675ec5841efd10c9d2f1028d9'))
paddle.fluid.layers.DynamicRNN.__init__ (ArgSpec(args=['self', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '6adf97f83acf6453d4a6a4b1070f3754')) paddle.fluid.layers.DynamicRNN.__init__ (ArgSpec(args=['self', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '6adf97f83acf6453d4a6a4b1070f3754'))
paddle.fluid.layers.DynamicRNN.block (ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None), ('document', '6d3e0a5d9aa519a9773a36e1620ea9b7')) paddle.fluid.layers.DynamicRNN.block (ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None), ('document', '7935170393923803885fa461c3f3cfbc'))
paddle.fluid.layers.DynamicRNN.memory (ArgSpec(args=['self', 'init', 'shape', 'value', 'need_reorder', 'dtype'], varargs=None, keywords=None, defaults=(None, None, 0.0, False, 'float32')), ('document', '57cdd0a63747f4c670cdb9d250ceb7e1')) paddle.fluid.layers.DynamicRNN.memory (ArgSpec(args=['self', 'init', 'shape', 'value', 'need_reorder', 'dtype'], varargs=None, keywords=None, defaults=(None, None, 0.0, False, 'float32')), ('document', '904250e0e51498e5c52711e667c20941'))
paddle.fluid.layers.DynamicRNN.output (ArgSpec(args=['self'], varargs='outputs', keywords=None, defaults=None), ('document', 'b439a176a3328de8a75bdc5c08eece4a')) paddle.fluid.layers.DynamicRNN.output (ArgSpec(args=['self'], varargs='outputs', keywords=None, defaults=None), ('document', 'eccd774fb93665e51fb38bfb84d78b52'))
paddle.fluid.layers.DynamicRNN.static_input (ArgSpec(args=['self', 'x'], varargs=None, keywords=None, defaults=None), ('document', '55ab9c562edd7dabec0bd6fd6c1a28cc')) paddle.fluid.layers.DynamicRNN.static_input (ArgSpec(args=['self', 'x'], varargs=None, keywords=None, defaults=None), ('document', 'a766b9ea54014d1af913b0d39d7fb010'))
paddle.fluid.layers.DynamicRNN.step_input (ArgSpec(args=['self', 'x', 'level'], varargs=None, keywords=None, defaults=(0,)), ('document', '4b300851b5201891d0e11c406e4c7d07')) paddle.fluid.layers.DynamicRNN.step_input (ArgSpec(args=['self', 'x', 'level'], varargs=None, keywords=None, defaults=(0,)), ('document', '70081f137db4d215b302e49b5db33353'))
paddle.fluid.layers.DynamicRNN.update_memory (ArgSpec(args=['self', 'ex_mem', 'new_mem'], varargs=None, keywords=None, defaults=None), ('document', '5d83987da13b98363d6a807a52d8024f')) paddle.fluid.layers.DynamicRNN.update_memory (ArgSpec(args=['self', 'ex_mem', 'new_mem'], varargs=None, keywords=None, defaults=None), ('document', 'b416c1c4a742a86379887b092cf7f2f0'))
paddle.fluid.layers.StaticRNN ('paddle.fluid.layers.control_flow.StaticRNN', ('document', '4b0befc7f1ca7f11a459939f09c24d9a')) paddle.fluid.layers.StaticRNN ('paddle.fluid.layers.control_flow.StaticRNN', ('document', '4b0befc7f1ca7f11a459939f09c24d9a'))
paddle.fluid.layers.StaticRNN.__init__ (ArgSpec(args=['self', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '6adf97f83acf6453d4a6a4b1070f3754')) paddle.fluid.layers.StaticRNN.__init__ (ArgSpec(args=['self', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '6adf97f83acf6453d4a6a4b1070f3754'))
paddle.fluid.layers.StaticRNN.memory (ArgSpec(args=['self', 'init', 'shape', 'batch_ref', 'init_value', 'init_batch_dim_idx', 'ref_batch_dim_idx'], varargs=None, keywords=None, defaults=(None, None, None, 0.0, 0, 1)), ('document', 'dcacaa7f1953e89ef5c9e0f9f37c5470')) paddle.fluid.layers.StaticRNN.memory (ArgSpec(args=['self', 'init', 'shape', 'batch_ref', 'init_value', 'init_batch_dim_idx', 'ref_batch_dim_idx'], varargs=None, keywords=None, defaults=(None, None, None, 0.0, 0, 1)), ('document', 'dcacaa7f1953e89ef5c9e0f9f37c5470'))
......
...@@ -2002,44 +2002,68 @@ class IfElse(object): ...@@ -2002,44 +2002,68 @@ class IfElse(object):
class DynamicRNN(object): class DynamicRNN(object):
""" """
The dynamic RNN can process a batch of sequence data. The length of each **Note: the input of this class should be LoDTensor which holds the
sample sequence can be different. This API automatically process them in information of variable-length sequences. If the input is fixed-length Tensor,
batch. please use StaticRNN (fluid.layers.** :ref:`api_fluid_layers_StaticRNN` **) for
better performance.**
DynamicRNN can process a minibatch of variable-length sequences.
The length of each sample can be different and is recorded in LoD.
In DynamicRNN, an input sequence will be unfolded into time steps and users
can define how to process each time step in :code:`block()` .
The total number of time steps is determined by the longest sequence.
DynamicRNN will not pad all sequences to the same length, instead it will
sort the sequences internally by the sequence length in descending order.
The input sequences will be shrinked because only sequences of which the
length is larger than the time step will participate the remaining calculation.
If defined :code:`drnn = DynamicRNN()`, then users can call :code:`drnn()`
to obtain the result sequences. It is a LoDTensor gained by merging all
time steps's output. When RNN's input sequence x meets :code:`x.lod_level == 1`,
the output LoDTensor will have the same LoD with x. The result of :code:`drnn()`
includes RNN's outputs of all time steps, users can call
:ref:`api_fluid_layers_sequence_last_step` to extract the data of the last time step.
Warning:
Currently it is not supported to set :code:`is_sparse = True` of any
layers defined within DynamicRNN's :code:`block` function.
The input lod must be set. Please reference to `lod_tensor`. Args:
name (str, optional): The default value is None. Normally there is no
The dynamic RNN will unfold sequence into timesteps. Users need to define need for user to set this property. For more information,
how to process each time step during the :code:`with` block. please refer to :ref:`api_guide_Name` .
The `memory` is used staging data cross time step. The initial value of
memory can be zero or another variable.
The dynamic RNN can mark multiple variables as its output. Use `drnn()` to
get the output sequence.
NOTES:
Currently it is not supported that setting is_sparse to True of any
layers within DynamicRNN.
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import paddle.fluid as fluid
sentence = fluid.layers.data(name='sentence', shape=[1], dtype='int64', lod_level=1) sentence = fluid.data(name='sentence', shape=[None, 32], dtype='float32', lod_level=1)
embedding = fluid.layers.embedding(input=sentence, size=[65536, 32], is_sparse=True) encoder_proj = fluid.data(name='encoder_proj', shape=[None, 32], dtype='float32', lod_level=1)
decoder_boot = fluid.data(name='boot', shape=[None, 10], dtype='float32')
drnn = fluid.layers.DynamicRNN()
with drnn.block(): drnn = fluid.layers.DynamicRNN()
word = drnn.step_input(embedding) with drnn.block():
prev = drnn.memory(shape=[200]) # Set sentence as RNN's input, each time step processes a word from the sentence
hidden = fluid.layers.fc(input=[word, prev], size=200, act='relu') current_word = drnn.step_input(sentence)
drnn.update_memory(prev, hidden) # set prev to hidden # Set encode_proj as RNN's static input
drnn.output(hidden) encoder_word = drnn.static_input(encoder_proj)
# Initialize memory with boot_memory, which need reorder according to RNN's input sequences
# Get the last time step of rnn. It is the encoding result. memory = drnn.memory(init=decoder_boot, need_reorder=True)
rnn_output = drnn() fc_1 = fluid.layers.fc(input=encoder_word, size=30)
last = fluid.layers.sequence_last_step(rnn_output) fc_2 = fluid.layers.fc(input=current_word, size=30)
decoder_inputs = fc_1 + fc_2
hidden, _, _ = fluid.layers.gru_unit(input=decoder_inputs, hidden=memory, size=30)
# Update memory with hidden
drnn.update_memory(ex_mem=memory, new_mem=hidden)
out = fluid.layers.fc(input=hidden, size=10, bias_attr=True, act='softmax')
# Set hidden and out as RNN's outputs
drnn.output(hidden, out)
# Get RNN's result
hidden, out = drnn()
# Get RNN's result of the last time step
last = fluid.layers.sequence_last_step(out)
""" """
BEFORE_RNN = 0 BEFORE_RNN = 0
IN_RNN = 1 IN_RNN = 1
...@@ -2063,14 +2087,94 @@ class DynamicRNN(object): ...@@ -2063,14 +2087,94 @@ class DynamicRNN(object):
def step_input(self, x, level=0): def step_input(self, x, level=0):
""" """
Mark a sequence as a dynamic RNN input. This function is used to set sequence x as DynamicRNN's input.
The maximum sequence length in x determines the number of time steps
the RNN unit will be executed. DynamicRNN can take multiple inputs.
When all inputs' :code:`lod_level` are 1, all inputs should hold the
same LoD. When :code:`x.lod_level >= 2` , the input sequence will be
unfold along specified level, and the slice of each time step is a
LoDTensor whose lod_level is :code:`x.lod_level - level - 1` .
In this case, the specified LoD level of multiple inputs should be the same.
- Case 1:
.. code-block:: text
# input, where Si is slice data of shape [1, N]
level = 0
x.lod = [[2, 1, 3]]
x.shape = [6, N]
x.data = [[S0],
[S0],
[S1],
[S2],
[S2],
[S2]]
# output
# step 0, time step data of 3 sequences
out.lod = [[]]
out.shape = [3, N]
out.data = [[S2],
[S0],
[S1]]
# step 1, time step data of 2 sequences
out.lod = [[]]
out.shape = [2, N]
out.data = [[S2],
[S0]]
# step 2, time step data of 1 sequences
out.lod = [[]]
out.shape = [1, N]
out.data = [[S2]]
Args: Args:
x (Variable): The input sequence which should have lod information. x (Variable): The input LoDTensor which holds information of a
level (int): The level of lod used to split steps. Default: 0. minibatch of variable-length sequences and should meet :code:`x.lod_level >= 1` .
When RNN has multiple inputs, the first dimension should match
across all inputs, but other shape components may differ.
Optional data types are: bool, float16, float32, float64, int8, int16, int32, int64, uint8.
level (int, optional): The level of lod used to split steps.
It should be in range :math:`[0, x.lod\_level)` . The default value is 0.
Returns: Returns:
The current timestep in the input sequence. Variable: The current time step in the input sequence. If there are :code:`num_sequences` \
sequences in x whose length is larger than :code:`step_idx` , the returned Variable \
will only hold the :code:`step_idx` -th time step of those `num_sequences` sequences. \
The data type is the same as input. If :code:`x.lod_level == 1` , the return value is \
a Tensor of shape :math:`\{num\_sequences, x.shape[1], ...\}` , or it will \
be a variable-length LoDTensor.
Raises:
ValueError: When :code:`step_input()` is called outside :code:`block()` .
TypeError: When x is not a Variable.
Examples:
.. code-block:: python
import paddle.fluid as fluid
sentence = fluid.data(name='sentence', shape=[None, 1], dtype='int64', lod_level=1)
embedding = fluid.layers.embedding(input=sentence, size=[65536, 32], is_sparse=True)
drnn = fluid.layers.DynamicRNN()
with drnn.block():
# Set embedding as RNN's input, each time step processes a word from the sentence
word = drnn.step_input(embedding)
# Initialize memory to a Tensor whose value is 0, shape=[batch_size, 200],
# where batch_size is the number of sequences in embedding.
memory = drnn.memory(shape=[200])
hidden = fluid.layers.fc(input=[word, memory], size=200, act='relu')
# Update memory to hidden
drnn.update_memory(ex_mem=memory, new_mem=hidden)
# Set hidden as RNN's output
drnn.output(hidden)
# Get RNN's result
rnn_output = drnn()
""" """
self._assert_in_rnn_block_("step_input") self._assert_in_rnn_block_("step_input")
if not isinstance(x, Variable): if not isinstance(x, Variable):
...@@ -2117,38 +2221,129 @@ class DynamicRNN(object): ...@@ -2117,38 +2221,129 @@ class DynamicRNN(object):
def static_input(self, x): def static_input(self, x):
""" """
Mark a variable as a RNN input. The input will not be scattered into This function is used to set x as DynamicRNN's static input. It is optional.
time steps. It is optional.
- Case 1, set static input with LoD
.. code-block:: text
# RNN's input is the same as the case listed in step_input
# static input, where Si is slice data of shape [1, M]
x.lod = [[3, 1, 2]]
x.shape = [6, M]
x.data = [[S0],
[S0],
[S0],
[S1],
[S2],
[S2]]
# step 0, batch data corresponding to the 3 input sequences
out.lod = [[2, 3, 1]]
out.shape = [6, M]
out.data = [[S2],
[S2],
[S0],
[S0],
[S0],
[S1]]
# step 1, batch data corresponding to the 2 input sequences
out.lod = [[2, 3]]
out.shape = [5, M]
out.data = [[S2],
[S2],
[S0],
[S0],
[S0]]
# step 2, batch data corresponding to the 1 input sequences
out.lod = [[2]]
out.shape = [2, M]
out.data = [[S2],
[S2]]
- Case 2, set static input without LoD
.. code-block:: text
# RNN's input is the same as the case listed in step_input
# static input, where Si is slice data of shape [1, M]
x.lod = [[]]
x.shape = [3, M]
x.data = [[S0],
[S1],
[S2]]
# step 0, batch data corresponding to the 3 input sequences
out.lod = [[]]
out.shape = [3, M]
out.data = [[S2],
[S0],
[S1]]
# step 1, batch data corresponding to the 2 input sequences
out.lod = [[]]
out.shape = [2, M]
out.data = [[S2],
[S0]]
# step 2, batch data corresponding to the 1 input sequences
out.lod = [[]]
out.shape = [1, M]
out.data = [[S2]]
Args: Args:
x (Variable): The input variable. x (Variable): The static input LoDTensor which should hold the same number of sequences
as RNN's input (the input LoDTensor set by :code:`step_input()` ). If the LoD is None,
the input x will be treated as a minibatch with :code:`x.shape[0]` sequences of length 1.
Optional data types are: bool, float16, float32, float64, int8, int16, int32, int64, uint8.
Returns: Returns:
The input variable that can access in RNN. Variable: The input LoDTensor after sorted and shrinked. If there are :code:`num_sequences` \
sequences in RNN's input LoDTensor whose length is larger than :code:`step_idx` , \
the static input Tensor will be sorted to the same order as RNN's input and \
will only retain data corresponding to those :code:`num_sequences` sequences. \
The data type is the same as input. If :code:`x.lod == None` , the return value is \
a Tensor of shape :math:`\{num\_sequences, x.shape[1], ...\}` , or it will \
be a variable-length LoDTensor.
Raises:
ValueError: When :code:`static_input()` is called outside :code:`block()` .
TypeError: When x is not a Variable.
RuntimeError: When :code:`static_input()` is called before :code:`step_input()` .
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import paddle.fluid as fluid
sentence = fluid.layers.data(name='sentence', dtype='float32', shape=[32], lod_level=1) sentence = fluid.data(name='sentence', shape=[None, 32], dtype='float32', lod_level=1)
encoder_proj = fluid.layers.data(name='encoder_proj', dtype='float32', shape=[32], lod_level=1) encoder_proj = fluid.data(name='encoder_proj', shape=[None, 32], dtype='float32', lod_level=1)
decoder_boot = fluid.layers.data(name='boot', dtype='float32', shape=[10], lod_level=1) decoder_boot = fluid.data(name='boot', shape=[None, 10], dtype='float32')
drnn = fluid.layers.DynamicRNN() drnn = fluid.layers.DynamicRNN()
with drnn.block(): with drnn.block():
current_word = drnn.step_input(sentence) # Set sentence as RNN's input, each time step processes a word from the sentence
encoder_word = drnn.static_input(encoder_proj) current_word = drnn.step_input(sentence)
hidden_mem = drnn.memory(init=decoder_boot, need_reorder=True) # Set encode_proj as RNN's static input
fc_1 = fluid.layers.fc(input=encoder_word, size=30, bias_attr=False) encoder_word = drnn.static_input(encoder_proj)
fc_2 = fluid.layers.fc(input=current_word, size=30, bias_attr=False) # Initialize memory with boot_memory, which need reorder according to RNN's input sequences
decoder_inputs = fc_1 + fc_2 memory = drnn.memory(init=decoder_boot, need_reorder=True)
h, _, _ = fluid.layers.gru_unit(input=decoder_inputs, hidden=hidden_mem, size=30) fc_1 = fluid.layers.fc(input=encoder_word, size=30)
drnn.update_memory(hidden_mem, h) fc_2 = fluid.layers.fc(input=current_word, size=30)
out = fluid.layers.fc(input=h, size=10, bias_attr=True, act='softmax') decoder_inputs = fc_1 + fc_2
drnn.output(out) hidden, _, _ = fluid.layers.gru_unit(input=decoder_inputs, hidden=memory, size=30)
# Update memory with hidden
rnn_output = drnn() drnn.update_memory(ex_mem=memory, new_mem=hidden)
out = fluid.layers.fc(input=hidden, size=10, bias_attr=True, act='softmax')
# Set out as RNN's output
drnn.output(out)
# Get RNN's result
rnn_output = drnn()
""" """
self._assert_in_rnn_block_("static_input") self._assert_in_rnn_block_("static_input")
if not isinstance(x, Variable): if not isinstance(x, Variable):
...@@ -2172,7 +2367,12 @@ class DynamicRNN(object): ...@@ -2172,7 +2367,12 @@ class DynamicRNN(object):
@signature_safe_contextmanager @signature_safe_contextmanager
def block(self): def block(self):
""" """
The block for user to define operators in RNN. The function is used to list the operations executed during
each time step in RNN. The operation list will be executed :code:`max_sequence_len`
times (where :code:`max_sequence_len` is the maximum length of RNN's input sequences).
Raises:
ValueError: When :code:`block()` is called multi-times.
""" """
if self.status != DynamicRNN.BEFORE_RNN: if self.status != DynamicRNN.BEFORE_RNN:
raise ValueError("rnn.block() can only be invoke once") raise ValueError("rnn.block() can only be invoke once")
...@@ -2201,7 +2401,16 @@ class DynamicRNN(object): ...@@ -2201,7 +2401,16 @@ class DynamicRNN(object):
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
""" """
Get the output of RNN. This API should only be invoked after RNN.block() This function is used to get the output sequneces of DynamicRNN.
Args:
None
Returns:
Variable or Variable list: RNN's output sequences.
Raises:
ValueError: When :code:`__call__()` is called before :code:`block()` .
""" """
if self.status != DynamicRNN.AFTER_RNN: if self.status != DynamicRNN.AFTER_RNN:
raise ValueError(("Output of the dynamic RNN can only be visited " raise ValueError(("Output of the dynamic RNN can only be visited "
...@@ -2218,62 +2427,89 @@ class DynamicRNN(object): ...@@ -2218,62 +2427,89 @@ class DynamicRNN(object):
need_reorder=False, need_reorder=False,
dtype='float32'): dtype='float32'):
""" """
Create a memory variable for dynamic rnn. Create a memory Variable for DynamicRNN to deliver data cross time steps.
It can be initialized by an existing Tensor or a constant Tensor of given
dtype and shape.
If the :code:`init` is not None, :code:`memory` will be initialized by Args:
this variable. The :code:`need_reorder` is used to reorder the memory as init (Variable, optional): LoDTensor used to initialize the memory.
the input variable. It should be set to true when the initialized memory If init is not None, it should hold the same number of sequences
depends on the input sample. as RNN's input (the input LoDTensor set by :code:`step_input()` )
and the memory will be initialized to it. If init's LoD is None,
it will be treated as a minibatch with :code:`init.shape[0]` sequences
of length 1. The default value is None.
shape (list|tuple, optional): When init is None, it is used to specify
the memory's shape. Note that the shape does not include the batch_size.
If setting shape to :math:`\{D_1, D_2, ...\}` , the shape of memory Tensor
will be :math:`\{batch\_size, D_1, D_2, ...\}` , where batch_size is
determined by RNN's input sequences. The default value is None.
value (float, optional): When init is None, it is used as initalized value
of memory. The default value is 0.0.
need_reorder (bool, optional): When init is not None, it determines whether
the memory needs to reorder like the RNN's input sequeneces. It should be
set to True when the initialized memory depends on the order of input samples.
The default value is False.
dtype (str|numpy.dtype, optional): When init is None, it is used to set the
data type of memory. The default value is "float32". Optional data types
are: "float32", "float64", "int32", "int64".
Returns:
Variable: The memory LoDTensor after shrinked. If there are :code:`num_sequences` \
sequences in RNN's input LoDTensor whose length is larger than :code:`step_idx` , \
the memory Tensor also need to be shrinked and will only retain data \
corresponding to those :code:`num_sequences` sequences.
Raises:
ValueError: When :code:`memory()` is called outside :code:`block()` .
TypeError: When init is set and is not a Variable.
ValueError: When :code:`memory()` is called before :code:`step_input()` .
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import paddle.fluid as fluid
sentence = fluid.layers.data(name='sentence', shape=[32], dtype='float32', lod_level=1) sentence = fluid.data(name='sentence', shape=[None, 32], dtype='float32', lod_level=1)
boot_memory = fluid.layers.data(name='boot', shape=[10], dtype='float32', lod_level=1) boot_memory = fluid.data(name='boot', shape=[None, 10], dtype='float32')
drnn = fluid.layers.DynamicRNN()
with drnn.block():
word = drnn.step_input(sentence)
memory = drnn.memory(init=boot_memory, need_reorder=True)
hidden = fluid.layers.fc(input=[word, memory], size=10, act='tanh')
drnn.update_memory(ex_mem=memory, new_mem=hidden)
drnn.output(hidden)
rnn_output = drnn() drnn = fluid.layers.DynamicRNN()
with drnn.block():
# Set sentence as RNN's input, each time step processes a word from the sentence
word = drnn.step_input(sentence)
# Initialize memory with boot_memory, which need reorder according to RNN's input sequences
memory = drnn.memory(init=boot_memory, need_reorder=True)
hidden = fluid.layers.fc(input=[word, memory], size=10, act='tanh')
# Update memory with hidden
drnn.update_memory(ex_mem=memory, new_mem=hidden)
# Set hidden as RNN's output
drnn.output(hidden)
# Get RNN's result
rnn_output = drnn()
Otherwise, if :code:`shape`, :code:`value`, :code:`dtype` are set, the
:code:`memory` will be initialized by this :code:`value`.
Examples: Examples:
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import paddle.fluid as fluid
sentence = fluid.layers.data(name='sentence', dtype='float32', shape=[32], lod_level=1) sentence = fluid.data(name='sentence', shape=[None, 32], dtype='float32', lod_level=1)
drnn = fluid.layers.DynamicRNN() drnn = fluid.layers.DynamicRNN()
with drnn.block(): with drnn.block():
word = drnn.step_input(sentence) # Set sentence as RNN's input, each time step processes a word from the sentence
memory = drnn.memory(shape=[10], dtype='float32', value=0) word = drnn.step_input(sentence)
hidden = fluid.layers.fc(input=[word, memory], size=10, act='tanh') # Initialize memory to a Tensor whose value is 0, shape=[batch_size, 10],
drnn.update_memory(ex_mem=memory, new_mem=hidden) # where batch_size is the number of sequences in sentence.
drnn.output(hidden) memory = drnn.memory(shape=[10], dtype='float32', value=0)
hidden = fluid.layers.fc(input=[word, memory], size=10, act='tanh')
rnn_output = drnn() # Update memory with hidden
drnn.update_memory(ex_mem=memory, new_mem=hidden)
# Set hidden as RNN's output
Args: drnn.output(hidden)
init(Variable|None): The initialized variable.
shape(list|tuple): The memory shape. The shape does not contain batch_size. # Get RNN's result
value(float): the initalized value. rnn_output = drnn()
need_reorder(bool): True if the initialized memory depends on the input sample.
dtype(str|numpy.dtype): The data type of the initialized memory.
Returns:
The memory variable.
""" """
self._assert_in_rnn_block_('memory') self._assert_in_rnn_block_('memory')
self._init_zero_idx_() self._init_zero_idx_()
...@@ -2344,15 +2580,21 @@ class DynamicRNN(object): ...@@ -2344,15 +2580,21 @@ class DynamicRNN(object):
def update_memory(self, ex_mem, new_mem): def update_memory(self, ex_mem, new_mem):
""" """
Update the memory from ex_mem to new_mem. NOTE that the shape and data Update the memory which need to be delivered across time steps.
type of :code:`ex_mem` and :code:`new_mem` must be same.
Args: Args:
ex_mem(Variable): the memory variable. ex_mem (Variable): The memory data of previous time step.
new_mem(Variable): the plain variable generated in RNN block. new_mem (Variable): The new memory data produced in current time step.
The shape and data type of ex_mem and new_mem should be the same.
Returns: Returns:
None None
Raises:
ValueError: When :code:`update_memory()` is called outside :code:`block()` .
TypeError: When :code:`ex_mem` or :code:`new_mem` is not a Variable.
ValueError: When :code:`ex_mem` is defined by :code:`memory()` .
ValueError: When :code:`update_memory()` is called before :code:`step_input()` .
""" """
self._assert_in_rnn_block_('update_memory') self._assert_in_rnn_block_('update_memory')
if not isinstance(ex_mem, Variable): if not isinstance(ex_mem, Variable):
...@@ -2372,13 +2614,17 @@ class DynamicRNN(object): ...@@ -2372,13 +2614,17 @@ class DynamicRNN(object):
def output(self, *outputs): def output(self, *outputs):
""" """
Mark the RNN output variables. This function is used to set :code:`outputs` as RNN's output.
Args: Args:
outputs: The output variables. *outputs (Variable ...): The output Tensor. DynamicRNN can mark multiple
Variables as its output.
Returns: Returns:
None None
Raises:
ValueError: When :code:`output()` is called outside :code:`block()` .
""" """
self._assert_in_rnn_block_('output') self._assert_in_rnn_block_('output')
parent_block = self._parent_block_() parent_block = self._parent_block_()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册