Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Crayon鑫
Paddle
提交
a74e7981
P
Paddle
项目概览
Crayon鑫
/
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看板
提交
a74e7981
编写于
7月 27, 2017
作者:
S
Superjom
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add an appendix to explain sequence info data structure
上级
81016bb0
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
117 addition
and
16 deletion
+117
-16
paddle/operators/rnn_design.md
paddle/operators/rnn_design.md
+117
-16
未找到文件。
paddle/operators/rnn_design.md
浏览文件 @
a74e7981
...
...
@@ -31,29 +31,80 @@
-
额外会有一个
`SeqPosVar`
,存储句子的结构,比如offest:
`0,2,5,9`
为了支持sub-sequence,Paddle里使用
`Argument.subSequenceStartPositions`
来存储2维的序列信息,更高维度的序列无法支持;
这里为了扩展性,将SeqPosVar定义成如下数据结构来支持N维的序列信息的存储
:
这里为了扩展性,将SeqPosVar定义成如下数据结构来支持N维的序列信息的存储
```
c++
struct
SeqPos
{
int
dim
{
1
};
std
::
vector
<
std
::
shared_ptr
<
std
::
vector
<
int
>>
startPoses
;
};
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>
seq_start_positions_
;
```
其中,startPoses可以用于存储多维的子序列,具体如下:
-
如果为1维序列,则
`dim=1`
,
`startPoses.size() = 1`
-
如果为 2 维序列,则
`dim=2`
,
`startPoses[0]`
存储第一维序列信息,
`startPoses[1:]`
存储第二维序列信息
-
如果为 n 维序列,则
`dim=n`
,
`startPoses[0]`
存储第一维序列,后续追加第
`2.. n`
维序列
-
当有完整的 n 维序列的
`SeqPos`
信息时,可以从前往后,粒度从粗到细解析序列
-
当拆解成 n-1 维序列时,
`dim=n-1`
,startPoses 去除第 1 维序列信息,为每个次级序列单独抽取出对应的信息组成新的
`SeqPos`
附录中演示如何用二维的vector来存储多个 level 的变长序列的start position.
Tensor 扩展为
```
c++
struct
TensorWithSequence
{
Tensor
*
tensor
;
std
::
shared_ptr
<
SeqPos
>
seq_pos
;
}
/*
* Tensor storing sequences.
*/
class
TensorWithSequence
{
public:
Tenser
*
tensor
()
{
return
tensor_
;
}
/*
* get an element of current level.
*/
TensorWithSequence
Element
(
int
element
)
const
;
/*
* get an element of n-th level.
* NOTE low performance.
*/
TensorWithSequence
Element
(
int
level
,
int
element
)
const
;
/*
* get number of elements in n-th level.
*/
size_t
Elements
(
int
level
=
0
)
const
;
/*
* get the number of levels of sequences.
*/
size_t
Levels
()
const
;
/*
* copy other's pointers to share their data.
*/
void
ShareDataFrom
(
const
TensorWithSequence
&
other
);
/*
* just copy other's sequence info (use shared_ptr to share memory).
*/
void
ShareSeqPosFrom
(
const
TensorWithSequence
&
other
);
/*
* copy others' sequence info for mutation.
*/
void
CopySeqPosFrom
(
const
TensorWithSequence
&
other
);
private:
Tensor
*
tensor_
;
/*
* store start positions of all levels.
*
* data format like
*
* 0-th level start positions
* 1-th level, element 0, start positions
* 1-th level, element 1, start positions
* ...
* 1-th level, element k, start positions
* 2-th level, element 0, start positions
* 2-th level, element 1, start positions
* ...
* 2-th level, element n, start positions
* ...
*
*/
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>
seq_start_positions_
;
};
```
## 框架支持方法
...
...
@@ -144,6 +195,56 @@ x x
-
将每个时间步的输出重新还原为原始输入的序列顺序(以防止Infer阶段顺序打乱)
-
将序列折叠,在batch维度上展开
## 附录
这里演示多level的变长序列的存储方法,本设计会用两层的
`vector`
来存储所有序列的信息,具体数据格式如下
```
c++
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>
seq_start_positions_
;
```
为了方便讨论,可以临时修改为
```
c++
typedef
std
::
vector
<
int
>
element_t
;
std
::
vector
<
element_t
>
seq_start_positions_
;
```
假设tensor 里按batch存储 instance作为基本单位,
默认序列里的元素都是相邻排列,
因此只需要以instance 为基本单位,
记录 start position就可以分解出每个序列的信息。
`seq_start_positions_`
里从上往下存储着
`level 0 ~ level L`
的元素,可以认为level越小,表示的序列粒度越大。
比如存储
`batch of paragraphs`
则有
-
`level 0`
存储 paragraphs 的 start positions
-
`level 1`
存储 sentences 的 start positions
因为 tensor 里存储着batch of words,所以以上两个level的start positions的单位均为word。
具体地,假设有如下例子,比如需要存储 batch of paragraphs,tensor中存储了 batch of words,而序列信息如下
-
paragraph 0 has 3 sentences:
-
sentence 0 has 3 words
-
sentence 1 has 4 words
-
sentence 2 has 2 words
-
paragraph 1 has 2 sentences:
-
sentence 0 has 5 words
-
sentence 1 has 3 words
那么
`seq_start_positions_`
会有如下内容
-
0 9(=3+4+2)
-
0 3 7
-
0 5
其中每行是一个
`element_t`
,具体含义如下
-
`seq_start_positions_[0]`
存储了
`0 9`
,表示paragraph 0 在 tensor 中的偏移为 0,对应地, paragraph 1 为 9 (以word 为单位)
-
从
`seq_start_positions_[0]`
中可以知道,当前
`mini-batch`
总共只有 2 个 paragraph,因此后续的两个
`element_t`
分别存储了两个 paragraph 中句子的信息
-
紧接着
`seq_start_positions_[1]`
存储了第0个paragraph 的信息,表明有3个sentence,其在paragraph 0在tensor中对应部分的偏移分别为0,3 和7
-
紧接着
`seq_start_positions_[2]`
存储了第1个paragraph 的信息,表明有2个sentence,其在paragraph 0在tensor中对应部分的偏移分别为0和 5
如上证明了
`seq_start_positions_`
的数据结构适用于 level 为 1(也就是Paddle中subseq),通过归纳法可以证明其适用于 N level 的序列,这里暂不赘述。
## 参考文献
1.
[
Tensorflow Bucketing
](
https://www.tensorflow.org/versions/r0.12/api_docs/python/contrib.training/bucketing
)
2.
[
mxnet Bucketing
](
http://mxnet.io/how_to/bucketing.html
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录