Skip to content

Commit 9cc1937

Browse files
author
Yibing Liu
authored
Merge pull request #13400 from kuke/fix_seq_pad
Get sequence length in sequence_pad op & fix sequence_mask op
2 parents 020d13c + 1c87558 commit 9cc1937

File tree

6 files changed

+69
-13
lines changed

6 files changed

+69
-13
lines changed

paddle/fluid/operators/sequence_mask_op.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ REGISTER_OP_CPU_KERNEL(
2323
paddle::operators::SequenceMaskKernel<paddle::platform::CPUDeviceContext,
2424
int>,
2525
paddle::operators::SequenceMaskKernel<paddle::platform::CPUDeviceContext,
26-
int64_t>);
26+
int64_t>,
27+
paddle::operators::SequenceMaskKernel<paddle::platform::CPUDeviceContext,
28+
float>,
29+
paddle::operators::SequenceMaskKernel<paddle::platform::CPUDeviceContext,
30+
double>);

paddle/fluid/operators/sequence_mask_op.cu

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ REGISTER_OP_CUDA_KERNEL(
1919
paddle::operators::SequenceMaskKernel<paddle::platform::CUDADeviceContext,
2020
int>,
2121
paddle::operators::SequenceMaskKernel<paddle::platform::CUDADeviceContext,
22-
int64_t>);
22+
int64_t>,
23+
paddle::operators::SequenceMaskKernel<paddle::platform::CUDADeviceContext,
24+
float>,
25+
paddle::operators::SequenceMaskKernel<paddle::platform::CUDADeviceContext,
26+
double>);

paddle/fluid/operators/sequence_pad_op.cc

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ class SequencePadOp : public framework::OperatorWithKernel {
2929
"Input(PadValue) of SequencePadOp should not be null.");
3030
PADDLE_ENFORCE(ctx->HasOutput("Out"),
3131
"Output(Out) of SequencePadOp should not be null.");
32+
PADDLE_ENFORCE(ctx->HasOutput("Length"),
33+
"Output(Length) of SequencePadOp should not be null.");
3234

3335
auto x_dims = ctx->GetInputDim("X");
3436
PADDLE_ENFORCE_GE(x_dims.size(), 2,
35-
"The rank of Input(x) can't be less than 2.");
37+
"The rank of Input(X) can't be less than 2.");
3638
auto time_step_dims = framework::slice_ddim(x_dims, 1, x_dims.size());
3739
auto pad_value_dims = ctx->GetInputDim("PadValue");
3840
PADDLE_ENFORCE(pad_value_dims == framework::make_ddim({1}) ||
@@ -41,8 +43,8 @@ class SequencePadOp : public framework::OperatorWithKernel {
4143
"shape equals to time steps in sequences");
4244

4345
int out_dim_0 = -1;
44-
int out_dim_1 = -1;
4546

47+
int padded_length = ctx->Attrs().Get<int>("padded_length");
4648
if (ctx->IsRuntime()) {
4749
// run time
4850
framework::Variable* x_var =
@@ -58,27 +60,37 @@ class SequencePadOp : public framework::OperatorWithKernel {
5860

5961
int seq_num = x_lod_0.size() - 1;
6062
int max_seq_len = math::MaximumSequenceLength(x_lod_0);
61-
int padded_length = ctx->Attrs().Get<int>("padded_length");
6263
if (padded_length == -1) {
6364
padded_length = max_seq_len;
6465
}
6566
PADDLE_ENFORCE_GE(padded_length, max_seq_len,
6667
"The Attr(padded_length) must be -1 or an int greater "
6768
"than the length of the longest original sequence.");
6869
out_dim_0 = seq_num;
69-
out_dim_1 = padded_length;
7070
} else {
7171
// compile time
72+
if (padded_length == -1) {
73+
padded_length = 1;
74+
}
7275
framework::VarDesc* x_desc =
7376
boost::get<framework::VarDesc*>(ctx->GetInputVarPtrs("X")[0]);
7477
PADDLE_ENFORCE_GE(x_desc->GetLoDLevel(), 1);
7578
}
7679

77-
std::vector<int> out_dims_vec{out_dim_0, out_dim_1};
80+
std::vector<int> out_dims_vec{out_dim_0, padded_length};
81+
std::vector<int> len_dims_vec{out_dim_0, 1};
7882
auto time_step_dims_vec = framework::vectorize2int(time_step_dims);
7983
out_dims_vec.insert(out_dims_vec.end(), time_step_dims_vec.begin(),
8084
time_step_dims_vec.end());
8185
ctx->SetOutputDim("Out", framework::make_ddim(out_dims_vec));
86+
ctx->SetOutputDim("Length", framework::make_ddim(len_dims_vec));
87+
}
88+
89+
protected:
90+
framework::OpKernelType GetExpectedKernelType(
91+
const framework::ExecutionContext& ctx) const override {
92+
auto data_type = framework::GetDataTypeOfVar(ctx.InputVar("X"));
93+
return framework::OpKernelType(data_type, ctx.device_context());
8294
}
8395
};
8496

