作用
Transformer与CNN和RNN等模型不一样,CNN使用的是卷积,相当于是局部的注意力机制,而RNN本来就是可以处理时序信息,当抛弃循环神经网络结构,完全采用Attention取而代之,词序信息就会丢失,模型就没有办法知道每个词在句子中的相对和绝对的位置信息。但是Transformer需要使用位置编码(positional encoding)来进行时序的处理。
实现
首先我们会有一个直观的想法,分配一个0到1之间的数值给每个时间步,其中,0表示第一个词,1表示最后一个词。这种方法虽然简单,但会带来很多问题。其中一个就是你无法知道在一个特定区间范围内到底存在多少个单词。比如有的句子很长,有的很短。
另外的一个想法是线性分配一个数值给每个时间步。也就是,1分配给第一个词,2分配给第二个词,以此类推。存在的问题是,不仅这些数值会变得非常大,而且模型也会遇到一些比训练中的所有句子都要长的句子。此外,数据集中不一定在所有数值上都会包含相对应长度的句子,也就是模型很有可能没有看到过任何一个这样的长度的样本句子,这会严重影响模型的泛化能力。
所以良好的位置编码需要:
- 它能为每个时间步输出一个独一无二的编码;
- 不同长度的句子之间,任何两个时间步之间的距离应该保持一致;
- 模型应该能毫不费力地泛化到更长的句子。它的值应该是有界的;
- 它必须是确定性的。
transformer中的位置编码(正弦位置编码)
位置编码PE和词向量的维度需要保持一致,才能之后相加。其中pos是词的输入的位置,i是维度,我的理解是正弦编码需要不同的频率来对位置进行编码,将距离信息表现的更充分。
我们举一个例子来说明,pos=3,d(model)=128,位置是3,词向量的维度是128.那么位置编码如下: