Skip to content

Commit 2ad6c8b

Browse files
authored
Merge pull request #7694 from pkuyym/fix-7691
Add python wrapper for sequence reshape operator.
2 parents 4f93331 + 811c4ee commit 2ad6c8b

File tree

3 files changed

+104
-37
lines changed

3 files changed

+104
-37
lines changed

doc/api/v2/fluid/layers.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,8 @@ l2_normalize
504504
------------
505505
.. autofunction:: paddle.v2.fluid.layers.l2_normalize
506506
:noindex:
507+
508+
sequence_reshape
509+
----------------
510+
.. autofunction:: paddle.v2.fluid.layers.sequence_reshape
511+
:noindex:

python/paddle/v2/fluid/layers/nn.py

Lines changed: 91 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
'batch_norm', 'beam_search_decode', 'conv2d_transpose', 'sequence_expand',
2929
'lstm_unit', 'reduce_sum', 'reduce_mean', 'reduce_max', 'reduce_min',
3030
'sequence_first_step', 'sequence_last_step', 'dropout', 'split',
31-
'l2_normalize', 'matmul', 'warpctc'
31+
'l2_normalize', 'matmul', 'warpctc', 'sequence_reshape'
3232
]
3333

3434

@@ -213,33 +213,33 @@ def dynamic_lstm(input,
213213
(https://arxiv.org/pdf/1402.1128.pdf), the formula is as follows:
214214
215215
.. math::
216-
217-
i_t & = \sigma(W_{ix}x_{t} + W_{ih}h_{t-1} + W_{ic}c_{t-1} + b_i)
218216
219-
f_t & = \sigma(W_{fx}x_{t} + W_{fh}h_{t-1} + W_{fc}c_{t-1} + b_f)
217+
i_t & = \sigma(W_{ix}x_{t} + W_{ih}h_{t-1} + W_{ic}c_{t-1} + b_i)
220218
221-
\\tilde{c_t} & = act_g(W_{cx}x_t + W_{ch}h_{t-1} + b_c)
219+
f_t & = \sigma(W_{fx}x_{t} + W_{fh}h_{t-1} + W_{fc}c_{t-1} + b_f)
222220
223-
o_t & = \sigma(W_{ox}x_{t} + W_{oh}h_{t-1} + W_{oc}c_t + b_o)
221+
\\tilde{c_t} & = act_g(W_{cx}x_t + W_{ch}h_{t-1} + b_c)
224222
225-
c_t & = f_t \odot c_{t-1} + i_t \odot \\tilde{c_t}
223+
o_t & = \sigma(W_{ox}x_{t} + W_{oh}h_{t-1} + W_{oc}c_t + b_o)
224+
225+
c_t & = f_t \odot c_{t-1} + i_t \odot \\tilde{c_t}
226226
227227
h_t & = o_t \odot act_h(c_t)
228228
229-
where the :math:`W` terms denote weight matrices (e.g. :math:`W_{xi}` is
229+
where the :math:`W` terms denote weight matrices (e.g. :math:`W_{xi}` is
230230
the matrix of weights from the input gate to the input), :math:`W_{ic}, \
231-
W_{fc}, W_{oc}` are diagonal weight matrices for peephole connections. In
232-
our implementation, we use vectors to reprenset these diagonal weight
233-
matrices. The :math:`b` terms denote bias vectors (:math:`b_i` is the input
234-
gate bias vector), :math:`\sigma` is the non-line activations, such as
235-
logistic sigmoid function, and :math:`i, f, o` and :math:`c` are the input
236-
gate, forget gate, output gate, and cell activation vectors, respectively,
231+
W_{fc}, W_{oc}` are diagonal weight matrices for peephole connections. In
232+
our implementation, we use vectors to reprenset these diagonal weight
233+
matrices. The :math:`b` terms denote bias vectors (:math:`b_i` is the input
234+
gate bias vector), :math:`\sigma` is the non-line activations, such as
235+
logistic sigmoid function, and :math:`i, f, o` and :math:`c` are the input
236+
gate, forget gate, output gate, and cell activation vectors, respectively,
237237
all of which have the same size as the cell output activation vector :math:`h`.
238238
239-
The :math:`\odot` is the element-wise product of the vectors. :math:`act_g`
240-
and :math:`act_h` are the cell input and cell output activation functions
241-
and `tanh` is usually used for them. :math:`\\tilde{c_t}` is also called
242-
candidate hidden state, which is computed based on the current input and
239+
The :math:`\odot` is the element-wise product of the vectors. :math:`act_g`
240+
and :math:`act_h` are the cell input and cell output activation functions
241+
and `tanh` is usually used for them. :math:`\\tilde{c_t}` is also called
242+
candidate hidden state, which is computed based on the current input and
243243
the previous hidden state.
244244
245245
Set `use_peepholes` to `False` to disable peephole connection. The formula
@@ -251,38 +251,38 @@ def dynamic_lstm(input,
251251
Users can choose to use fully-connect layer before LSTM layer.
252252
253253
Args:
254-
input(Variable): The input of dynamic_lstm layer, which supports
255-
variable-time length input sequence. The underlying
256-
tensor in this Variable is a matrix with shape
257-
(T X 4D), where T is the total time steps in this
254+
input(Variable): The input of dynamic_lstm layer, which supports
255+
variable-time length input sequence. The underlying
256+
tensor in this Variable is a matrix with shape
257+
(T X 4D), where T is the total time steps in this
258258
mini-batch, D is the hidden size.
259259
size(int): 4 * hidden size.
260-
param_attr(ParamAttr): The parameter attribute for the learnable
261-
hidden-hidden weights.
260+
param_attr(ParamAttr): The parameter attribute for the learnable
261+
hidden-hidden weights.
262262
263-
- The shape is (D x 4D), where D is the hidden
264-
size.
263+
- The shape is (D x 4D), where D is the hidden
264+
size.
265265
- Weights = {:math:`W_{ch}, W_{ih}, \
266266
W_{fh}, W_{oh}`}
267267
bias_attr(ParamAttr): The bias attribute for the learnable bias
268-
weights, which contains two parts, input-hidden
269-
bias weights and peephole connections weights if
270-
setting `use_peepholes` to `True`.
268+
weights, which contains two parts, input-hidden
269+
bias weights and peephole connections weights if
270+
setting `use_peepholes` to `True`.
271271
272-
1. `use_peepholes = False`
273-
- The shape is (1 x 4D).
272+
1. `use_peepholes = False`
273+
- The shape is (1 x 4D).
274274
- Biases = {:math:`b_c, b_i, b_f, b_o`}.
275-
2. `use_peepholes = True`
276-
- The shape is (1 x 7D).
275+
2. `use_peepholes = True`
276+
- The shape is (1 x 7D).
277277
- Biases = { :math:`b_c, b_i, b_f, b_o, W_{ic}, \
278278
W_{fc}, W_{oc}`}.
279-
use_peepholes(bool): Whether to enable diagonal/peephole connections,
279+
use_peepholes(bool): Whether to enable diagonal/peephole connections,
280280
default `True`.
281281
is_reverse(bool): Whether to compute reversed LSTM, default `False`.
282-
gate_activation(str): The activation for input gate, forget gate and
283-
output gate. Choices = ["sigmoid", "tanh", "relu",
282+
gate_activation(str): The activation for input gate, forget gate and
283+
output gate. Choices = ["sigmoid", "tanh", "relu",
284284
"identity"], default "sigmoid".
285-
cell_activation(str): The activation for cell output. Choices = ["sigmoid",
285+
cell_activation(str): The activation for cell output. Choices = ["sigmoid",
286286
"tanh", "relu", "identity"], default "tanh".
287287
candidate_activation(str): The activation for candidate hidden state.
288288
Choices = ["sigmoid", "tanh", "relu", "identity"],
@@ -1914,3 +1914,57 @@ def warpctc(input, label, blank=0, norm_by_times=False, **kwargs):
19141914
attrs={'blank': blank,
19151915
'norm_by_times': norm_by_times})
19161916
return loss_out
1917+
1918+
1919+
def sequence_reshape(input, new_dim):
1920+
"""
1921+
**Sequence Reshape Layer**
1922+
1923+
This layer will rearrange the input sequences. The new dimension is set by
1924+
user. Length of each sequence is computed according to original length,
1925+
original dimension and new dimension. The following example will help to
1926+
illustrate the function of this layer:
1927+
1928+
.. code-block:: text
1929+
1930+
x is a LoDTensor:
1931+
x.lod = [[0, 2, 6]]
1932+
x.data = [[1, 2], [3, 4],
1933+
[5, 6], [7, 8], [9, 10], [11, 12]]
1934+
x.dims = [6, 2]
1935+
1936+
set new_dim = 4
1937+
1938+
then out is a LoDTensor:
1939+
out.lod = [[0, 1, 3]]
1940+
out.data = [[1, 2, 3, 4],
1941+
[5, 6, 7, 8], [9, 10, 11, 12]]
1942+
out.dims = [3, 4]
1943+
1944+
Currently, only 1-level LoDTensor is supported and please make sure
1945+
(original length * original dimension) can be divided by new dimension with
1946+
no remainder for each sequence.
1947+
1948+
Args:
1949+
input (Variable): (LodTensor, default: LoDTensor<float>), a 2-D LoDTensor
1950+
with shape being [N, M] where M for dimension.
1951+
new_dim (int): New dimension which the input LoDTensor is reshaped to.
1952+
1953+
Returns:
1954+
Variable: Reshaped LoDTensor according to new dimension.
1955+
1956+
Examples:
1957+
.. code-block:: python
1958+
1959+
x = fluid.layers.data(name='x', shape=[5, 20],
1960+
dtype='float32', lod_level=1)
1961+
x_reshaped = layers.sequence_reshape(input=x, new_dim=10)
1962+
"""
1963+
helper = LayerHelper('sequence_reshape', **locals())
1964+
out = helper.create_tmp_variable(helper.input_dtype())
1965+
helper.append_op(
1966+
type='sequence_reshape',
1967+
inputs={'X': [input]},
1968+
outputs={'Out': [out]},
1969+
attrs={'new_dim': new_dim})
1970+
return out

python/paddle/v2/fluid/tests/test_layers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@ def test_get_places(self):
216216
self.assertIsNotNone(x)
217217
print(str(program))
218218

219+
def test_sequence_reshape(self):
220+
program = Program()
221+
with program_guard(program):
222+
x = layers.data(name='x', shape=[8], dtype='float32', lod_level=1)
223+
out = layers.sequence_reshape(input=x, new_dim=16)
224+
self.assertIsNotNone(out)
225+
print(str(program))
226+
219227

220228
if __name__ == '__main__':
221229
unittest.main()

0 commit comments

Comments
 (0)