preface:这个项目是一个简单的transformer架构完成英文-德文之间的翻译,也是本人进入NLP领域的第一个小项目,主要为了对transformer架构进一步熟悉,特别是decoder部分。
一、data preparing
数据集选择中德翻译数据集,采用BPE方法构建词表。
二、position encoding的几点思考?
(1)为什么不直接在 embedding 的数据上直接加上相应位置的数字?比如一个[17, 64, 512](17个句子,每个句子被BPE编码成64个tokens,每个tokens的embedding维度为512),可以设置一个[17, 64, 512]的矩阵,其中64个token每个都直接加相应的位置索引。
这样做如果句子特别长,最终BPE编码也会很长,直接加相应的位置索引可能最后一个token会加上一个很大的数字,最终会破坏embedding的信息。
(2)为什么不根据句子的长度进行设计 position encoding ?比如句子在BPE编码后的tokens 长度为 64,可以第一个token +
0
64
\frac{0}{64}
640, 第二个token +
1
64
\frac{1}{64}
641…,以此类推,最终所有的position encoding的值不会超过1。
这样做不太灵活(其实就是相对位置编码,需要学习),因为输入的训练数据的句子长度是变化的,如果第一个batch输入的长度是64,第二个batch输入的长度的 66,那么每次相同位置的position encoding的值都不同,所以模型可能会confused。(position encoding应该需要绝对位置,不需要学习)
(3)为什么最终使用 正弦-余弦编码呢
可以参考一下文章: 一文搞懂Transformer的位置编码
可以参考一下视频: Visual Guide to Transformer Neural Networks
transformer论文中采用的位置编码
P
E
(
p
o
s
,
2
i
)
=
s
i
n
(
p
o
s
1000
0
2
i
d
)
=
s
i
n
(
1
1000
0
2
i
d
×
p
o
s
)
PE(pos,2i) = sin(\frac{pos}{10000^{\frac{2i}{d}}})=sin(\frac{1}{10000^{\frac{2i}{d}}}\times pos)
PE(pos,2i)=sin(10000d2ipos)=sin(10000d2i1×pos)
P
E
(
p
o
s
,
2
i
+
1
)
=
c
o
s
(
p
o
s
1000
0
2
i
d
)
=
c
o
s
(
1
1000
0
2
i
d
×
p
o
s
)
PE(pos,2i+1) = cos(\frac{pos}{10000^{\frac{2i}{d}}})=cos(\frac{1}{10000^{\frac{2i}{d}}}\times pos)
PE(pos,2i+1)=cos(10000d2ipos)=cos(10000d2i1×pos)
其中,pos指的是一个句子经过BPE编码后的token的位置,
i
i
i指的是每个token经过embedding后embedding的维度,
d
d
d 表示每个token的embedding的维度,也就是transformer模型的输入维度。
总而言之,上面的两个公式就是利用不同的
2
i
d
\frac{2i}{d}
d2i来控制三角函数的周期,在每个embedding位置上产生不同周期的三角函数值,来告诉模型不同tokens的位置信息。