[WIP] 支持Padding的LoDTensor
Created by: velconia
当前 LoD 设计
using LoD = std::vector<Vector<size_t>>;
面临的问题
支持用户更习惯的 Padding 模式
Paddle整体基于LoD
解决方案
设计
基于LoD支持Padding
我们的框架现在有两种数据结构,LodTensor, SelectedRows;
SelectedRows 只有在 sparse embedding 情况下才会发生,在此不表, 只讨论 LodTensor;
LoDTensor 现在有两种情况:
1. 表示变长数据的LoDTensor:
如下的长度分别为 (3, 2, 4)的三个输入:
22, 23, 24;
22, 21;
19, 18, 11, 10;
LoDTensor 将数据sequence的变长信息表示为 LoD :
0, 3, 5, 9
而数据本身被表示为一个 shape 为 [3 + 2 + 4 = 9, 1] 的一个张量;
2. 表示张量数据的LoDTensor:
LoDTensor中的LoD信息为空;
退化为不包含关于数据sequence变长信息的一个张量;
现在,为了支持 Padding, 我们引入第三种特例:
3. 表示被Padding的变长数据的LodTensor
LoDTensor的LoD值各个相等:
对于如下被 padding 过的用户输入:
22, 23, 24, 0;
22, 21, 0, 0;
19, 18, 11, 10;
LoDTensor 将数据sequence的变长信息表示为 LoD :
0, 4, 8, 12
而数据本身被表示为一个 shape 为 [4 + 4 + 4 = 12, 1] 的一个张量;
新的RNN Layer
我们参考 Tensorflow 的代码:
seq_max_len = 20 # Sequence max length
x = tf.placeholder("float", [None, seq_max_len, 1])
seqlen = tf.placeholder(tf.int32, [None])
weights = {
'out': tf.Variable(tf.random_normal([n_hidden, n_classes]))
}
biases = {
'out': tf.Variable(tf.random_normal([n_classes]))
}
pred = dynamicRNN(x, seqlen, weights, biases)
x 是 Padding 后的数据,seq_max_len 是序列最大长度,seqlen 是各个序列的真实长度;
所以我们的在将 LoDTensor 改为 表示被Padding的变长数据的LodTensor
后,
我们还需要让用户像 Tensorflow 一样,传入 seqlen 来表示各个序列的真实长度;
收益
- Padding 问题被简化为 LoDTensor 的一个特例,得到解决;
- 对框架改动不大,实现代价小;
- 有关LoDTensor的性能问题可以统一进行优化;