diff --git a/doc/api/trainer_config_helpers/layers.rst b/doc/api/trainer_config_helpers/layers.rst index 3685868ffcfdf1d17557e5e8bcba6cbc25804147..2793d6afd9565eb461c8657b838b146fe1992b20 100644 --- a/doc/api/trainer_config_helpers/layers.rst +++ b/doc/api/trainer_config_helpers/layers.rst @@ -308,6 +308,12 @@ repeat_layer :members: repeat_layer :noindex: +seq_reshape_layer +----------------- +.. automodule:: paddle.trainer_config_helpers.layers + :members: seq_reshape_layer + :noindex: + Math Layers =========== diff --git a/paddle/gserver/layers/SequenceReshapeLayer.cpp b/paddle/gserver/layers/SequenceReshapeLayer.cpp index 66f49159087ab9e2c83b1d74e9b4d9bfe4f49e79..433592953b220eda4db4634124a57a2074cef4c0 100644 --- a/paddle/gserver/layers/SequenceReshapeLayer.cpp +++ b/paddle/gserver/layers/SequenceReshapeLayer.cpp @@ -20,9 +20,12 @@ limitations under the License. */ namespace paddle { /** - * A layer for reshaping the sequence - * Input: a sequence - * Output: a sequence + * A layer for reshaping the sequence. Assume the input sequence has + * T instances, the dimension of each instance is M, and the input + * reshape_dim is N, then the output sequence has T*M/N instances, + * the dimension of each instance is N. + * + * Note that T*M/N must be an integer. */ class SequenceReshapeLayer : public Layer { diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 0ff29772356af7dcb36b71fa2b1263dc4477d0e4..0d3a31b9d39a28070bdadc8329caf8e383dbace8 100755 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -37,6 +37,7 @@ __all__ = [ "dotmul_projection", "dotmul_operator", "repeat_layer", + "seq_reshape_layer", "table_projection", "mixed_layer", "data_layer", @@ -125,6 +126,7 @@ class LayerType(object): GRUMEMORY = "gated_recurrent" SEQUENCE_LAST_INSTANCE = "seqlastins" SEQUENCE_FIRST_INSTANCE = "seqfirstins" + SEQUENCE_RESHAPE = "seqreshape" POOLING_MAX = "max" POOLING_AVG = 'average' FC_LAYER = "fc" @@ -1450,6 +1452,61 @@ def repeat_layer(input, num_repeats, name=None, layer_attr=None): parents=[input]) +@wrap_name_default("seqreshape") +@wrap_act_default(act=IdentityActivation()) +@wrap_bias_attr_default(has_bias=False) +@layer_support() +def seq_reshape_layer(input, + reshape_size, + act=None, + name=None, + layer_attr=None, + bias_attr=None): + """ + A layer for reshaping the sequence. Assume the input sequence has T instances, + the dimension of each instance is M, and the input reshape_size is N, then the + output sequence has T*M/N instances, the dimension of each instance is N. + + Note that T*M/N must be an integer. + + The example usage is: + + .. code-block:: python + + reshape = seq_reshape_layer(input=layer, reshape_size=4) + + :param input: Input layer. + :type input: LayerOutput + :param reshape_size: the size of reshaped sequence. + :type reshape_size: int + :param name: Layer name. + :type name: basestring + :param act: Activation type. + :type act: BaseActivation + :param layer_attr: extra layer attributes. + :type layer_attr: ExtraLayerAttribute. + :param bias_attr: The Bias Attribute. If no bias, then pass False or + something not type of ParameterAttribute. None will get a + default Bias. + :type bias_attr: ParameterAttribute or None or bool + :return: LayerOutput object. + :rtype: LayerOutput + """ + + Layer( + inputs=[input.name], + name=name, + size=reshape_size, + type=LayerType.SEQUENCE_RESHAPE, + bias=ParamAttr.to_bias(bias_attr), + **ExtraAttr.to_kwargs(layer_attr)) + return LayerOutput( + name=name, + size=reshape_size, + layer_type=LayerType.SEQUENCE_RESHAPE, + parents=[input]) + + @wrap_name_default() @layer_support() def interpolation_layer(input, weight, name=None, layer_attr=None): @@ -2604,6 +2661,10 @@ def seq_concat_layer(a, b, act=None, name=None, layer_attr=None, :type act: BaseActivation :param layer_attr: Extra Layer Attribute. :type layer_attr: ExtraLayerAttribute + :param bias_attr: The Bias Attribute. If no bias, then pass False or + something not type of ParameterAttribute. None will get a + default Bias. + :type bias_attr: ParameterAttribute or None or bool :return: LayerOutput object. :rtype: LayerOutput """ diff --git a/python/paddle/trainer_config_helpers/tests/configs/file_list.sh b/python/paddle/trainer_config_helpers/tests/configs/file_list.sh index 55cef6be0c630c88c11401682449d8aabdafb124..c9178e3c6a46a2d663ec368569e529e780b76a6f 100755 --- a/python/paddle/trainer_config_helpers/tests/configs/file_list.sh +++ b/python/paddle/trainer_config_helpers/tests/configs/file_list.sh @@ -5,6 +5,6 @@ last_first_seq test_expand_layer test_ntm_layers test_hsigmoid img_layers img_trans_layers util_layers simple_rnn_layers unused_layers test_cost_layers test_rnn_group shared_fc shared_lstm shared_gru test_cost_layers_with_weight test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops -test_seq_concat) +test_seq_concat_reshape) export whole_configs=(test_split_datasource) diff --git a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat_reshape.protostr similarity index 72% rename from python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr rename to python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat_reshape.protostr index 2fa55e87b5d13c2fc6f8a404733c17cf0a21c875..91284b4fb32fcfdbf6b9e7384ffe080574b78821 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat.protostr +++ b/python/paddle/trainer_config_helpers/tests/configs/protostr/test_seq_concat_reshape.protostr @@ -23,17 +23,29 @@ layers { input_layer_name: "data2" } } +layers { + name: "__seqreshape_0__" + type: "seqreshape" + size: 5 + active_type: "linear" + inputs { + input_layer_name: "data1" + } +} input_layer_names: "data1" input_layer_names: "data2" output_layer_names: "__seqconcat_0__" +output_layer_names: "__seqreshape_0__" sub_models { name: "root" layer_names: "data1" layer_names: "data2" layer_names: "__seqconcat_0__" + layer_names: "__seqreshape_0__" input_layer_names: "data1" input_layer_names: "data2" output_layer_names: "__seqconcat_0__" + output_layer_names: "__seqreshape_0__" is_recurrent_layer_group: false } diff --git a/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py b/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat_reshape.py similarity index 57% rename from python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py rename to python/paddle/trainer_config_helpers/tests/configs/test_seq_concat_reshape.py index 193d9d0df9ed80a4bc555095116b42192c7757f0..5c161ba805fb301e8feb8702ad61a8341df40e3f 100644 --- a/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat.py +++ b/python/paddle/trainer_config_helpers/tests/configs/test_seq_concat_reshape.py @@ -3,7 +3,10 @@ from paddle.trainer_config_helpers import * settings(batch_size=1000, learning_rate=1e-5) din1 = data_layer(name='data1', size=30) - din2 = data_layer(name='data2', size=30) -outputs(seq_concat_layer(a=din1, b=din2)) +opts = [] +opts.append(seq_concat_layer(a=din1, b=din2)) +opts.append(seq_reshape_layer(input=din1, reshape_size=5)) + +outputs(opts) diff --git a/python/paddle/v2/__init__.py b/python/paddle/v2/__init__.py index cfdcebceb5fcf5be0a54b62fb76c58ee5be57729..be752731ba232a43933b117085c5da3ee363b035 100644 --- a/python/paddle/v2/__init__.py +++ b/python/paddle/v2/__init__.py @@ -21,15 +21,8 @@ import data_type import py_paddle.swig_paddle as api __all__ = [ - 'optimizer', - 'layer', - 'activation', - 'parameters', - 'init', - 'trainer', - 'event', - 'data_type', - 'data_feeder', + 'optimizer', 'layer', 'activation', 'parameters', 'init', 'trainer', + 'event', 'data_type', 'data_feeder' ] diff --git a/python/paddle/v2/layer.py b/python/paddle/v2/layer.py index 4d052c983c2c07730fe5111ccb961de68e73fb8f..507725ee4ff71200656869a2be1d0f7dd67b6387 100644 --- a/python/paddle/v2/layer.py +++ b/python/paddle/v2/layer.py @@ -66,12 +66,14 @@ Also, the creation of a protobuf message is hidden in the invocation of paddle.v2.parameters.create, no longer exposed to users. """ +import collections + import paddle.trainer_config_helpers as conf_helps -from . import data_type as v2_data from paddle.trainer_config_helpers.config_parser_utils import \ parse_network_config as __parse__ from paddle.trainer_config_helpers.default_decorators import wrap_name_default -import collections + +import data_type __all__ = [ 'parse_network', 'data', 'fc', 'max_id', 'classification_cost', @@ -166,7 +168,7 @@ So we also need to implement some special LayerV2. class DataLayerV2(Layer): def __init__(self, name, type, **kwargs): - assert isinstance(type, v2_data.InputType) + assert isinstance(type, data_type.InputType) self.type = type self.__method_name__ = 'data_layer' @@ -198,8 +200,8 @@ cross_entropy_cost = __convert_to_v2__( parent_names=['input', 'label']) if __name__ == '__main__': - pixel = data(name='pixel', type=v2_data.dense_vector(784)) - label = data(name='label', type=v2_data.integer_value(10)) + pixel = data(name='pixel', type=data_type.dense_vector(784)) + label = data(name='label', type=data_type.integer_value(10)) hidden = fc(input=pixel, size=100, act=conf_helps.SigmoidActivation()) inference = fc(input=hidden, size=10, act=conf_helps.SoftmaxActivation()) maxid = max_id(input=inference)