@@ -96,6 +108,10 @@ class SequencePadOpMaker : public framework::OpProtoAndCheckerMaker {
96108
AddOutput(
97109
"Out",
98110
"(LoDTensor) The output vairable, which contains padded sequences.");
111+
AddOutput(
112+
"Length",
113+
"(LoDTensor) The output vairable, which contains the actual length of "
114+
"sequences before padding.");
99115
AddAttr<int>(
100116
"padded_length",
101117
"The length of padded sequences. It can be setted to -1 or "
@@ -125,6 +141,7 @@ class SequencePadOpMaker : public framework::OpProtoAndCheckerMaker {
125141
then we get LoDTensor:
126142
Out.data = [[a, b, 0, 0],
127143
[c, d, e, 0]]
144+
Length.data = [[2], [3]]
128145
129146
Case 2:
130147
@@ -138,7 +155,8 @@ class SequencePadOpMaker : public framework::OpProtoAndCheckerMaker {
138155
then we get LoDTensor:
139156
Out.data = [[[a1, a2], [b1, b2], [0, 0]],
140157
[[c1, c2], [d1, d2], [e1, e2]]]
141-
158+
Length.data = [[2], [3]]
159+
142160
Case 3:
143161
144162
Given a 1-level LoDTensor input(X):
@@ -151,6 +169,7 @@ class SequencePadOpMaker : public framework::OpProtoAndCheckerMaker {
151169
then we get LoDTensor:
152170
Out.data = [[[a1, a2], [b1, b2], [p1, p2]],
153171
[[c1, c2], [d1, d2], [e1, e2]]]
172+
Length.data = [[2], [3]]
154173
155174
)DOC");
156175
}
@@ -171,6 +190,13 @@ class SequencePadGradOp : public framework::OperatorWithKernel {
171190
ctx->ShareLoD("X", /*->*/ framework::GradVarName("X"));
172191
}
173192
}
193+
194+
protected:
195+
framework::OpKernelType GetExpectedKernelType(
196+
const framework::ExecutionContext& ctx) const override {
197+
auto data_type = framework::GetDataTypeOfVar(ctx.InputVar("X"));
198+
return framework::OpKernelType(data_type, ctx.device_context());
199+
}
174200
};
175201

176202
} // namespace operators

paddle/fluid/operators/sequence_pad_op.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class SequencePadOpKernel : public framework::OpKernel<T> {
3232
void Compute(const framework::ExecutionContext& ctx) const override {
3333
const auto* x = ctx.Input<LoDTensor>("X");
3434
auto* out = ctx.Output<LoDTensor>("Out");
35+
auto* len_t = ctx.Output<LoDTensor>("Length");
3536
out->mutable_data<T>(ctx.GetPlace());
3637

3738
const auto* pad_value = ctx.Input<LoDTensor>("PadValue");
@@ -41,6 +42,15 @@ class SequencePadOpKernel : public framework::OpKernel<T> {
4142
math::PaddingLoDTensorFunctor<DeviceContext, T>()(
4243
ctx.template device_context<DeviceContext>(), *x, out, *pad_value,
4344
padded_length, 0, false, math::kBatchLengthWidth);
45+
46+
LoDTensor seq_len;
47+
seq_len.Resize(len_t->dims());
48+
int64_t* len_data = seq_len.mutable_data<int64_t>(platform::CPUPlace());
49+
for (size_t i = 1; i < x->lod()[0].size(); ++i) {
50+
len_data[i - 1] = x->lod()[0][i] - x->lod()[0][i - 1];
51+
}
52+
framework::TensorCopy(seq_len, ctx.GetPlace(),
53+
ctx.template device_context<DeviceContext>(), len_t);
4454
}
4555
};
4656

python/paddle/fluid/layers/nn.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,7 +2776,8 @@ def sequence_pad(x, pad_value, maxlen=None):
27762776
longest original sequence."
27772777
27782778
Returns:
2779-
Variable: The padded sequence batch. All sequences has the same length.
2779+
Variable: The padded sequence batch and the original lengths before
2780+
padding. All sequences has the same length.
27802781
27812782
Examples:
27822783
.. code-block:: python
@@ -2792,15 +2793,21 @@ def sequence_pad(x, pad_value, maxlen=None):
27922793
helper = LayerHelper('sequence_pad', input=x, **locals())
27932794
dtype = helper.input_dtype()
27942795
out = helper.create_tmp_variable(dtype)
2796+
length = helper.create_tmp_variable(dtype)
2797+
2798+
pad_value.stop_gradient = True
2799+
length.stop_gradient = True
2800+
27952801
if maxlen is None:
27962802
maxlen = -1
27972803
helper.append_op(
27982804
type='sequence_pad',
27992805
inputs={'X': x,
28002806
'PadValue': pad_value},
2801-
outputs={'Out': out},
2807+
outputs={'Out': out,
2808+
'Length': length},
28022809
attrs={'padded_length': maxlen})
2803-
return out
2810+
return out, length
28042811

28052812

28062813
def beam_search(pre_ids,
@@ -6017,7 +6024,7 @@ def sequence_mask(x, maxlen=None, dtype='int64', name=None):
60176024
inputs={'X': [x]},
60186025
outputs={'Y': out},
60196026
attrs={
6020-
'max_len': maxlen if maxlen is not None else -1,
6027+
'maxlen': maxlen if maxlen is not None else -1,
60216028
'out_dtype': out.dtype
60226029
})
60236030
return out

python/paddle/fluid/tests/unittests/test_sequence_pad_op.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ def compute(self):
6262
start_idx = end_idx
6363

6464
out_data = np.array(padded_sequences)
65-
self.outputs = {'Out': out_data}
65+
length = np.array(self.x_len_lod[0]).reshape((-1, 1))
66+
self.outputs = {'Out': out_data, 'Length': length}
6667

6768
def setUp(self):
6869
self.op_type = 'sequence_pad'
@@ -129,3 +130,7 @@ def set_attr(self):
129130
self.pad_value = [1.0]
130131
self.padded_length = 7
131132
self.dtype = 'float32'
133+
134+
135+
if __name__ == '__main__':
136+
unittest.main()

0 commit comments

Comments
 (0)