Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
机器未来
Paddle
提交
a281e101
P
Paddle
项目概览
机器未来
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
a281e101
编写于
6月 07, 2018
作者:
G
guosheng
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make cc_test of beam_search_op and beam_searc_decode_op run correctly
上级
741046e8
变更
7
显示空白变更内容
内联
并排
Showing
7 changed file
with
50 addition
and
336 deletion
+50
-336
paddle/fluid/operators/CMakeLists.txt
paddle/fluid/operators/CMakeLists.txt
+2
-2
paddle/fluid/operators/beam_search_decode_op.cc
paddle/fluid/operators/beam_search_decode_op.cc
+0
-4
paddle/fluid/operators/beam_search_decode_op.h
paddle/fluid/operators/beam_search_decode_op.h
+7
-177
paddle/fluid/operators/beam_search_decode_op_test.cc
paddle/fluid/operators/beam_search_decode_op_test.cc
+28
-120
paddle/fluid/operators/beam_search_op.cc
paddle/fluid/operators/beam_search_op.cc
+1
-20
paddle/fluid/operators/beam_search_op.h
paddle/fluid/operators/beam_search_op.h
+2
-8
paddle/fluid/operators/beam_search_op_test.cc
paddle/fluid/operators/beam_search_op_test.cc
+10
-5
未找到文件。
paddle/fluid/operators/CMakeLists.txt
浏览文件 @
a281e101
...
...
@@ -288,8 +288,8 @@ set(GLOB_OP_LIB ${OP_LIBRARY} CACHE INTERNAL "Global OP library")
cc_test
(
gather_test SRCS gather_test.cc DEPS tensor
)
cc_test
(
scatter_test SRCS scatter_test.cc DEPS tensor
)
#
cc_test(beam_search_decode_op_test SRCS beam_search_decode_op_test.cc DEPS lod_tensor)
#
cc_test(beam_search_op_test SRCS beam_search_op_test.cc DEPS lod_tensor beam_search_op)
cc_test
(
beam_search_decode_op_test SRCS beam_search_decode_op_test.cc DEPS lod_tensor
)
cc_test
(
beam_search_op_test SRCS beam_search_op_test.cc DEPS lod_tensor beam_search_op
)
cc_test
(
strided_memcpy_test SRCS strided_memcpy_test.cc DEPS tensor memory
)
cc_test
(
save_load_op_test SRCS save_load_op_test.cc DEPS save_op load_op
)
cc_test
(
save_load_combine_op_test SRCS save_load_combine_op_test.cc DEPS save_combine_op load_combine_op
)
...
...
paddle/fluid/operators/beam_search_decode_op.cc
浏览文件 @
a281e101
...
...
@@ -87,13 +87,9 @@ void BeamSearchDecodeFunctor::operator()() const {
BeamSearchDecoder
<
T
>
beam_search_decoder
(
beam_size_
,
end_id_
);
// Check if the tensor is on GPU. If so, use the CPU copy instead
if
(
tensor_on_gpu_
)
{
// beam_search_decoder.PackAllSteps(step_ids_, step_scores_, id_tensor_,
// score_tensor_);
beam_search_decoder
.
Backtrace
(
step_ids_
,
step_scores_
,
id_tensor_
,
score_tensor_
);
}
else
{
// beam_search_decoder.PackAllSteps(step_ids_origin_, step_scores_origin_,
// id_tensor_, score_tensor_);
beam_search_decoder
.
Backtrace
(
step_ids_origin_
,
step_scores_origin_
,
id_tensor_
,
score_tensor_
);
}
...
...
paddle/fluid/operators/beam_search_decode_op.h
浏览文件 @
a281e101
...
...
@@ -28,41 +28,11 @@ using LoDTensorArray = framework::LoDTensorArray;
// all the lod have 2 levels.
// The First is source level, the second is sentence level.
// source level describe how many
candidate words for this source.
//
sentence level describe these candidates belong to which prefix
// source level describe how many
prefixes (branchs) for each source sentece
//
(beam). sentence level describe how these candidates belong to the prefixes.
const
size_t
kSourceLevel
=
0
;
const
size_t
kSentenceLevel
=
1
;
template
<
typename
T
>
struct
BeamNode
{
BeamNode
(
int64_t
word_id
,
T
score
)
:
word_id_
(
word_id
),
score_
(
score
)
{}
~
BeamNode
()
{
if
(
parent_
)
{
parent_
->
DropKid
(
this
);
if
(
parent_
->
kids_
.
size
()
==
0UL
)
{
delete
parent_
;
}
}
VLOG
(
3
)
<<
"Delete BeamNode root with word_id:"
<<
this
->
word_id_
;
}
void
AppendTo
(
BeamNode
*
parent
)
{
parent_
=
parent
;
parent
->
kids_
.
insert
(
this
);
}
void
DropKid
(
BeamNode
*
kid
)
{
kids_
.
erase
(
kid
);
}
BeamNode
*
parent_
=
nullptr
;
std
::
unordered_set
<
BeamNode
*>
kids_
;
int64_t
word_id_
;
T
score_
;
};
template
<
typename
T
>
using
BeamNodeVector
=
std
::
vector
<
std
::
unique_ptr
<
BeamNode
<
T
>>>
;
template
<
typename
T
>
struct
Sentence
{
std
::
vector
<
int64_t
>
word_ids
;
...
...
@@ -77,25 +47,6 @@ struct BeamSearchDecoder {
BeamSearchDecoder
(
size_t
beam_size
,
int
end_id
)
:
beam_size_
(
beam_size
),
end_id_
(
end_id
)
{}
/**
* make a BeamNode and all it's related prefix BeanNode into a Sentence.
*/
Sentence
<
T
>
MakeSentence
(
const
BeamNode
<
T
>*
node
)
const
;
/**
* Param:
* cur_ids: LoDTensor of One step for word ID
* cur_scores: LoDTensor of One Step for word score
* prefixes_list: prefixes for each source sentence.
* sentence_vector_list: result sentence_vector for each source sentence.
* Return:
* a new prefixes list for each source of current step
*/
std
::
vector
<
BeamNodeVector
<
T
>>
PackTwoSteps
(
const
LoDTensor
&
cur_ids
,
const
LoDTensor
&
cur_scores
,
std
::
vector
<
BeamNodeVector
<
T
>>*
prefixes_list
,
std
::
vector
<
SentenceVector
<
T
>>*
sentence_vector_list
)
const
;
/**
* convert the result sentence_vector for each source sentence into two
* LodTensor.
...
...
@@ -105,29 +56,18 @@ struct BeamSearchDecoder {
* sentence_vector_list: sentence_vector for each source sentence.
* id_tensor: result LoDTensor for sentences of id.
* score_tensor: result LoDTensor for sentences of score.
* reverse: whether ids of sentence in sentence_vector_list is reversed
* sort_by_score: whether to sort hypotheses of each sentence by scores.
*/
void
ConvertSentenceVectorToLodTensor
(
std
::
vector
<
SentenceVector
<
T
>>
sentence_vector_list
,
LoDTensor
*
id_tensor
,
LoDTensor
*
score_tensor
,
bool
reverse
=
fals
e
,
LoDTensor
*
score_tensor
,
bool
reverse
=
tru
e
,
bool
sort_by_score
=
true
)
const
;
/**
* Pack all steps of id/score LodTensor into sentence LoDTensor
* it's main logic is:
* ```python
* prefix
* result_sentence
* result_lod_tensor
*
* for (step in steps):
* prefix = PackTwoSteps(prefix, step, &result_sentence)
* ConvertSentenceVector<T>ToLodTensor(result_sentence, &result_lod_tensor)
* ```
* Gather the hypotheses for each source sentence by backtrace though the
* LoDTensorArray step_ids whose lods reserve the path in the tree.
*/
void
PackAllSteps
(
const
LoDTensorArray
&
step_ids
,
const
LoDTensorArray
&
step_scores
,
LoDTensor
*
id_tensor
,
LoDTensor
*
score_tensor
)
const
;
void
Backtrace
(
const
LoDTensorArray
&
step_ids
,
const
LoDTensorArray
&
step_scores
,
LoDTensor
*
id_tensor
,
LoDTensor
*
score_tensor
)
const
;
...
...
@@ -136,80 +76,6 @@ struct BeamSearchDecoder {
int
end_id_
;
};
template
<
typename
T
>
Sentence
<
T
>
BeamSearchDecoder
<
T
>::
MakeSentence
(
const
BeamNode
<
T
>*
node
)
const
{
Sentence
<
T
>
sentence
;
while
(
node
!=
nullptr
)
{
sentence
.
word_ids
.
emplace_back
(
node
->
word_id_
);
sentence
.
scores
.
emplace_back
(
node
->
score_
);
node
=
node
->
parent_
;
}
std
::
reverse
(
std
::
begin
(
sentence
.
word_ids
),
std
::
end
(
sentence
.
word_ids
));
std
::
reverse
(
std
::
begin
(
sentence
.
scores
),
std
::
end
(
sentence
.
scores
));
return
sentence
;
}
template
<
typename
T
>
std
::
vector
<
BeamNodeVector
<
T
>>
BeamSearchDecoder
<
T
>::
PackTwoSteps
(
const
LoDTensor
&
cur_ids
,
const
LoDTensor
&
cur_scores
,
std
::
vector
<
BeamNodeVector
<
T
>>*
prefixes_list
,
std
::
vector
<
SentenceVector
<
T
>>*
sentence_vector_list
)
const
{
std
::
vector
<
BeamNodeVector
<
T
>>
result
;
for
(
size_t
src_idx
=
0
;
src_idx
<
cur_ids
.
lod
()[
kSourceLevel
].
size
()
-
1
;
++
src_idx
)
{
size_t
src_start
=
cur_ids
.
lod
().
at
(
kSourceLevel
)[
src_idx
];
size_t
src_end
=
cur_ids
.
lod
().
at
(
kSourceLevel
)[
src_idx
+
1
];
BeamNodeVector
<
T
>
beam_nodes
;
// if prefixes size is 0, it means this is the first step. In this step,
// all candidate id is the start of candidate sentences.
if
(
prefixes_list
->
empty
())
{
PADDLE_ENFORCE_EQ
(
cur_ids
.
lod
().
at
(
kSourceLevel
).
back
(),
cur_ids
.
lod
().
at
(
kSentenceLevel
).
back
(),
"in the first step"
);
for
(
size_t
id_idx
=
src_start
;
id_idx
<
src_end
;
++
id_idx
)
{
beam_nodes
.
push_back
(
std
::
unique_ptr
<
BeamNode
<
T
>>
(
new
BeamNode
<
T
>
(
cur_ids
.
data
<
int64_t
>
()[
id_idx
],
cur_scores
.
data
<
T
>
()[
id_idx
])));
}
}
else
{
BeamNodeVector
<
T
>&
prefixes
=
prefixes_list
->
at
(
src_idx
);
SentenceVector
<
T
>&
sentence_vector
=
(
*
sentence_vector_list
)[
src_idx
];
PADDLE_ENFORCE_EQ
(
src_end
-
src_start
,
prefixes
.
size
(),
"prefix and candidate set number should be the same"
);
auto
candidate_offset
=
cur_ids
.
lod
()[
kSentenceLevel
];
for
(
size_t
prefix_idx
=
0
;
prefix_idx
<
prefixes
.
size
();
++
prefix_idx
)
{
std
::
unique_ptr
<
BeamNode
<
T
>>&
prefix
=
prefixes
[
prefix_idx
];
size_t
candidate_start
=
candidate_offset
[
src_start
+
prefix_idx
];
size_t
candidate_end
=
candidate_offset
[
src_start
+
prefix_idx
+
1
];
if
(
candidate_start
==
candidate_end
)
{
VLOG
(
3
)
<<
"this sentence has no more candidate, "
"add to result sentence and rm it from beam tree"
;
sentence_vector
.
push_back
(
MakeSentence
(
prefix
.
get
()));
prefix
.
reset
();
}
else
{
for
(
size_t
candidate_idx
=
candidate_start
;
candidate_idx
<
candidate_end
;
++
candidate_idx
)
{
auto
*
candidate
=
new
BeamNode
<
T
>
(
cur_ids
.
data
<
int64_t
>
()[
candidate_idx
],
cur_scores
.
data
<
T
>
()[
candidate_idx
]);
candidate
->
AppendTo
(
prefix
.
get
());
beam_nodes
.
push_back
(
std
::
unique_ptr
<
BeamNode
<
T
>>
(
candidate
));
}
prefix
.
release
();
}
}
}
result
.
push_back
(
std
::
move
(
beam_nodes
));
}
return
result
;
}
template
<
typename
T
>
void
BeamSearchDecoder
<
T
>::
ConvertSentenceVectorToLodTensor
(
std
::
vector
<
SentenceVector
<
T
>>
sentence_vector_list
,
LoDTensor
*
id_tensor
,
...
...
@@ -273,42 +139,6 @@ void BeamSearchDecoder<T>::ConvertSentenceVectorToLodTensor(
framework
::
TensorFromVector
<
T
>
(
score_data
,
cpu_ctx
,
score_tensor
);
}
template
<
typename
T
>
void
BeamSearchDecoder
<
T
>::
PackAllSteps
(
const
LoDTensorArray
&
step_ids
,
const
LoDTensorArray
&
step_scores
,
LoDTensor
*
id_tensor
,
LoDTensor
*
score_tensor
)
const
{
PADDLE_ENFORCE
(
!
step_ids
.
empty
(),
"step num should be larger than 0"
);
PADDLE_ENFORCE_EQ
(
step_ids
.
size
(),
step_scores
.
size
(),
"step_ids and step_scores should be the same"
);
const
size_t
step_num
=
step_ids
.
size
();
const
size_t
src_num
=
step_ids
.
at
(
0
).
lod
().
at
(
kSourceLevel
).
size
()
-
1
;
PADDLE_ENFORCE_GT
(
src_num
,
0UL
,
"source num should be larger than 0"
);
// previous prefixes for each step,
// the init length is 0, means this is the first step.
std
::
vector
<
BeamNodeVector
<
T
>>
beamnode_vector_list
(
0
);
std
::
vector
<
SentenceVector
<
T
>>
sentence_vector_list
(
src_num
);
// pack all steps for one batch first, then another batch
for
(
size_t
step_id
=
0
;
step_id
<
step_num
;
++
step_id
)
{
beamnode_vector_list
=
PackTwoSteps
(
step_ids
.
at
(
step_id
),
step_scores
.
at
(
step_id
),
&
beamnode_vector_list
,
&
sentence_vector_list
);
}
// append last beam_node to result
for
(
size_t
src_idx
=
0
;
src_idx
<
src_num
;
++
src_idx
)
{
for
(
auto
&
beam_node
:
beamnode_vector_list
.
at
(
src_idx
))
{
sentence_vector_list
[
src_idx
].
push_back
(
MakeSentence
(
beam_node
.
get
()));
beam_node
.
reset
();
}
}
ConvertSentenceVectorToLodTensor
(
sentence_vector_list
,
id_tensor
,
score_tensor
);
}
template
<
typename
T
>
void
BeamSearchDecoder
<
T
>::
Backtrace
(
const
LoDTensorArray
&
step_ids
,
const
LoDTensorArray
&
step_scores
,
...
...
paddle/fluid/operators/beam_search_decode_op_test.cc
浏览文件 @
a281e101
...
...
@@ -20,15 +20,11 @@ using LoD = paddle::framework::LoD;
using
LoDTensor
=
paddle
::
framework
::
LoDTensor
;
using
LoDTensorArray
=
paddle
::
framework
::
LoDTensorArray
;
template
<
typename
T
>
using
BeamNode
=
paddle
::
operators
::
BeamNode
<
T
>
;
template
<
typename
T
>
using
BeamSearchDecoder
=
paddle
::
operators
::
BeamSearchDecoder
<
T
>
;
template
<
typename
T
>
using
Sentence
=
paddle
::
operators
::
Sentence
<
T
>
;
template
<
typename
T
>
using
BeamNodeVector
=
paddle
::
operators
::
BeamNodeVector
<
T
>
;
template
<
typename
T
>
using
SentenceVector
=
paddle
::
operators
::
SentenceVector
<
T
>
;
namespace
paddle
{
...
...
@@ -77,138 +73,50 @@ void GenerateExample(const std::vector<size_t>& level_0,
}
// namespace test
}
// namespace paddle
TEST
(
BeamSearchDecodeOp
,
DeleteBeamNode
)
{
auto
*
root
=
new
BeamNode
<
float
>
(
0
,
0
);
auto
*
b1
=
new
BeamNode
<
float
>
(
1
,
1
);
auto
*
b2
=
new
BeamNode
<
float
>
(
2
,
2
);
auto
*
b3
=
new
BeamNode
<
float
>
(
3
,
3
);
b1
->
AppendTo
(
root
);
b2
->
AppendTo
(
root
);
b3
->
AppendTo
(
b1
);
delete
b3
;
delete
b2
;
}
TEST
(
BeamSearchDecodeOp
,
MakeSentence
)
{
auto
*
root
=
new
BeamNode
<
float
>
(
0
,
0
);
auto
*
b1
=
new
BeamNode
<
float
>
(
1
,
1
);
auto
*
end
=
new
BeamNode
<
float
>
(
2
,
2
);
b1
->
AppendTo
(
root
);
end
->
AppendTo
(
b1
);
BeamSearchDecoder
<
float
>
helper
;
Sentence
<
float
>
sentence
=
helper
.
MakeSentence
(
end
);
delete
end
;
std
::
vector
<
int64_t
>
expect_ids
=
{
0
,
1
,
2
};
ASSERT_EQ
(
sentence
.
word_ids
,
expect_ids
);
std
::
vector
<
float
>
expect_scores
=
{
0
,
1
,
2
};
ASSERT_EQ
(
sentence
.
scores
,
expect_scores
);
}
TEST
(
BeamSearchDecodeOp
,
PackTwoStepsFistStep
)
{
CPUPlace
place
;
LoDTensorArray
ids
;
LoDTensorArray
scores
;
paddle
::
test
::
GenerateExample
(
std
::
vector
<
size_t
>
{
0
,
2
,
6
},
std
::
vector
<
size_t
>
{
0
,
1
,
2
,
3
,
4
,
5
,
6
},
std
::
vector
<
int
>
{
1
,
2
,
3
,
4
,
5
,
6
},
&
ids
,
&
scores
);
std
::
vector
<
BeamNodeVector
<
float
>>
beamnode_vector_list
;
std
::
vector
<
SentenceVector
<
float
>>
sentence_vector_list
(
2
,
SentenceVector
<
float
>
());
BeamSearchDecoder
<
float
>
helper
;
beamnode_vector_list
=
helper
.
PackTwoSteps
(
ids
[
0
],
scores
[
0
],
&
beamnode_vector_list
,
&
sentence_vector_list
);
ASSERT_EQ
(
beamnode_vector_list
.
size
(),
2UL
);
ASSERT_EQ
(
beamnode_vector_list
[
0
].
size
(),
2UL
);
ASSERT_EQ
(
beamnode_vector_list
[
1
].
size
(),
4UL
);
}
TEST
(
BeamSearchDecodeOp
,
PackTwoSteps
)
{
CPUPlace
place
;
// first source has three prefix
BeamNodeVector
<
float
>
source0_prefixes
;
source0_prefixes
.
push_back
(
std
::
unique_ptr
<
BeamNode
<
float
>>
(
new
BeamNode
<
float
>
(
1
,
1
)));
source0_prefixes
.
push_back
(
std
::
unique_ptr
<
BeamNode
<
float
>>
(
new
BeamNode
<
float
>
(
0
,
0
)));
source0_prefixes
.
push_back
(
std
::
unique_ptr
<
BeamNode
<
float
>>
(
new
BeamNode
<
float
>
(
3
,
3
)));
// second source has two prefix
BeamNodeVector
<
float
>
source1_prefixes
;
source1_prefixes
.
push_back
(
std
::
unique_ptr
<
BeamNode
<
float
>>
(
new
BeamNode
<
float
>
(
4
,
4
)));
source1_prefixes
.
push_back
(
std
::
unique_ptr
<
BeamNode
<
float
>>
(
new
BeamNode
<
float
>
(
5
,
5
)));
std
::
vector
<
BeamNodeVector
<
float
>>
beamnode_vector_list
;
std
::
vector
<
SentenceVector
<
float
>>
sentence_vector_list
(
2
,
SentenceVector
<
float
>
());
beamnode_vector_list
.
push_back
(
std
::
move
(
source0_prefixes
));
beamnode_vector_list
.
push_back
(
std
::
move
(
source1_prefixes
));
// generate data for one step
LoDTensorArray
ids
;
LoDTensorArray
scores
;
paddle
::
test
::
GenerateExample
(
std
::
vector
<
size_t
>
{
0
,
3
,
5
},
std
::
vector
<
size_t
>
{
0
,
1
,
1
,
3
,
4
,
5
},
std
::
vector
<
int
>
{
0
,
1
,
2
,
3
,
4
},
&
ids
,
&
scores
);
BeamSearchDecoder
<
float
>
helper1
;
beamnode_vector_list
=
helper1
.
PackTwoSteps
(
ids
[
0
],
scores
[
0
],
&
beamnode_vector_list
,
&
sentence_vector_list
);
ASSERT_EQ
(
sentence_vector_list
[
0
].
size
(),
1UL
);
ASSERT_EQ
(
sentence_vector_list
[
1
].
size
(),
0UL
);
ASSERT_EQ
(
beamnode_vector_list
[
0
].
size
(),
3UL
);
ASSERT_EQ
(
beamnode_vector_list
[
1
].
size
(),
2UL
);
}
TEST
(
BeamSearchDecodeOp
,
PackAllSteps
)
{
TEST
(
BeamSearchDecodeOp
,
Backtrace
)
{
CPUPlace
place
;
// we will constuct a sample data with 3 steps and 2 source sentences
// we will constuct a sample data with 4 steps and 2 source sentences
// beam_size = 2, start_id = 0, end_id = 1
LoDTensorArray
ids
;
LoDTensorArray
scores
;
paddle
::
test
::
GenerateExample
(
std
::
vector
<
size_t
>
{
0
,
3
,
6
},
std
::
vector
<
size_t
>
{
0
,
1
,
2
,
3
,
4
,
5
,
6
},
std
::
vector
<
int
>
{
1
,
2
,
3
,
4
,
5
,
6
},
&
ids
,
&
scores
);
std
::
vector
<
size_t
>
{
0
,
1
,
2
},
std
::
vector
<
size_t
>
{
0
,
1
,
2
},
std
::
vector
<
int
>
{
0
,
0
},
&
ids
,
&
scores
);
// start with start_id
paddle
::
test
::
GenerateExample
(
std
::
vector
<
size_t
>
{
0
,
1
,
2
},
std
::
vector
<
size_t
>
{
0
,
2
,
4
},
std
::
vector
<
int
>
{
2
,
3
,
4
,
5
},
&
ids
,
&
scores
);
paddle
::
test
::
GenerateExample
(
std
::
vector
<
size_t
>
{
0
,
2
,
4
},
std
::
vector
<
size_t
>
{
0
,
2
,
2
,
4
,
4
},
std
::
vector
<
int
>
{
3
,
1
,
5
,
4
},
&
ids
,
&
scores
);
paddle
::
test
::
GenerateExample
(
std
::
vector
<
size_t
>
{
0
,
2
,
4
},
std
::
vector
<
size_t
>
{
0
,
1
,
2
,
3
,
4
},
std
::
vector
<
int
>
{
1
,
1
,
3
,
5
},
&
ids
,
&
scores
);
paddle
::
test
::
GenerateExample
(
std
::
vector
<
size_t
>
{
0
,
3
,
6
},
std
::
vector
<
size_t
>
{
0
,
1
,
1
,
3
,
5
,
5
,
6
},
std
::
vector
<
int
>
{
0
,
1
,
2
,
3
,
4
,
5
},
&
ids
,
&
scores
);
paddle
::
test
::
GenerateExample
(
std
::
vector
<
size_t
>
{
0
,
3
,
6
},
std
::
vector
<
size_t
>
{
0
,
0
,
1
,
2
,
3
,
4
,
5
},
std
::
vector
<
int
>
{
0
,
1
,
2
,
3
,
4
},
&
ids
,
&
scores
);
std
::
vector
<
size_t
>
{
0
,
2
,
4
},
std
::
vector
<
size_t
>
{
0
,
0
,
0
,
2
,
2
},
// the branchs of the first source sentence
// are pruned since finished
std
::
vector
<
int
>
{
5
,
1
},
&
ids
,
&
scores
);
ASSERT_EQ
(
ids
.
size
(),
3
UL
);
ASSERT_EQ
(
scores
.
size
(),
3
UL
);
ASSERT_EQ
(
ids
.
size
(),
5
UL
);
ASSERT_EQ
(
scores
.
size
(),
5
UL
);
BeamSearchDecoder
<
float
>
helper
;
BeamSearchDecoder
<
float
>
helper
(
2
,
1
);
// beam_size = 2, end_id = 1
LoDTensor
id_tensor
;
LoDTensor
score_tensor
;
helper
.
PackAllSteps
(
ids
,
scores
,
&
id_tensor
,
&
score_tensor
);
helper
.
Backtrace
(
ids
,
scores
,
&
id_tensor
,
&
score_tensor
);
LoD
lod
=
id_tensor
.
lod
();
std
::
vector
<
size_t
>
expect_source_lod
=
{
0
,
4
,
8
};
std
::
vector
<
size_t
>
expect_source_lod
=
{
0
,
2
,
4
};
EXPECT_EQ
(
lod
[
0
],
expect_source_lod
);
std
::
vector
<
size_t
>
expect_sentence_lod
=
{
0
,
1
,
3
,
6
,
9
,
10
,
13
,
16
,
19
};
std
::
vector
<
size_t
>
expect_sentence_lod
=
{
0
,
4
,
7
,
12
,
17
};
EXPECT_EQ
(
lod
[
1
],
expect_sentence_lod
);
// 2| 1, 0| 3, 1, 0| 3, 2, 1| 5| 4, 3, 2| 4, 4, 3| 6, 5, 4
std
::
vector
<
int
>
expect_data
=
{
2
,
1
,
0
,
3
,
1
,
0
,
3
,
2
,
1
,
5
,
4
,
3
,
2
,
4
,
4
,
3
,
6
,
5
,
4
};
std
::
vector
<
int
>
expect_data
=
{
0
,
2
,
3
,
1
,
0
,
2
,
1
,
0
,
4
,
5
,
3
,
5
,
0
,
4
,
5
,
3
,
1
};
ASSERT_EQ
(
id_tensor
.
dims
()[
0
],
static_cast
<
int64_t
>
(
expect_data
.
size
()));
for
(
size_t
i
=
0
;
i
<
expect_data
.
size
();
++
i
)
{
ASSERT_EQ
(
id_tensor
.
data
<
int64_t
>
()[
i
],
...
...
paddle/fluid/operators/beam_search_op.cc
浏览文件 @
a281e101
...
...
@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and
limitations under the License. */
#include <algorithm>
#include <limits>
#include <map>
#include <string>
#include <vector>
...
...
@@ -110,23 +109,6 @@ void BeamSearch::PruneEndBeams(const framework::LoDTensor &pre_ids,
}
}
int
BeamSearch
::
PruneEndidCandidates
(
const
framework
::
LoDTensor
&
pre_ids
,
std
::
vector
<
std
::
vector
<
Item
>>
*
items
)
{
auto
*
pre_ids_data
=
pre_ids
.
data
<
int64_t
>
();
int
res
=
0
;
for
(
size_t
offset
=
0
;
offset
<
items
->
size
();
offset
++
)
{
auto
prefix_id
=
pre_ids_data
[
offset
];
if
(
prefix_id
==
end_id_
)
{
items
->
at
(
offset
).
clear
();
}
else
{
res
++
;
}
}
return
res
;
}
std
::
vector
<
std
::
vector
<
BeamSearch
::
Item
>>
BeamSearch
::
ToMap
(
const
std
::
vector
<
std
::
vector
<
Item
>>
&
items
,
size_t
element_num
)
{
std
::
vector
<
std
::
vector
<
Item
>>
result
;
...
...
@@ -201,8 +183,7 @@ bool BeamSearch::NextItemSet(const framework::LoDTensor &pre_ids,
auto
pre_score
=
pre_scores_data
[
offset
];
if
(
pre_id
==
end_id_
)
{
// Allocate all probability mass to eos_id for finished branchs and the
// other
// candidate ids can be ignored.
// other candidate ids can be ignored.
items
->
emplace_back
(
offset
,
end_id_
,
pre_score
);
}
else
{
for
(
size_t
d
=
0
;
d
<
instance_dim
;
d
++
)
{
...
...
paddle/fluid/operators/beam_search_op.h
浏览文件 @
a281e101
...
...
@@ -155,17 +155,11 @@ class BeamSearch {
protected:
/*
* Prune the source sentences all branchs finished, and it is optional.
* Pruning must one step later than finishing, since the end tokens
* must be writed out. Also the finished branchs with top 1 score can
* be pruned.
* Pruning must one step later than finishing (thus pre_ids is needed here),
* since the end tokens must be writed out.
*/
void
PruneEndBeams
(
const
framework
::
LoDTensor
&
pre_ids
,
std
::
vector
<
std
::
vector
<
Item
>>*
items
);
/*
* Delete all the records that follows the end token.
*/
int
PruneEndidCandidates
(
const
framework
::
LoDTensor
&
pre_ids
,
std
::
vector
<
std
::
vector
<
Item
>>*
items
);
/*
* Transform the items into a map whose key is offset, value is the items.
...
...
paddle/fluid/operators/beam_search_op_test.cc
浏览文件 @
a281e101
...
...
@@ -30,7 +30,7 @@ using std::endl;
void
CreateInput
(
LoDTensor
*
ids
,
LoDTensor
*
scores
)
{
LoD
lod
;
vector
<
size_t
>
level0
({
0
,
1
,
4
});
vector
<
size_t
>
level0
({
0
,
2
,
4
});
vector
<
size_t
>
level1
({
0
,
1
,
2
,
3
,
4
});
lod
.
push_back
(
level0
);
lod
.
push_back
(
level1
);
...
...
@@ -64,17 +64,22 @@ TEST(beam_search_op, run) {
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
pre_ids
.
mutable_data
<
int64_t
>
(
place
)[
i
]
=
i
+
1
;
}
LoDTensor
pre_scores
;
pre_scores
.
Resize
(
framework
::
make_ddim
(
vector
<
int64_t
>
(
4
,
1
)));
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
pre_scores
.
mutable_data
<
float
>
(
place
)[
i
]
=
0.1
;
}
BeamSearch
beamsearch
(
ids
,
scores
,
(
int64_t
)
0
,
(
int64
_t
)
2
,
0
);
BeamSearch
beamsearch
(
ids
,
scores
,
(
size_t
)
0
,
(
size
_t
)
2
,
0
);
LoDTensor
sids
,
sscores
;
beamsearch
(
pre_ids
,
&
sids
,
&
sscores
);
beamsearch
(
pre_ids
,
pre_scores
,
&
sids
,
&
sscores
);
LOG
(
INFO
)
<<
"score: "
<<
sscores
<<
endl
;
ASSERT_EQ
(
sids
.
lod
(),
sscores
.
lod
());
vector
<
int
>
tids
({
2
,
4
,
3
,
8
});
vector
<
float
>
tscores
({
0.
3
,
0.5
,
0.9
,
0.7
});
vector
<
int
>
tids
({
4
,
2
,
3
,
8
});
vector
<
float
>
tscores
({
0.
5
,
0.6
,
0.9
,
0.7
});
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
ASSERT_EQ
(
tids
[
i
],
sids
.
data
<
int64_t
>
()[
i
]);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录