一文轻松搞懂Transformer PE位置编码

140 阅读5分钟

本文希望通过简洁的语言和例子,以一个更直观的角度向读者展示位置编码的特点及其作用。文章中的词指的是token。

Transformer需要词的位置信息

目前我们所熟知的各种国内外语言大模型均基于Transformer架构设计,该技术的核心是自注意力机制(关于自注意力、多头自注意力和带掩码的自注意力笔者将会在系列文章中详细讲解)。

当一个词表中的所有词经过Embedding变成一个个词向量后,如果直接输入给Transformer使用,那么任意两个词经过线性映射然后再做点积得到的注意力分数在任何句子中将是一样的,因为词向量不变,经过的计算步骤也不变的缘故,这样显然是有问题的,毕竟“我喜欢你”和“你喜欢我”中的“我”和“你”互换了位置,这种相同的词位置的不同导致句子语义发生的差异,或者导致词与词之间的关联情况的差异应当在计算中体现出来,才能让模型学习到这种差异。

对于深度学习中最常用的卷积神经网络CNN循环神经网络RNN,我们知道其计算过程就是按照位置逐步进行的,所以一般不需要额外给输入数据添加位置信息,而由上所述,Transformer的输入数据则需要我们人为地为其注入位置信息。

如何设计位置编码?

位置编码的设计不局限于某种形式。如果能够在位置编码信息中同时表达出一个词在句子中的位置也就是绝对位置以及一个词与其他词的相对位置,那么这种编码就是符合基本要求的。

例句“早上八点上班”中包含了6个词,每个词的词向量长度假设是5,以“早”这个词的词向量为例:

早(0.11,0.93,0.47,0.26,0.22)

方法一: 使用可学习的位置编码

也就是说把位置编码也作为模型训练时需要学习的参数,比如设置一个位置编码P(一个n行d列的矩阵,假设n=6,d=5),那么P就是一个有30个参数的可学习的位置编码,将句子的词向量矩阵和P对应位相加即可,那么“早”的词向量加上位置信息后就是(P11+0.11,P12+0.93,...)。一方面这样做就限定了句子长度为某个值,超过了这个值那么P就无法处理,另一方面P的参数是学习来的,在位置信息方面可解释性比较差。

方法二:非参数化的方法

不通过参数学习的方式获得位置编码,而是采用函数或者逻辑规则来给某个位置的词赋予位置信息,可以称它为固定方法(fixed)。比如我们设定,一个在句子中位置为pos的词(这里假定位置索引从1开始),词向量长度为d,其词向量在第i个维度被赋予的位置编码是posi/100000;那么对于“早”这个词加上位置编码后就是(0.11+11/100000,0.93+1*2/100000,...) 当然,这是笔者随意构思的一个未经理论论证和试验验证的例子。

Transformer使用的位置编码

640.webp

上图公式中,pos是词在句子中的位置 **,**比如“早”的pos就是0 很多人把i当成是词向量中每个位置的索引 ,其实这是错误的,i本身没有意义,公式中是用2i和2i+1来分别代表词向量的偶数和奇数位置的维度的索引,d_model是词向量的长度,“早”的词向量的长度就是5。

从横向上看,也就是对于某个位置的编码就是sin、cos交替的形式,例如“上”这个词因为在第二个位置处,所以位置编码为:

641.webp

这种方式决定了某个位置上的词的位置编码是确定的,和具体的词和句子无关 ,这表达了词的绝对位置信息;该方法理论上不受限于句子长度;三角函数取值有界,处于[-1,1]之间,也保证了位置编码数值可控。交替使用sin、cos函数使得不同维度的位置编码有一定的正交性,也就是说不同维度上的位置编码比较独立,形成良好区分。

结合三角函数公式:

642.webp

可得:

643.webp

其中w_i是位置编码公式里pos的系数部分。所以,距离为k的两个词的特征编码,其中一个可以表示为另一个的一种线性组合形式,也就是表达出了词与词之间的相对位置信息

从纵向上看,也就是不同位置的词的同一维度的位置编码,是关于pos的函数,奇数位是cos(pos),偶数位是sin(pos)。
在公式中10000这个数值放在分母上使得函数有较小的频率即较大的周期,从而使得不同位置的词在同一特征维度下的取值尽量不会相同,来保证差异性,除非句子很长。这种差异性也随着词之间距离的增大而增大,而距离比较近的词即pos变动比较小时的差异性由于10000在分母上缩放的影响变得比较微弱。这其中也隐含了绝对位置和相对位置带来的差异。