提交 84627bb9 编写于 作者: C caoying03

add config helper for sequence slice layer.

上级 ec2c753c
...@@ -257,6 +257,11 @@ seq_concat ...@@ -257,6 +257,11 @@ seq_concat
.. autoclass:: paddle.v2.layer.seq_concat .. autoclass:: paddle.v2.layer.seq_concat
:noindex: :noindex:
seq_slice
---------
.. autoclass:: paddle.v2.layer.seq_slice
:noindex:
Reshaping Layers Reshaping Layers
================ ================
......
...@@ -2657,6 +2657,51 @@ class SubSequenceLayer(LayerBase): ...@@ -2657,6 +2657,51 @@ class SubSequenceLayer(LayerBase):
self.create_bias_parameter(bias, size) self.create_bias_parameter(bias, size)
@config_layer('seq_slice')
class SeqSliceLayer(LayerBase):
def __init__(self, name, inputs, starts, ends, bias=False, **xargs):
if isinstance(inputs, list):
assert len(inputs) == 1, ('the first input of sequence slice layer '
'is a single sequence input.')
else:
inputs = [inputs]
if starts is not None:
if isinstance(starts, list):
assert len(starts) == 1, (
'the start indices for sequence slice layer cannot '
'be a list having more than one element.')
starts = starts[0]
inputs.append(starts)
if ends is not None:
if isinstance(ends, list):
assert len(ends) == 1, (
'the end indices for sequence slice layer cannot '
'be a list having more than one element.')
ends = ends[0]
inputs.append(ends)
assert len(inputs) >= 2, (
'the sequence slice layer has at least two inputs.')
super(SeqSliceLayer, self).__init__(
name, 'seq_slice', 0, inputs=inputs, **xargs)
input_layer0 = self.get_input_layer(0)
size = input_layer0.size
self.set_layer_size(size)
if len(inputs) == 3:
assert (
self.get_input_layer(1).size == self.get_input_layer(2).size), (
'If start and end indices are both given to'
'sequence slice layer, they should have the same width.')
elif len(inputs) == 2:
if starts is not None:
self.config.select_first = True
else:
self.config.select_first = False
@config_layer('out_prod') @config_layer('out_prod')
class OuterProdLayer(LayerBase): class OuterProdLayer(LayerBase):
def __init__(self, name, inputs, device=None): def __init__(self, name, inputs, device=None):
......
...@@ -131,6 +131,7 @@ __all__ = [ ...@@ -131,6 +131,7 @@ __all__ = [
'crop_layer', 'crop_layer',
'clip_layer', 'clip_layer',
'slice_projection', 'slice_projection',
'seq_slice_layer',
] ]
...@@ -225,6 +226,7 @@ class LayerType(object): ...@@ -225,6 +226,7 @@ class LayerType(object):
PRELU = 'prelu' PRELU = 'prelu'
CROP_LAYER = 'crop' CROP_LAYER = 'crop'
CLIP_LAYER = 'clip' CLIP_LAYER = 'clip'
SEQ_SLICE = 'seq_slice'
@staticmethod @staticmethod
def is_layer_type(type_name): def is_layer_type(type_name):
...@@ -6119,3 +6121,69 @@ def clip_layer(input, min, max, name=None): ...@@ -6119,3 +6121,69 @@ def clip_layer(input, min, max, name=None):
max=max) max=max)
return LayerOutput( return LayerOutput(
name, LayerType.CLIP_LAYER, parents=[input], size=input.size) name, LayerType.CLIP_LAYER, parents=[input], size=input.size)
@wrap_name_default()
def seq_slice_layer(input, starts, ends, name=None):
"""
seq_slice_layer will return one or several sub-sequences from the
input sequence layer given start and end indices.
- If only start indices are given, and end indices are set to None,
this layer slices the input sequence from the given start indices
to its end.
- If only end indices are given, and start indices are set to None,
this layer slices the input sequence from its beginning to the
given end indices.
- If start and end indices are both given, they should have the same
number of elements.
If start or end indices contains more than one elements, the input sequence
will be sliced for multiple times.
.. code-block:: python
seq_silce = seq_slice_layer(input=input_seq,
starts=start_pos, ends=end_pos)
:param name: name of this layer.
:type name: basestring
:param input: input for this layer, it should be a sequence.
:type input: LayerOutput
:param starts: start indices to slice the input sequence.
:type starts: LayerOutput|None
:param ends: end indices to slice the input sequence.
:type ends: LayerOutput|None
:return: LayerOutput object.
:rtype: LayerOutput
"""
assert isinstance(input, LayerOutput), (
'The first input of seq_slice layer must be a PaddlePaddle layer.')
if starts is not None:
assert isinstance(starts, LayerOutput), (
'The start indices for seq_slice layer '
'must be a PaddlePaddle layer.')
if ends is not None:
assert isinstance(ends, LayerOutput), (
'The end indices for seq_slice layer must be a PaddlePaddle layer.')
assert starts is not None or ends is not None, (
'start and end indices '
'cannot be set to None at the same time, at least one of '
'them should be given.')
if starts is not None and ends is not None:
assert starts.size == ends.size, (
'If start and end indices are both given to seq_slice_layer, '
'they should have the same width.')
Layer(
name=name,
type=LayerType.SEQ_SLICE,
inputs=input.name,
starts=starts.name if starts is not None else None,
ends=ends.name if ends is not None else None)
return LayerOutput(
name, LayerType.SEQ_SLICE, parents=[input], size=input.size)
...@@ -7,6 +7,7 @@ test_rnn_group shared_fc shared_lstm shared_gru test_cost_layers_with_weight ...@@ -7,6 +7,7 @@ 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_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops
test_seq_concat_reshape test_pad test_smooth_l1 test_multiplex_layer test_seq_concat_reshape test_pad test_smooth_l1 test_multiplex_layer
test_prelu_layer test_row_conv test_detection_output_layer test_multibox_loss_layer test_prelu_layer test_row_conv test_detection_output_layer test_multibox_loss_layer
test_recursive_topology test_gated_unit_layer test_clip_layer test_row_l2_norm_layer) test_recursive_topology test_gated_unit_layer test_clip_layer test_row_l2_norm_layer
test_seq_slice_layer)
export whole_configs=(test_split_datasource) export whole_configs=(test_split_datasource)
type: "nn"
layers {
name: "word"
type: "data"
size: 128
active_type: ""
}
layers {
name: "starts"
type: "data"
size: 5
active_type: ""
}
layers {
name: "ends"
type: "data"
size: 5
active_type: ""
}
layers {
name: "__seq_slice_layer_0__"
type: "seq_slice"
size: 128
active_type: ""
inputs {
input_layer_name: "word"
}
inputs {
input_layer_name: "starts"
}
inputs {
input_layer_name: "ends"
}
}
layers {
name: "__seq_slice_layer_1__"
type: "seq_slice"
size: 128
active_type: ""
inputs {
input_layer_name: "word"
}
inputs {
input_layer_name: "starts"
}
select_first: true
}
layers {
name: "__seq_slice_layer_2__"
type: "seq_slice"
size: 128
active_type: ""
inputs {
input_layer_name: "word"
}
inputs {
input_layer_name: "ends"
}
select_first: false
}
input_layer_names: "word"
output_layer_names: "__seq_slice_layer_0__"
output_layer_names: "__seq_slice_layer_1__"
output_layer_names: "__seq_slice_layer_2__"
sub_models {
name: "root"
layer_names: "word"
layer_names: "starts"
layer_names: "ends"
layer_names: "__seq_slice_layer_0__"
layer_names: "__seq_slice_layer_1__"
layer_names: "__seq_slice_layer_2__"
input_layer_names: "word"
output_layer_names: "__seq_slice_layer_0__"
output_layer_names: "__seq_slice_layer_1__"
output_layer_names: "__seq_slice_layer_2__"
is_recurrent_layer_group: false
}
#!/usr/bin/env python
#coding=utf-8
from paddle.trainer_config_helpers import *
input_seq = data_layer("word", size=128)
starts = data_layer("starts", size=5)
ends = data_layer("ends", size=5)
seq_slice1 = seq_slice_layer(input=input_seq, starts=starts, ends=ends)
seq_slice2 = seq_slice_layer(input=input_seq, starts=starts, ends=None)
seq_slice3 = seq_slice_layer(input=input_seq, starts=None, ends=ends)
outputs(seq_slice1, seq_slice2, seq_slice3)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册