Skip to content

Commit 33fa2df

Browse files
authored
Compelete max_sequence_len_op (#5913)
1 parent 0ac8c74 commit 33fa2df

File tree

4 files changed

+121
-8
lines changed

4 files changed

+121
-8
lines changed

paddle/operators/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ set(DEPS_OPS
200200
lod_rank_table_op
201201
lod_tensor_to_array_op
202202
array_to_lod_tensor_op
203+
max_sequence_len_op
203204
lstm_op
204205
tensor_array_read_write_op
205206
gru_op
@@ -222,6 +223,7 @@ op_library(pool_with_index_op DEPS pooling)
222223
op_library(lod_rank_table_op SRCS lod_rank_table_op.cc DEPS lod_rank_table)
223224
op_library(lod_tensor_to_array_op SRCS lod_tensor_to_array_op.cc DEPS lod_rank_table_op)
224225
op_library(array_to_lod_tensor_op SRCS array_to_lod_tensor_op.cc DEPS lod_rank_table_op)
226+
op_library(max_sequence_len_op SRCS max_sequence_len_op.cc DEPS lod_rank_table)
225227
op_library(tensor_array_read_write_op SRCS tensor_array_read_write_op.cc)
226228
if(WITH_GPU)
227229
op_library(nccl_op DEPS nccl_common)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License. */
14+
15+
#include "paddle/framework/lod_rank_table.h"
16+
#include "paddle/framework/op_registry.h"
17+
#include "paddle/framework/operator.h"
18+
19+
namespace paddle {
20+
namespace operators {
21+
22+
class MaxSeqenceLenOp : public framework::OperatorBase {
23+
public:
24+
MaxSeqenceLenOp(const std::string &type,
25+
const framework::VariableNameMap &inputs,
26+
const framework::VariableNameMap &outputs,
27+
const framework::AttributeMap &attrs)
28+
: OperatorBase(type, inputs, outputs, attrs) {}
29+
30+
void Run(const framework::Scope &scope,
31+
const platform::DeviceContext &dev_ctx) const override {
32+
auto &rank_table =
33+
scope.FindVar(Input("RankTable"))->Get<framework::LoDRankTable>();
34+
auto *out =
35+
scope.FindVar(Output("Out"))->GetMutable<framework::LoDTensor>();
36+
int64_t *out_ptr = out->mutable_data<int64_t>({1}, platform::CPUPlace());
37+
*out_ptr = rank_table.items()[0].length;
38+
}
39+
};
40+
41+
class MaxSeqenceLenOpProtoMaker : public framework::OpProtoAndCheckerMaker {
42+
public:
43+
MaxSeqenceLenOpProtoMaker(framework::OpProto *proto,
44+
framework::OpAttrChecker *op_checker)
45+
: OpProtoAndCheckerMaker(proto, op_checker) {
46+
AddInput("RankTable", "The lod_rank_table.");
47+
AddOutput("Out", "The max sequence length.");
48+
AddComment(
49+
R"DOC(Calculate the max sequence length through lod_rank_table.)DOC");
50+
}
51+
};
52+
53+
class MaxSeqenceLenInferShape : public framework::InferShapeBase {
54+
public:
55+
void operator()(framework::InferShapeContext *context) const override {
56+
PADDLE_ENFORCE(context->HasInput("RankTable"));
57+
context->SetOutputDim("Out", {1});
58+
}
59+
};
60+
} // namespace operators
61+
} // namespace paddle
62+
63+
REGISTER_OPERATOR(max_sequence_len, paddle::operators::MaxSeqenceLenOp,
64+
paddle::operators::MaxSeqenceLenOpProtoMaker,
65+
paddle::operators::MaxSeqenceLenInferShape,
66+
paddle::framework::EmptyGradOpMaker);

python/paddle/v2/fluid/layers.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,20 @@ def lod_rank_table(x, level=0, main_program=None):
13541354
return table
13551355

13561356

1357+
def max_sequence_len(rank_table, main_program=None):
1358+
"""
1359+
This function creates an operator to calculate the length of
1360+
max seqence through input rank_table(should be a lod_rank_table)
1361+
"""
1362+
helper = LayerHelper("max_seqence_len", **locals())
1363+
res = helper.create_tmp_variable(dtype="int64")
1364+
helper.append_op(
1365+
type="max_sequence_len",
1366+
inputs={"RankTable": rank_table},
1367+
outputs={"Out": res})
1368+
return res
1369+
1370+
13571371
def topk(input, k, main_program=None, startup_program=None):
13581372
helper = LayerHelper('topk', **locals())
13591373
topk_out = helper.create_tmp_variable(dtype=input.data_type)

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

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ def test_lod_tensor_to_array_level_0(self):
1818
tensor.set_lod([[0, 3, 9, 10]])
1919
expect = map(lambda x: numpy.array(x).astype('int32'),
2020
[[3, 0, 9], [4, 1], [5, 2], [6], [7], [8]])
21-
self.main(tensor=tensor, expect_array=expect, expect_lod=[] * 6)
21+
self.main(
22+
tensor=tensor,
23+
expect_array=expect,
24+
expect_lod=[] * 6,
25+
expect_max_len=6)
2226

2327
def test_lod_tensor_to_array_level_0_empty_seq(self):
2428
tensor = core.LoDTensor()
@@ -27,7 +31,11 @@ def test_lod_tensor_to_array_level_0_empty_seq(self):
2731
tensor.set_lod([[0, 3, 9, 9, 10]])
2832
expect = map(lambda x: numpy.array(x).astype('int32'),
2933
[[3, 0, 9], [4, 1], [5, 2], [6], [7], [8]])
30-
self.main(tensor=tensor, expect_array=expect, expect_lod=[] * 6)
34+
self.main(
35+
tensor=tensor,
36+
expect_array=expect,
37+
expect_lod=[] * 6,
38+
expect_max_len=6)
3139

3240
def test_lod_tensor_to_array_level_1(self):
3341
tensor = core.LoDTensor()
@@ -44,7 +52,11 @@ def test_lod_tensor_to_array_level_1(self):
4452
]
4553

4654
lod = [[[0, 2, 5]], [[0, 6, 12]], [[0, 3]]]
47-
self.main(tensor=tensor, expect_array=expect, expect_lod=lod)
55+
self.main(
56+
tensor=tensor,
57+
expect_array=expect,
58+
expect_lod=lod,
59+
expect_max_len=3)
4860

4961
def test_lod_tensor_to_array_level_1_empty_seq(self):
5062
tensor = core.LoDTensor()
@@ -63,7 +75,11 @@ def test_lod_tensor_to_array_level_1_empty_seq(self):
6375
]
6476

6577
lod = [[[0, 5, 8, 8, 15]], [[0, 2, 6, 7, 8]], [[0, 2, 6]], [[0, 2]]]
66-
self.main(tensor=tensor, expect_array=expect, expect_lod=lod)
78+
self.main(
79+
tensor=tensor,
80+
expect_array=expect,
81+
expect_lod=lod,
82+
expect_max_len=4)
6783

6884
def test_lod_tensor_to_array_level_2(self):
6985
tensor = core.LoDTensor()
@@ -80,22 +96,33 @@ def test_lod_tensor_to_array_level_2(self):
8096
]
8197
lod = [[[0, 1, 3, 4], [0, 1, 4, 8, 12]],
8298
[[0, 4, 7], [0, 1, 5, 9, 17, 21, 27, 31]], [[0, 2], [0, 6, 7]]]
83-
self.main(tensor=tensor, expect_array=expect, expect_lod=lod)
99+
self.main(
100+
tensor=tensor,
101+
expect_array=expect,
102+
expect_lod=lod,
103+
expect_max_len=3)
84104

85105
def test_lod_tensor_to_array_level_2_skip_level(self):
86106
tensor = core.LoDTensor()
87107
tensor.set(
88108
numpy.arange(50).reshape(50, 1).astype('int32'), self.place())
89109
tensor.set_lod([[0, 2, 5, 6], [0, 2, 5, 6, 10, 12, 13],
90110
[0, 3, 7, 11, 17, 21, 22, 23, 27, 31, 39, 45, 46, 50]])
91-
self.main(tensor=tensor, expect_array=None, expect_lod=None, level=1)
92-
93-
def main(self, tensor, expect_array, expect_lod, level=0):
111+
self.main(
112+
tensor=tensor,
113+
expect_array=None,
114+
expect_lod=None,
115+
expect_max_len=4,
116+
level=1)
117+
118+
def main(self, tensor, expect_array, expect_lod, expect_max_len, level=0):
94119
place = self.place()
95120
program = Program()
96121
x = layers.data(name='x', shape=[10], main_program=program)
97122
x.persistable = True
98123
table = layers.lod_rank_table(x, level=level, main_program=program)
124+
max_len = layers.max_sequence_len(table, main_program=program)
125+
max_len.persistable = True
99126
array = layers.lod_tensor_to_array(x, table, main_program=program)
100127
array.persistable = True
101128

@@ -110,6 +137,10 @@ def main(self, tensor, expect_array, expect_lod, level=0):
110137
self.check_array_same(array, expect_array, expect_lod)
111138
self.check_tensor_same(scope.find_var(result.name).get_tensor(), tensor)
112139

140+
self.assertEqual(
141+
numpy.array(scope.find_var(max_len.name).get_tensor())[0],
142+
expect_max_len)
143+
113144
def check_array_same(self, array, expect_tensor, expect_lod):
114145
self.assertEqual(len(expect_tensor), len(array))
115146
for i, exp in enumerate(zip(expect_tensor, expect_lod)):

0 commit comments

Comments
 (0)