Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
Paddle
提交
2ef18675
P
Paddle
项目概览
BaiXuePrincess
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
2ef18675
编写于
11月 10, 2017
作者:
X
xzl
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'develop' of
https://github.com/PaddlePaddle/Paddle
into poolmaxpool_with_mask
上级
ba2e5de6
e5d810b9
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
125 addition
and
75 deletion
+125
-75
paddle/operators/sequence_concat_op.cc
paddle/operators/sequence_concat_op.cc
+21
-17
paddle/operators/sequence_concat_op.h
paddle/operators/sequence_concat_op.h
+40
-23
python/paddle/v2/framework/tests/op_test.py
python/paddle/v2/framework/tests/op_test.py
+10
-5
python/paddle/v2/framework/tests/test_seq_concat_op.py
python/paddle/v2/framework/tests/test_seq_concat_op.py
+54
-30
未找到文件。
paddle/operators/sequence_concat_op.cc
浏览文件 @
2ef18675
...
...
@@ -68,38 +68,42 @@ class SequenceConcatOpMaker : public framework::OpProtoAndCheckerMaker {
"The level should be less than the level number of inputs."
)
.
SetDefault
(
0
);
AddComment
(
R"DOC(
Sequence Concat Operator.
The sequence_concat operator concatenates multiple LoDTensors.
It supports a sequence (LoD Tensor with level number is 1)
The sequence_concat operator concatenates multiple LoDTensors.
It only supports sequence (LoD Tensor with level number is 1)
or a nested sequence (LoD tensor with level number is 2) as its input.
The following examples explain how the operator works:
- Case1:
If the axis is other than 0(here, axis is 1 and level is 1),
each input should have the same LoD information and the LoD
each input should have the same LoD information and the LoD
information of the output keeps the same as the input.
LoD(x0) = {{0,2,4}, {0,1,2,3,4}}; Dims(x0) = (4,3,4)
LoD(x1) = {{0,2,4}, {0,1,2,3,4}}; Dims(x1) = (4,4,4)
LoD(Out) = {{0,2,4}, {0,1,2,3,4}}; Dims(Out) = (4,7,4)
LoD(x0) = {{0,2,4}, {0,1,2,3,4}}; Dims(x0) = (4,3,4)
LoD(x1) = {{0,2,4}, {0,1,2,3,4}}; Dims(x1) = (4,4,4)
LoD(Out) = {{0,2,4}, {0,1,2,3,4}}; Dims(Out) = (4,7,4)
- Case2:
If the axis is 0(here, leve is 0), the inputs are concatenated along
If the axis is 0(here, leve is 0), the inputs are concatenated along
time steps, the LoD information of the output need to re-compute.
The LoD information of level-1 should be same.
LoD(x0) = {{0,2,4}, {0,1,2,3,4}}; Dims(x0) = (4,3,4)
LoD(x1) = {{0,3,5}, {0,1,2,3,5}}; Dims(x1) = (5
,3,4)
LoD(Out) = {{0,5,9}, {0,1,2,3,4,5,6,7,9}}; Dims(Out) = (9
,3,4)
LoD(x0) = {{0,2,4}, {0,1,2,3,4}}; Dims(x0) = (4,3,4)
LoD(x1) = {{0,2,4}, {0,1,3,5,7}}; Dims(x1) = (7
,3,4)
LoD(Out) = {{0,2,4}, {0,2,5,8,11}}; Dims(Out) = (11
,3,4)
- Case3:
If the axis is 0(here, level is 1).
LoD(x0) = {{0,2,4}, {0,1,2,3,4}}; Dims(x0) = (4,3,4)
LoD(x1) = {{0,3,5}, {0,1,3,4,5}}; Dims(x1) = (5
,3,4)
LoD(Out) = {{0,5,9}, {0,2,5,7,9}}; Dims(Out) = (9
,3,4)
LoD(x0) = {{0,2,4}, {0,1,2,3,4}}; Dims(x0) = (4,3,4)
LoD(x1) = {{0,3,4}, {0,1,3,5,7}}; Dims(x1) = (7
,3,4)
LoD(Out) = {{0,5,8}, {0,1,2,3,5,7,8,9,11}}; Dims(Out) = (11
,3,4)
NOTE: The levels of all the inputs should be the same.
- Case4:
If the LoD number is 1, axis is 0, level is 0
LoD(x0) = {{0,1,2,3,4}}; Dims(x0) = (4,3,4)
LoD(x1) = {{0,1,3,5,7}}; Dims(x1) = (7,3,4)
LoD(Out) = {{0,2,5,8,11}}; Dims(Out) = (11,3,4)
NOTE: The levels of all the inputs should be the same.
)DOC"
);
}
};
...
...
paddle/operators/sequence_concat_op.h
浏览文件 @
2ef18675
...
...
@@ -24,28 +24,38 @@ using LoDTensor = framework::LoDTensor;
using
LoD
=
framework
::
LoD
;
template
<
typename
T
>
LoD
concatLoD
(
const
std
::
vector
<
const
T
*>
ins
,
const
size_t
axis
,
const
size_t
level
)
{
LoD
ConcatLoD
(
const
std
::
vector
<
const
T
*>
ins
,
const
size_t
level
)
{
auto
out_lod
=
ins
[
0
]
->
lod
();
auto
numLevels
=
ins
[
0
]
->
NumLevels
();
const
size_t
n
=
ins
.
size
();
if
(
axis
==
0UL
)
{
for
(
size_t
i
=
1
;
i
<
n
;
++
i
)
{
for
(
size_t
j
=
0
;
j
<
ins
[
i
]
->
lod
()[
0
].
size
();
++
j
)
{
out_lod
[
0
][
j
]
+=
ins
[
i
]
->
lod
()[
0
][
j
];
}
const
size_t
level_idx
=
ins
[
0
]
->
NumLevels
()
-
1
-
level
;
for
(
size_t
i
=
1
;
i
<
n
;
++
i
)
{
for
(
size_t
j
=
0
;
j
<
ins
[
i
]
->
lod
()[
level_idx
].
size
();
++
j
)
{
out_lod
[
level_idx
][
j
]
+=
ins
[
i
]
->
lod
()[
level_idx
][
j
];
}
}
if
(
ins
[
0
]
->
NumLevels
()
==
2
)
{
for
(
size_t
j
=
1
;
j
<
ins
[
i
]
->
lod
()[
1
].
size
();
++
j
)
{
if
(
level
==
0UL
)
{
out_lod
[
1
].
push_back
(
out_lod
[
1
].
back
()
+
ins
[
i
]
->
lod
()[
1
][
j
]
-
ins
[
i
]
->
lod
()[
1
][
j
-
1
]);
}
else
if
(
level
==
1UL
)
{
out_lod
[
1
][
j
]
+=
ins
[
1
]
->
lod
()[
1
][
j
];
}
for
(
size_t
i
=
level_idx
;
i
<
numLevels
-
1
;
++
i
)
{
size_t
lod_len
=
1
;
for
(
size_t
j
=
0
;
j
<
n
;
++
j
)
{
lod_len
+=
ins
[
j
]
->
lod
()[
i
+
1
].
size
()
-
1
;
}
out_lod
[
i
+
1
].
clear
();
out_lod
[
i
+
1
].
resize
(
lod_len
);
size_t
idx
=
1
;
for
(
size_t
j
=
0
;
j
<
ins
[
0
]
->
lod
()[
i
].
size
()
-
1
;
++
j
)
{
for
(
size_t
k
=
0
;
k
<
n
;
++
k
)
{
for
(
size_t
m
=
ins
[
k
]
->
lod
()[
i
][
j
];
m
<
ins
[
k
]
->
lod
()[
i
][
j
+
1
];
++
m
)
{
out_lod
[
i
+
1
][
idx
]
=
out_lod
[
i
+
1
][
idx
-
1
]
+
ins
[
k
]
->
lod
()[
i
+
1
][
m
+
1
]
-
ins
[
k
]
->
lod
()[
i
+
1
][
m
];
idx
++
;
}
}
}
}
return
out_lod
;
}
...
...
@@ -82,18 +92,21 @@ class SequenceConcatOpKernel : public framework::OpKernel<T> {
"should be greater than the specify level"
);
out
->
mutable_data
<
T
>
(
ctx
.
GetPlace
());
auto
out_lod
=
concatLoD
<
LoDTensor
>
(
ins
,
axis
,
level
);
auto
out_lod
=
ins
[
0
]
->
lod
();
if
(
axis
==
0
)
{
out_lod
=
ConcatLoD
<
LoDTensor
>
(
ins
,
level
);
}
out
->
set_lod
(
out_lod
);
auto
out_lod_level
=
out_lod
[
level
];
const
size_t
level_idx
=
out_lod
.
size
()
-
level
-
1
;
auto
out_lod_level
=
framework
::
ToAbsOffset
(
out_lod
)[
level_idx
];
for
(
size_t
i
=
0
;
i
<
out_lod_level
.
size
()
-
1
;
++
i
)
{
Tensor
out_t
=
out
->
Slice
(
static_cast
<
int
>
(
out_lod_level
[
i
]),
static_cast
<
int
>
(
out_lod_level
[
i
+
1
]));
auto
out_stride
=
framework
::
stride
(
out_t
.
dims
());
size_t
offset
=
0
;
for
(
size_t
j
=
0
;
j
<
n
;
++
j
)
{
auto
in_lod_level
=
ins
[
j
]
->
lod
()[
level
];
auto
in_lod_level
=
framework
::
ToAbsOffset
(
ins
[
j
]
->
lod
())[
level_idx
];
auto
in_stride
=
framework
::
stride
(
ins
[
j
]
->
dims
());
Tensor
in_t
=
ins
[
j
]
->
Slice
(
static_cast
<
int
>
(
in_lod_level
[
i
]),
static_cast
<
int
>
(
in_lod_level
[
i
+
1
]));
...
...
@@ -124,9 +137,12 @@ class SequenceConcatGradOpKernel : public framework::OpKernel<T> {
x_grads
[
i
]
->
set_lod
(
ins
[
i
]
->
lod
());
x_grads
[
i
]
->
mutable_data
<
T
>
(
ctx
.
GetPlace
());
}
auto
out_lod
=
concatLoD
<
LoDTensor
>
(
ins
,
axis
,
level
);
auto
out_lod_level
=
out_lod
[
level
];
auto
out_lod
=
ins
[
0
]
->
lod
();
if
(
axis
==
0UL
)
{
out_lod
=
ConcatLoD
<
LoDTensor
>
(
ins
,
level
);
}
const
size_t
level_idx
=
out_lod
.
size
()
-
level
-
1
;
auto
out_lod_level
=
framework
::
ToAbsOffset
(
out_lod
)[
level_idx
];
for
(
size_t
i
=
0
;
i
<
out_lod_level
.
size
()
-
1
;
++
i
)
{
Tensor
out_grad_t
=
...
...
@@ -136,7 +152,8 @@ class SequenceConcatGradOpKernel : public framework::OpKernel<T> {
size_t
offset
=
0
;
for
(
size_t
j
=
0
;
j
<
n
;
++
j
)
{
auto
x_grad_lod_level
=
x_grads
[
j
]
->
lod
()[
level
];
auto
x_grad_lod_level
=
framework
::
ToAbsOffset
(
x_grads
[
j
]
->
lod
())[
level_idx
];
auto
x_grad_stride
=
framework
::
stride
(
x_grads
[
j
]
->
dims
());
Tensor
x_grad_t
=
x_grads
[
j
]
->
Slice
(
static_cast
<
int
>
(
x_grad_lod_level
[
i
]),
...
...
python/paddle/v2/framework/tests/op_test.py
浏览文件 @
2ef18675
...
...
@@ -215,7 +215,11 @@ class OpTest(unittest.TestCase):
if
isinstance
(
input_vars
[
var_name
],
list
):
for
name
,
np_value
in
self
.
inputs
[
var_name
]:
tensor
=
core
.
LoDTensor
()
tensor
.
set
(
np_value
,
place
)
if
isinstance
(
np_value
,
tuple
):
tensor
.
set
(
np_value
[
0
],
place
)
tensor
.
set_lod
(
np_value
[
1
])
else
:
tensor
.
set
(
np_value
,
place
)
feed_map
[
name
]
=
tensor
else
:
tensor
=
core
.
LoDTensor
()
...
...
@@ -236,7 +240,6 @@ class OpTest(unittest.TestCase):
inputs
=
append_input_output
(
block
,
op_proto
,
self
.
inputs
,
True
)
outputs
=
append_input_output
(
block
,
op_proto
,
self
.
outputs
,
False
)
op
=
block
.
append_op
(
type
=
self
.
op_type
,
inputs
=
inputs
,
...
...
@@ -397,9 +400,11 @@ class OpTest(unittest.TestCase):
if
not
isinstance
(
item
[
0
],
basestring
):
item
=
[[
param_name
]
+
list
(
item
)]
if
len
(
item
)
==
2
:
# only set var name and value, set lod to None
var
[
i
]
=
list
(
item
)
+
[
None
]
if
isinstance
(
item
[
1
],
tuple
):
var
[
i
]
=
[
item
[
0
],
item
[
1
][
0
],
item
[
1
][
1
]]
else
:
# only set var name and value, set lod to None
var
[
i
]
=
list
(
item
)
+
[
None
]
var_descs
=
[(
block
.
create_var
(
name
=
name
,
shape
=
each
.
shape
,
dtype
=
each
.
dtype
),
each
,
lod
)
for
name
,
each
,
lod
in
var
]
...
...
python/paddle/v2/framework/tests/test_seq_concat_op.py
浏览文件 @
2ef18675
...
...
@@ -4,7 +4,33 @@ import sys
from
op_test
import
OpTest
class
TestConcatOp
(
OpTest
):
def
to_abs_lod
(
lod
):
if
len
(
lod
)
==
0
or
len
(
lod
)
==
1
:
return
lod
import
copy
new_lod
=
copy
.
deepcopy
(
lod
)
for
idx
,
val
in
enumerate
(
lod
[
0
]):
new_lod
[
0
][
idx
]
=
lod
[
1
][
val
]
return
new_lod
def
seq_concat
(
inputs
,
level
):
lod0
=
inputs
[
'X'
][
0
][
1
][
1
]
lod1
=
inputs
[
'X'
][
1
][
1
][
1
]
x0
=
inputs
[
'X'
][
0
][
1
][
0
]
x1
=
inputs
[
'X'
][
1
][
1
][
0
]
level_idx
=
len
(
lod0
)
-
level
-
1
outs
=
[]
for
i
in
range
(
len
(
lod0
[
level_idx
])
-
1
):
sub_x0
=
x0
[
to_abs_lod
(
lod0
)[
level_idx
][
i
]:
to_abs_lod
(
lod0
)[
level_idx
][
i
+
1
],
:]
sub_x1
=
x1
[
to_abs_lod
(
lod1
)[
level_idx
][
i
]:
to_abs_lod
(
lod1
)[
level_idx
][
i
+
1
],
:]
outs
.
append
(
np
.
concatenate
((
sub_x0
,
sub_x1
),
axis
=
0
))
return
np
.
concatenate
(
outs
,
axis
=
0
)
class
TestSeqConcatOp
(
OpTest
):
def
set_data
(
self
):
# two level, batch size is 3
x0
=
np
.
random
.
random
((
4
,
6
,
3
)).
astype
(
'float32'
)
...
...
@@ -15,13 +41,7 @@ class TestConcatOp(OpTest):
level
=
1
self
.
inputs
=
{
'X'
:
[(
'x0'
,
(
x0
,
lod0
)),
(
'x1'
,
(
x1
,
lod1
))]}
self
.
attrs
=
{
'axis'
:
axis
,
'level'
:
level
}
outs
=
[]
for
i
in
range
(
4
):
sub_x0
=
x0
[
lod0
[
level
][
i
]:
lod0
[
level
][
i
+
1
],
:]
sub_x1
=
x1
[
lod1
[
level
][
i
]:
lod1
[
level
][
i
+
1
],
:]
outs
.
append
(
np
.
concatenate
((
sub_x0
,
sub_x1
),
axis
=
axis
))
self
.
outputs
=
{
'Out'
:
np
.
concatenate
(
outs
,
axis
=
0
)}
self
.
outputs
=
{
'Out'
:
(
np
.
concatenate
([
x0
,
x1
],
axis
=
1
),
lod0
)}
def
setUp
(
self
):
self
.
op_type
=
"sequence_concat"
...
...
@@ -34,46 +54,50 @@ class TestConcatOp(OpTest):
self
.
check_grad
([
'x0'
],
'Out'
)
class
Test
ConcatOpDiffLod
(
Test
ConcatOp
):
class
Test
SeqConcatOpLevelZeroNestedSequence
(
TestSeq
ConcatOp
):
def
set_data
(
self
):
# two level, batch size is 3
x0
=
np
.
random
.
random
((
4
,
6
,
3
)).
astype
(
'float32'
)
lod0
=
[[
0
,
2
,
4
],
[
0
,
1
,
2
,
3
,
4
]]
x1
=
np
.
random
.
random
((
5
,
6
,
3
)).
astype
(
'float32'
)
lod1
=
[[
0
,
3
,
5
],
[
0
,
1
,
2
,
3
,
5
]]
x1
=
np
.
random
.
random
((
7
,
6
,
3
)).
astype
(
'float32'
)
lod1
=
[[
0
,
2
,
4
],
[
0
,
1
,
3
,
5
,
7
]]
axis
=
0
level
=
1
level
=
0
self
.
inputs
=
{
'X'
:
[(
'x0'
,
(
x0
,
lod0
)),
(
'x1'
,
(
x1
,
lod1
))]}
self
.
attrs
=
{
'axis'
:
axis
,
'level'
:
level
}
outs
=
[]
for
i
in
range
(
4
):
sub_x0
=
x0
[
lod0
[
level
][
i
]:
lod0
[
level
][
i
+
1
],
:]
sub_x1
=
x1
[
lod1
[
level
][
i
]:
lod1
[
level
][
i
+
1
],
:]
outs
.
append
(
np
.
concatenate
((
sub_x0
,
sub_x1
),
axis
=
axis
))
out_lod
=
[[
0
,
2
,
4
],
[
0
,
2
,
5
,
8
,
11
]]
self
.
outputs
=
{
'Out'
:
(
seq_concat
(
self
.
inputs
,
level
),
out_lod
)}
self
.
outputs
=
{
'Out'
:
np
.
concatenate
(
outs
,
axis
=
0
)}
class
TestSeqConcatOplevelOneNestedSequence
(
TestSeqConcatOp
):
def
set_data
(
self
):
# two level, batch size is 3
x0
=
np
.
random
.
random
((
4
,
6
,
3
)).
astype
(
'float32'
)
lod0
=
[[
0
,
2
,
4
],
[
0
,
1
,
2
,
3
,
4
]]
x1
=
np
.
random
.
random
((
7
,
6
,
3
)).
astype
(
'float32'
)
lod1
=
[[
0
,
3
,
4
],
[
0
,
1
,
3
,
5
,
7
]]
axis
=
0
level
=
1
self
.
inputs
=
{
'X'
:
[(
'x0'
,
(
x0
,
lod0
)),
(
'x1'
,
(
x1
,
lod1
))]}
self
.
attrs
=
{
'axis'
:
axis
,
'level'
:
level
}
out_lod
=
[[
0
,
5
,
8
],
[
0
,
1
,
2
,
3
,
5
,
7
,
8
,
9
,
11
]]
self
.
outputs
=
{
'Out'
:
(
seq_concat
(
self
.
inputs
,
level
),
out_lod
)}
class
Test
ConcatOpLevelZero
(
Test
ConcatOp
):
class
Test
SeqConcatOpLevelZeroSequence
(
TestSeq
ConcatOp
):
def
set_data
(
self
):
# two level, batch size is 3
x0
=
np
.
random
.
random
((
4
,
3
,
4
)).
astype
(
'float32'
)
lod0
=
[[
0
,
2
,
4
],
[
0
,
1
,
2
,
3
,
4
]]
x1
=
np
.
random
.
random
((
5
,
3
,
4
)).
astype
(
'float32'
)
lod1
=
[[
0
,
3
,
5
],
[
0
,
1
,
3
,
4
,
5
]]
lod0
=
[[
0
,
1
,
2
,
3
,
4
]]
x1
=
np
.
random
.
random
((
7
,
3
,
4
)).
astype
(
'float32'
)
lod1
=
[[
0
,
1
,
3
,
5
,
7
]]
axis
=
0
level
=
0
self
.
inputs
=
{
'X'
:
[(
'x0'
,
(
x0
,
lod0
)),
(
'x1'
,
(
x1
,
lod1
))]}
self
.
attrs
=
{
'axis'
:
axis
,
'level'
:
level
}
outs
=
[]
for
i
in
range
(
2
):
sub_x0
=
x0
[
lod0
[
level
][
i
]:
lod0
[
level
][
i
+
1
],
:]
sub_x1
=
x1
[
lod1
[
level
][
i
]:
lod1
[
level
][
i
+
1
],
:]
outs
.
append
(
np
.
concatenate
((
sub_x0
,
sub_x1
),
axis
=
axis
))
self
.
outputs
=
{
'Out'
:
np
.
concatenate
(
outs
,
axis
=
0
)}
out_lod
=
[[
0
,
2
,
5
,
8
,
11
]]
self
.
outputs
=
{
'Out'
:
(
seq_concat
(
self
.
inputs
,
level
),
out_lod
)}
if
__name__
==
'__main__'
:
sys
.
exit
(
0
)
unittest
.
main
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录