|
|
|
@ -33,10 +33,11 @@ class SequenceExpandOp : public framework::OperatorWithKernel {
|
|
|
|
|
"Output(Out) of SequenceExpandOp should not be null.");
|
|
|
|
|
|
|
|
|
|
auto x_dims = ctx->GetInputDim("X");
|
|
|
|
|
auto out_dims = x_dims;
|
|
|
|
|
int ref_level = ctx->Attrs().Get<int>("ref_level");
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE_EQ(x_dims.size(), 2U,
|
|
|
|
|
"Dimension number of Input(X) should be 2.");
|
|
|
|
|
PADDLE_ENFORCE_GE(x_dims.size(), 2,
|
|
|
|
|
"Dimension number of Input(X) should be at least 2.");
|
|
|
|
|
|
|
|
|
|
if (ctx->IsRuntime()) {
|
|
|
|
|
framework::Variable* x_var =
|
|
|
|
@ -50,15 +51,9 @@ class SequenceExpandOp : public framework::OperatorWithKernel {
|
|
|
|
|
PADDLE_ENFORCE_LE(x_lod.size(), 1,
|
|
|
|
|
"Number of lod level of Input(X) should not be "
|
|
|
|
|
"greater than 1.");
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE(x_lod.size() == y_lod.size() || x_lod.size() == 0,
|
|
|
|
|
"Level number of Input(X)'s lod should be either equal "
|
|
|
|
|
"to 0 or equal to that of Input(Y).");
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE_GT(y_lod.size(), 0,
|
|
|
|
|
"Level number of Input(Y)'s lod should be "
|
|
|
|
|
"greater than 0.");
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE(
|
|
|
|
|
ref_level == -1 ||
|
|
|
|
|
(ref_level >= 0 && ref_level < static_cast<int>(y_lod.size())),
|
|
|
|
@ -68,6 +63,14 @@ class SequenceExpandOp : public framework::OperatorWithKernel {
|
|
|
|
|
|
|
|
|
|
if (ref_level == -1) ref_level = y_lod.size() - 1;
|
|
|
|
|
|
|
|
|
|
if (x_lod.size() > 0) {
|
|
|
|
|
PADDLE_ENFORCE(
|
|
|
|
|
x_lod.size() == 0 || x_lod[0].size() == y_lod[ref_level].size(),
|
|
|
|
|
"Level number of Input(X)'s lod should be 0. Otherwise "
|
|
|
|
|
"size of Input(X)'s first level lod should be equal to "
|
|
|
|
|
"size of Input(Y)'s lod of referred level.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t out_first_dim = 0;
|
|
|
|
|
if (y_lod[ref_level].size() <= 1) {
|
|
|
|
|
out_first_dim = x_dims[0];
|
|
|
|
@ -81,9 +84,12 @@ class SequenceExpandOp : public framework::OperatorWithKernel {
|
|
|
|
|
(y_lod[ref_level][i] - y_lod[ref_level][i - 1]) * x_seq_len;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ctx->SetOutputDim("Out", {out_first_dim, x_dims[1]});
|
|
|
|
|
out_dims[0] = out_first_dim;
|
|
|
|
|
ctx->SetOutputDim("Out", out_dims);
|
|
|
|
|
} else {
|
|
|
|
|
ctx->SetOutputDim("Out", {-1, x_dims[1]});
|
|
|
|
|
out_dims[0] = -1;
|
|
|
|
|
ctx->SetOutputDim("Out", out_dims);
|
|
|
|
|
ctx->ShareLoD("X", /*->*/ "Out");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
@ -105,69 +111,69 @@ class SequenceExpandOpMaker : public framework::OpProtoAndCheckerMaker {
|
|
|
|
|
AddComment(R"DOC(
|
|
|
|
|
Sequence Expand Operator.
|
|
|
|
|
|
|
|
|
|
This operator expands input(X) according to LOD of input(Y).
|
|
|
|
|
This operator expands `X` according to specified level lod of `Y`. Current
|
|
|
|
|
implementation constaints that lod level of `X` should be at most 1. Attribute
|
|
|
|
|
`ref_level` is used to specify which level lod of `Y` is referred to expand `X`.
|
|
|
|
|
If set `ref_level` to -1, then last level lod of `Y` would be referred.
|
|
|
|
|
Please note, rank of `X` should be at least 2, when the rank exceeds 2, `X`
|
|
|
|
|
would be viewed as a 2-D tensor.
|
|
|
|
|
|
|
|
|
|
Following are cases to better explain how this works:
|
|
|
|
|
|
|
|
|
|
Case 1:
|
|
|
|
|
|
|
|
|
|
Given a 2-level LoDTensor input(X)
|
|
|
|
|
X.lod = [[0, 2, 3],
|
|
|
|
|
[0, 1, 3, 4]]
|
|
|
|
|
X.data = [a, b, c, d]
|
|
|
|
|
Given a 1-level LoDTensor input(X)
|
|
|
|
|
X.lod = [[0, 2, 4]]
|
|
|
|
|
X.data = [[a], [b], [c], [d]]
|
|
|
|
|
X.dims = [4, 1]
|
|
|
|
|
and input(Y)
|
|
|
|
|
Y.lod = [[0, 2, 4],
|
|
|
|
|
[0, 3, 6, 7, 8]]
|
|
|
|
|
with condition len(Y.lod[-1]) -1 == X.dims[0]
|
|
|
|
|
then we get 2-level LoDTensor
|
|
|
|
|
Out.lod = [[0, 2, 4],
|
|
|
|
|
[0, 3, 6, 7, 8]]
|
|
|
|
|
Out.data = [a, a, a, b, b, b, c, d]
|
|
|
|
|
ref_level: 0
|
|
|
|
|
then we get 1-level LoDTensor
|
|
|
|
|
Out.lod = [[0, 2, 4, 6, 8]]
|
|
|
|
|
Out.data = [[a], [b], [a], [b], [c], [d], [c], [d]]
|
|
|
|
|
Out.dims = [8, 1]
|
|
|
|
|
|
|
|
|
|
Case 2:
|
|
|
|
|
|
|
|
|
|
Given 1-level LoDTensor input(X)
|
|
|
|
|
X.lod = [[0, 1, 4]]
|
|
|
|
|
X.data = [[a], [b], [c], [d]]
|
|
|
|
|
X.dims = [4, 1]
|
|
|
|
|
and input(Y)
|
|
|
|
|
Y.lod = [[0, 2, 4],
|
|
|
|
|
[0, 3, 6, 6, 8]]
|
|
|
|
|
ref_level: 0
|
|
|
|
|
then we get 1-level LoDTensor
|
|
|
|
|
Out.lod = [[0, 2, 5, 8]]
|
|
|
|
|
Out.data = [[a], [a], [b], [c], [d], [b], [c], [d]]
|
|
|
|
|
Out.dims = [8, 1]
|
|
|
|
|
|
|
|
|
|
Case 3:
|
|
|
|
|
|
|
|
|
|
Given a common Tensor input(X)
|
|
|
|
|
X.data = [a, b, c]
|
|
|
|
|
X.data = [[a], [b], [c]]
|
|
|
|
|
X.dims = [3, 1]
|
|
|
|
|
and input(Y)
|
|
|
|
|
Y.lod = [[0, 2, 3, 6]]
|
|
|
|
|
with condition len(Y.lod[-1]) -1 == X.dims[0]
|
|
|
|
|
then we get 1-level LoDTensor
|
|
|
|
|
Out.lod = [[0, 2, 3, 6]]
|
|
|
|
|
Out.data = [a, a, b, c, c, c]
|
|
|
|
|
ref_level: -1
|
|
|
|
|
then we a common Tensor
|
|
|
|
|
Out.data = [[a], [a], [b], [c], [c], [c]]
|
|
|
|
|
Out.dims = [6, 1]
|
|
|
|
|
|
|
|
|
|
Case 3:
|
|
|
|
|
Case 4:
|
|
|
|
|
|
|
|
|
|
Given a common Tensor input(X)
|
|
|
|
|
X.data = [[a, b], [c, d], [e, f]]
|
|
|
|
|
X.dims = [3, 2]
|
|
|
|
|
and input(Y)
|
|
|
|
|
Y.lod = [[0, 2, 3, 6]]
|
|
|
|
|
with condition len(Y.lod[-1]) -1 == X.dims[0]
|
|
|
|
|
then we get 1-level LoDTensor
|
|
|
|
|
Out.lod = [[0, 2, 3, 6]]
|
|
|
|
|
Out.data = [[a,b], [a,b] [c,d], [e, f], [e, f], [e, f]]
|
|
|
|
|
ref_level: 0
|
|
|
|
|
then we get a common LoDTensor
|
|
|
|
|
Out.data = [[a, b], [a, b] [c, d], [e, f], [e, f], [e, f]]
|
|
|
|
|
Out.dims = [6, 2]
|
|
|
|
|
|
|
|
|
|
Case 4:
|
|
|
|
|
|
|
|
|
|
Given 2-level a LoDTensor input(X)
|
|
|
|
|
X.lod = [[0, 2, 3],
|
|
|
|
|
[0, 1, 3, 4]]
|
|
|
|
|
X.data = [a, b, c, d]
|
|
|
|
|
X.dims = [4, 1]
|
|
|
|
|
and input(Y)
|
|
|
|
|
Y.lod = [[0, 2, 4],
|
|
|
|
|
[0, 3, 6, 6, 8]]
|
|
|
|
|
with condition len(Y.lod[-1]) -1 == X.dims[0]
|
|
|
|
|
then we get 2-level LoDTensor
|
|
|
|
|
Out.lod = [[0, 2, 4],
|
|
|
|
|
[0, 3, 6, 6, 8]]
|
|
|
|
|
Out.data = [a, a, a, b, b, b, d, d]
|
|
|
|
|
Out.dims = [8, 1]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
)DOC");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|