From a9cd513680d16d6e96290f0c8fb2bf415a9488d4 Mon Sep 17 00:00:00 2001 From: Aurelius84 Date: Tue, 27 Aug 2019 17:16:31 +0800 Subject: [PATCH] improve sequence_conv api doc (#19316) * improve sequence_conv api doc test=develop * add warning for padding param test=develop modify into deprecated --- paddle/fluid/API.spec | 2 +- python/paddle/fluid/layers/nn.py | 74 ++++++++++++++++--- .../fluid/tests/unittests/test_seq_conv.py | 16 ++++ 3 files changed, 80 insertions(+), 12 deletions(-) diff --git a/paddle/fluid/API.spec b/paddle/fluid/API.spec index 4c21db216c..b842df8434 100644 --- a/paddle/fluid/API.spec +++ b/paddle/fluid/API.spec @@ -122,7 +122,7 @@ paddle.fluid.layers.cross_entropy (ArgSpec(args=['input', 'label', 'soft_label', paddle.fluid.layers.bpr_loss (ArgSpec(args=['input', 'label', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '6263dfdeb6c670fa0922c9cbc8fb1bf4')) paddle.fluid.layers.square_error_cost (ArgSpec(args=['input', 'label'], varargs=None, keywords=None, defaults=None), ('document', 'bbb9e708bab250359864fefbdf48e9d9')) paddle.fluid.layers.chunk_eval (ArgSpec(args=['input', 'label', 'chunk_scheme', 'num_chunk_types', 'excluded_chunk_types', 'seq_length'], varargs=None, keywords=None, defaults=(None, None)), ('document', 'b02844e0ad4bd713c5fe6802aa13219c')) -paddle.fluid.layers.sequence_conv (ArgSpec(args=['input', 'num_filters', 'filter_size', 'filter_stride', 'padding', 'bias_attr', 'param_attr', 'act', 'name'], varargs=None, keywords=None, defaults=(3, 1, None, None, None, None, None)), ('document', '3d8e8f3e0e1cf520156be37605e83ccd')) +paddle.fluid.layers.sequence_conv (ArgSpec(args=['input', 'num_filters', 'filter_size', 'filter_stride', 'padding', 'padding_start', 'bias_attr', 'param_attr', 'act', 'name'], varargs=None, keywords=None, defaults=(3, 1, True, None, None, None, None, None)), ('document', '2bf23e7884c380c3b27f2709aa322cb9')) paddle.fluid.layers.conv2d (ArgSpec(args=['input', 'num_filters', 'filter_size', 'stride', 'padding', 'dilation', 'groups', 'param_attr', 'bias_attr', 'use_cudnn', 'act', 'name'], varargs=None, keywords=None, defaults=(1, 0, 1, None, None, None, True, None, None)), ('document', '35f5343338e38803c70ed0479965d0b4')) paddle.fluid.layers.conv3d (ArgSpec(args=['input', 'num_filters', 'filter_size', 'stride', 'padding', 'dilation', 'groups', 'param_attr', 'bias_attr', 'use_cudnn', 'act', 'name'], varargs=None, keywords=None, defaults=(1, 0, 1, None, None, None, True, None, None)), ('document', '367293b5bada54136a91621078d38334')) paddle.fluid.layers.sequence_pool (ArgSpec(args=['input', 'pool_type', 'is_test', 'pad_value'], varargs=None, keywords=None, defaults=(False, 0.0)), ('document', 'e90a93251c52dc4e6fb34fb3991b3f82')) diff --git a/python/paddle/fluid/layers/nn.py b/python/paddle/fluid/layers/nn.py index 01946d642e..7714a4548a 100644 --- a/python/paddle/fluid/layers/nn.py +++ b/python/paddle/fluid/layers/nn.py @@ -1919,22 +1919,70 @@ def sequence_conv(input, num_filters, filter_size=3, filter_stride=1, - padding=None, + padding=True, + padding_start=None, bias_attr=None, param_attr=None, act=None, name=None): """ - This function creates the op for sequence_conv, using the inputs and - other convolutional configurations for the filters and stride as given - in the input parameters to the function. + The sequence_conv receives input sequences with variable length and other convolutional + configuration parameters for the filter and stride to apply the convolution operation. + It fills all-zero padding data on both sides of the sequence by default to ensure that + the output is the same length as the input. You can customize the padding behavior by + configuring the parameter :attr:`padding\_start`. + + **Warning:** the parameter :attr:`padding` take no effect and will be deprecated in the future. + + .. code-block:: text + + Here we'll illustrate the details of the padding operation: + For a mini-batch of 2 variable lengths sentences, containing 3, and 1 time-steps: + Assumed input (X) is a [4, M, N] float LoDTensor, and X->lod()[0] = [0, 3, 4]. + Besides, for the sake of simplicity, we assume M=1 and N=2. + X = [[a1, a2; + b1, b2; + c1, c2] + [d1, d2]] + + This is to say that input (X) has 4 words and the dimension of each word + representation is 2. + + * Case1: + + If padding_start is -1 and filter_size is 3. + The length of padding data is calculated as follows: + up_pad_len = max(0, -padding_start) = 1 + down_pad_len = max(0, filter_size + padding_start - 1) = 1 + + The output of the input sequence after padding is: + data_aftet_padding = [[0, 0, a1, a2, b1, b2; + a1, a2, b1, b2, c1, c2; + b1, b2, c1, c2, 0, 0 ] + [0, 0, d1, d2, 0, 0 ]] + + It will be multiplied by the filter weight to get the final output. Args: input (Variable): ${x_comment} - num_filters (int): number of filters. - filter_size (int): the filter size (H and W). - filter_stride (int): stride of the filter. - padding (bool): if True, add paddings. + num_filters (int): the number of filters. + filter_size (int): the height of filter, the width is hidden size by default. + filter_stride (int): stride of the filter. Currently only supports :attr:`stride` = 1. + padding (bool): the parameter :attr:`padding` take no effect and will be discarded in the + future. Currently, it will always pad input to make sure the length of the output is + the same as input whether :attr:`padding` is set true or false. Because the length of + input sequence may be shorter than :attr:`filter\_size`, which will cause the convolution + result to not be computed correctly. These padding data will not be trainable or updated + while trainnig. + padding_start (int|None): It is used to indicate the start index for padding the input + sequence, which can be negative. The negative number means to pad + :attr:`|padding_start|` time-steps of all-zero data at the beginning of each instance. + The positive number means to skip :attr:`padding_start` time-steps of each instance, + and it will pad :math:`filter\_size + padding\_start - 1` time-steps of all-zero data + at the end of the sequence to ensure that the output is the same length as the input. + If set None, the same length :math:`\\frac{filter\_size}{2}` of data will be filled + on both sides of the sequence. If set 0, the length of :math:`filter\_size - 1` data + is padded at the end of each input sequence. bias_attr (ParamAttr|bool|None): The parameter attribute for the bias of sequence_conv. If it is set to False, no bias will be added to the output units. If it is set to None or one attribute of ParamAttr, sequence_conv @@ -1953,11 +2001,13 @@ def sequence_conv(input, Variable: output of sequence_conv Examples: + .. code-block:: python import paddle.fluid as fluid + x = fluid.layers.data(name='x', shape=[10,10], append_batch_size=False, dtype='float32') - x_conved = fluid.layers.sequence_conv(x,2) + x_conved = fluid.layers.sequence_conv(input=x, num_filters=2, filter_size=3, padding_start=-1) """ assert not in_dygraph_mode(), ( @@ -1968,6 +2018,8 @@ def sequence_conv(input, filter_param = helper.create_parameter( attr=helper.param_attr, shape=filter_shape, dtype=dtype) pre_bias = helper.create_variable_for_type_inference(dtype) + if padding_start is None: + padding_start = -int(filter_size // 2) helper.append_op( type='sequence_conv', @@ -1978,8 +2030,8 @@ def sequence_conv(input, outputs={"Out": pre_bias}, attrs={ 'contextStride': filter_stride, - 'contextStart': -int(filter_size // 2), - 'contextLength': filter_size + 'contextStart': padding_start, + 'contextLength': filter_size, }) pre_act = helper.append_bias_op(pre_bias) return helper.append_activation(pre_act) diff --git a/python/paddle/fluid/tests/unittests/test_seq_conv.py b/python/paddle/fluid/tests/unittests/test_seq_conv.py index da111f9b73..9f0115034d 100644 --- a/python/paddle/fluid/tests/unittests/test_seq_conv.py +++ b/python/paddle/fluid/tests/unittests/test_seq_conv.py @@ -241,5 +241,21 @@ class TestSeqProjectCase3(TestSeqProject): self.output_represention = 8 # output feature size +class TestSeqConvApi(unittest.TestCase): + def test_api(self): + import paddle.fluid as fluid + + x = fluid.layers.data('x', shape=[32], lod_level=1) + y = fluid.layers.sequence_conv( + input=x, num_filters=2, filter_size=3, padding_start=None) + + place = fluid.CPUPlace() + x_tensor = fluid.create_lod_tensor( + np.random.rand(10, 32).astype("float32"), [[2, 3, 1, 4]], place) + exe = fluid.Executor(place) + exe.run(fluid.default_startup_program()) + ret = exe.run(feed={'x': x_tensor}, fetch_list=[y], return_numpy=False) + + if __name__ == '__main__': unittest.main()