跳到主要内容

位置编码

为什么需要位置编码

  • 对于任何一门语言,单词在句子中的位置以及排列顺序是非常重要的,它们不仅是一个句子的语法结构的组成部分,更是表达语义的重要概念。
  • Transformer 模型抛弃了 RNN、LSTM、GRU 作为序列学习的基本模型。我们知道,RNN 本身就是一种顺序结构,天生就包含了词在序列中的位置信息。当抛弃 RNN 结构,完全采用 Attention 取而代之,这些词序信息就会丢失。

怎么实现位置编码

最简单的位置编码是:第一个 token 编码为 0,第一个 token 编码为 1,以此类推。这种方法带来的问题是,不仅这些数值会变得非常大,而且模型也会遇到一些比训练中的所有句子都要长的句子。此外,数据集中不一定在所有数值上都会包含相对应长度的句子,也就是模型很有可能没有看到过任何一个这样的长度的样本句子,这会严重影响模型的泛化能力。

因此,一种好的位置编码方案需要满足以下几条要求:

  • 能够为每个时间步输出一个独一无二的编码
  • 给定任意一个位置,编码的值必须是确定性的 (而不是需要在机器学习中的超参数)
  • 固定步长的两个位置的编码,应该存在一定的关系
  • 模型应该能泛化到更长的句子

Transformer 的位置编码

Transformer 的位置编码为:

PE(pos,2i)=sin(pos100002i/dmodel),PE(pos,2i+1)=cos(pos100002i/dmodel).\begin{aligned} \text{PE}_{(pos,2i)}=sin\left(\frac{pos}{10000^{2i/d_{model}}}\right), \\ \text{PE}_{(pos,2i+1)}=cos\left(\frac{pos}{10000^{2i/d_{model}}}\right). \end{aligned}

其中 pospos 为位置编号,ii 是维度编号。

为什么采用这种编码?我们看一下说明:

We chose this function because we hypothesized it would allow the model to easily learn to attend by relative positions, since for any fixed offset kk, PEpos+kPE_{pos+k} can be represented as a linear function of PEposPE_{pos}.

这句话的意思是,上面的编码能够让模型轻松关注相对位置。给定距离为 kk 的两个位置,其编码 PEpos+kPE_{pos+k}PEposPE_{pos} 存在固定的线性变换关系。

从结果来看,Transformer 的位置编码能够有效泛化到更长的句子。

需要明确的是,这不代表其为唯一可行的位置编码方案。

Transformer 编码的可视化

下图为对 20 个位置编码为的示例,其中每个位置编码为 512 维的向量。左半部分是维度为 2i2i 的正弦编码,右半部分是是维度为 2i2i 的余弦编码。

将它们交叉连接,就是 Transformer 使用的位置编码向量。