Skip to content

Commit f2ae7e3

Browse files
author
Yibing Liu
authored
Support seq len equal to 0 in sequence ops (#16964)
* Merge conflicts with 1.4 * Resolve conflicts * Fix some comments test=release/1.4 * Fix py3 error test=release/1.4
1 parent 5ab96d3 commit f2ae7e3

28 files changed

+390
-92
lines changed

paddle/fluid/framework/lod_tensor.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ bool CheckLoD(const LoD &in, int tensor_height) {
158158
if (level.size() < 2) return false;
159159
// check: the first offset(the begin offset) of each level should be 0.
160160
if (level.front() != 0) return false;
161-
// check: all the offsets in a level should be ascending(allow same items)
161+
// check: all the offsets in a level should be non-descending
162162
if (!std::is_sorted(level.begin(), level.end())) {
163163
return false;
164164
}
@@ -182,7 +182,7 @@ bool CheckAbsLoD(const LoD &in, int tensor_height) {
182182
if (in.empty()) return true;
183183
for (const auto &level : in) {
184184
// check: all the offsets in a level should be ascending(no same items
185-
// allows).
185+
// allowed).
186186
if (!std::is_sorted(level.begin(), level.begin(), [](size_t a, size_t b) {
187187
if (a < b) return true;
188188
return false;

paddle/fluid/framework/lod_tensor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ bool operator==(const LoD& a, const LoD& b);
7979
*
8080
* It will check two things:
8181
*
82-
* 1. all the offsets in a level should be ascending(no same items allows).
82+
* 1. all the offsets in a level should be non-descending.
8383
* 2. there should be more than 2 offsets existing in each level.
8484
* 3. the higher level's last offset should equals the lower level's size-1.
8585
* 4. the first offset(the begin offset) of each level should be 0.
@@ -95,7 +95,7 @@ bool CheckLoD(const LoD& in, int tensor_height = -1);
9595
* - Empty lod is treated as valid.
9696
*
9797
* It will check two things:
98-
* 1. all the offsets in a level should be ascending(no same items allows)
98+
* 1. all the offsets in a level should be ascending(no same items allowed).
9999
* 2. there should be more than 2 offsets existing in each level.
100100
* 3. the first offset of each level should be 0, and the last should be the
101101
* same(the height of underlying tensor) or `tensor_height` if

paddle/fluid/operators/crf_decoding_op.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class CRFDecodingOpKernel : public framework::OpKernel<T> {
4646
math::SetConstant<DeviceContext, int64_t>()(
4747
ctx.template device_context<DeviceContext>(), decoded_path, 0);
4848
for (size_t i = 0; i < seq_num; ++i) {
49+
if (lod[level][i] == lod[level][i + 1]) continue;
4950
int start_pos = static_cast<int>(lod[level][i]);
5051
int end_pos = static_cast<int>(lod[level][i + 1]);
5152
Tensor decoded_path_one_seq = decoded_path->Slice(start_pos, end_pos);

paddle/fluid/operators/math/context_project.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class ContextProjectFunctor {
104104
sequence_width = in.dims()[1];
105105

106106
for (int i = 0; i < static_cast<int>(lod_level_0.size()) - 1; ++i) {
107+
if (lod_level_0[i] == lod_level_0[i + 1]) continue;
108+
107109
input_row_begin = (context_start > 0)
108110
? static_cast<int>(lod_level_0[i]) + context_start
109111
: static_cast<int>(lod_level_0[i]);
@@ -134,6 +136,8 @@ class ContextProjectFunctor {
134136
if (padding_trainable) {
135137
PADDLE_ENFORCE_NOT_NULL(padding_data);
136138
for (int i = 0; i < static_cast<int>(lod_level_0.size()) - 1; ++i) {
139+
if (lod_level_0[i] == lod_level_0[i + 1]) continue;
140+
137141
Tensor out_t = col->Slice(static_cast<int>(lod_level_0[i]),
138142
static_cast<int>(lod_level_0[i + 1]));
139143

@@ -216,6 +220,8 @@ class ContextProjectGradFunctor {
216220

217221
if (input_grad) {
218222
for (int i = 0; i < static_cast<int>(lod_level_0.size()) - 1; ++i) {
223+
if (lod_level_0[i] == lod_level_0[i + 1]) continue;
224+
219225
input_row_begin = (context_start > 0)
220226
? static_cast<int>(lod_level_0[i]) + context_start
221227
: static_cast<int>(lod_level_0[i]);
@@ -248,6 +254,8 @@ class ContextProjectGradFunctor {
248254
if (pad_grad) {
249255
if (padding_trainable) {
250256
for (int i = 0; i < static_cast<int>(lod_level_0.size()) - 1; ++i) {
257+
if (lod_level_0[i] == lod_level_0[i + 1]) continue;
258+
251259
Tensor out_t = col->Slice(static_cast<int>(lod_level_0[i]),
252260
static_cast<int>(lod_level_0[i + 1]));
253261

paddle/fluid/operators/math/detail/lstm_gpu_kernel.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,9 @@ void gpu_lstm_forward(const platform::DeviceContext& context, Op op,
197197
threads = dim3(frame_per_block, 1);
198198
grid = dim3(frame_blocks, 1);
199199
} else {
200-
/* frame_per_block = 32 batch_per_block = 32 */
201-
threads = dim3(32, 32);
202-
grid = dim3((frame_size + 32 - 1) / 32, (batch_size + 32 - 1) / 32);
200+
/* frame_per_block = 32 batch_per_block = 16 */
201+
threads = dim3(32, 16);
202+
grid = dim3((frame_size + 32 - 1) / 32, (batch_size + 16 - 1) / 16);
203203
}
204204

205205
auto stream =

paddle/fluid/operators/sequence_ops/sequence_concat_op.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ inline framework::LoD ConcatLoD(const Container &xs,
3434
for (size_t j = 0; j < xs.size(); ++j) {
3535
auto &x_lod = xs[j].get().lod()[0];
3636
const framework::Tensor &tensor = xs[j].get();
37-
xs_in_order->emplace_back(tensor.Slice(x_lod[i - 1], x_lod[i]));
37+
if (x_lod[i - 1] < x_lod[i]) {
38+
xs_in_order->emplace_back(tensor.Slice(x_lod[i - 1], x_lod[i]));
39+
}
3840
sum += x_lod[i];
3941
}
4042
result[i] = sum;
@@ -97,6 +99,8 @@ class SeqConcatGradKernel : public framework::OpKernel<T> {
9799
const framework::LoDTensor *x = xs[j];
98100
framework::LoDTensor *dx = dxs[j];
99101
auto &x_lod = x->lod()[0];
102+
if (x_lod[i - 1] == x_lod[i]) continue;
103+
100104
sliced_x.emplace_back(x->Slice(x_lod[i - 1], x_lod[i]));
101105
if (dx != nullptr) {
102106
sliced_dx.emplace_back(dx->Slice(x_lod[i - 1], x_lod[i]));

paddle/fluid/operators/sequence_ops/sequence_enumerate_op.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ class SequenceEnumerateKernel : public framework::OpKernel<T> {
4747
out->set_lod(in->lod());
4848
auto out_data = out->mutable_data<T>(context.GetPlace());
4949
for (size_t i = 0; i < lod0.size() - 1; ++i) {
50+
if (lod0[i] == lod0[i + 1]) continue;
5051
int start = lod0[i];
5152
int end = lod0[i + 1];
53+
5254
int copy_size = win_size < end - start + 1 ? win_size : end - start + 1;
5355
int mid = end + 1 - copy_size;
5456
int pad_num = win_size - copy_size;

paddle/fluid/operators/sequence_ops/sequence_expand_op.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ struct SequenceExpandGradFunctor<platform::CPUDeviceContext, T> {
160160
int x_start = x_lod[i - 1];
161161
int x_end = x_lod[i];
162162
int x_seq_len = x_end - x_start;
163+
if (x_seq_len == 0) continue;
163164
auto dx_sub = dx->Slice(x_start, x_end);
164165
dx_sub.Resize(flatten_to_1d(dx_sub.dims()));
165166
int dout_end = dout_offset + repeat_num * x_seq_len;

paddle/fluid/operators/sequence_ops/sequence_slice_op.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ class SequenceSliceOpKernel : public framework::OpKernel<T> {
7676

7777
for (size_t i = 0; i < n; ++i) {
7878
PADDLE_ENFORCE_LE(0, offset_data[i],
79-
"The offset[%d] must greater than zero.", i);
80-
PADDLE_ENFORCE_LT(0, length_data[i],
81-
"The length[%d] must greater than zero.", i);
79+
"The offset[%d] must be nonnegative.", i);
80+
PADDLE_ENFORCE_LE(0, length_data[i],
81+
"The length[%d] must be nonnegative.", i);
8282
PADDLE_ENFORCE_LE(lod[0][i] + offset_data[i] + length_data[i],
8383
lod[0][i + 1], "The target tensor's length overflow.");
8484
}
@@ -95,6 +95,7 @@ class SequenceSliceOpKernel : public framework::OpKernel<T> {
9595

9696
size_t out_offset = 0;
9797
for (size_t i = 0; i < n; ++i) {
98+
if (length_data[i] == 0) continue;
9899
Tensor in_t = in->Slice(
99100
static_cast<int>(lod[0][i] + offset_data[i]),
100101
static_cast<int>(lod[0][i] + offset_data[i] + length_data[i]));
@@ -144,6 +145,7 @@ class SequenceSliceGradOpKernel : public framework::OpKernel<T> {
144145
static_cast<T>(0));
145146

146147
for (size_t i = 0; i < out_lod[0].size() - 1; ++i) {
148+
if (length_data[i] == 0) continue;
147149
Tensor out_grad_t =
148150
out_grad->Slice(static_cast<int>(out_lod[0][i]),
149151
static_cast<int>(out_lod[0][i + 1]));

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

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,15 @@ class TestCRFDecodingOp2(OpTest):
128128
ground truth being given.
129129
"""
130130

131+
def init_lod(self):
132+
self.lod = [[1, 2, 3, 4]]
133+
131134
def setUp(self):
132135
self.op_type = "crf_decoding"
133136
TAG_NUM = 5
134137

135-
lod = [[1, 2, 3, 4]]
136-
total_len = sum(lod[-1])
138+
self.init_lod()
139+
total_len = sum(self.lod[-1])
137140
transition = np.repeat(
138141
np.arange(
139142
TAG_NUM, dtype="float64").reshape(1, TAG_NUM),
@@ -152,9 +155,9 @@ def setUp(self):
152155
expected_output = (labels == predicted_labels).astype("int64")
153156

154157
self.inputs = {
155-
"Emission": (emission, lod),
158+
"Emission": (emission, self.lod),
156159
"Transition": transition,
157-
"Label": (labels, lod)
160+
"Label": (labels, self.lod)
158161
}
159162

160163
self.outputs = {"ViterbiPath": expected_output}
@@ -163,5 +166,15 @@ def test_check_output(self):
163166
self.check_output()
164167

165168

169+
class TestCRFDecodingOp3(TestCRFDecodingOp2):
170+
def init_lod(self):
171+
self.lod = [[1, 0, 0, 4]]
172+
173+
174+
class TestCRFDecodingOp4(TestCRFDecodingOp2):
175+
def init_lod(self):
176+
self.lod = [[0, 2, 3, 0]]
177+
178+
166179
if __name__ == "__main__":
167180
unittest.main()

0 commit comments

Comments
 (0)