transformer中的位置编码
一、自然语言处理中,位置信息的重要性
自然语言,本质上是一个序列数据,句子中的词语有先后顺序之分。可以从绝对位置和相对位置两个方面来说明位置信息的重要性。从绝对位置信息上讲,颠倒词语的先后顺序可能会改变整个句子的意思,例如“猫捉老鼠”和“老鼠捉猫”所表达的意思完全不同。从相对位置信息来讲,以某个词为中心,在句子中,越是靠近它的词,它们之间的关联性就越大,对它来说越重要。距离越远,可能关联性就越弱。
二、transformer为何需要位置信息
这个主要是由transformer的架构决定的。在transformer的Encoder和Decoder中,都是由多个(自注意力+全连接层)堆叠而成,然后再加上词嵌入向量作为输入。无论是词嵌入向量,还是自注意力机制,亦或者是全连接层,都是不带词语先后顺序信息的。自注意力机制摒弃了CNN和RNN的做法,它更像一个词袋,计算着词袋中各个词语间的相关性,这一点可以从自注意力机制的计算公式可以看出。再深究一些,就是自注意力机制具有置换等变性。所谓的置换等变性,就是说:假设自注意力机制的输入数据为,如果我们把输入数据重新排序,变为
(第一行和第二行对调了顺序),最终计算出的注意力分数矩阵除了矩阵中行的顺序变了外(第一行和第二行对调了顺序),其他没有变化。我们加入位置信息的目的,就是要破坏自注意力机制的位置等变性,让模型可以学到更多的知识。
三、位置编码所应该具有的性质
既然需要再输入数据中加入位置编码信息,那么什么样的位置编码可以算是一个好的位置编码呢?我们还是从其所表达的绝对位置信息和相对位置信息说起。
- 从表达绝对位置信息上来看:(1)具有唯一性:它能够唯一表达1,2,3,4...等这些位置。假设有两个序列,无论这两个序列的长度是否相同,长度相差有多大,在序列中第10个上的位置编码是一样的。某个位置上的位置编码不会随着序列的长度改变而改变。(2)具有延展性:可以表达训练数据以外的位置信息。比如说模型训练时,训练数据中序列的最大长度是100,但在实际应用中,序列长度超过了100,超出部分的位置编码也应该可以表示。(3)具有有限性:位置编码不能随着位置大小而无限增大。比如说,位置是1的地方,位置编码为1;位置是100的地方,位置编码是100...,这样就会越是靠后的位置编码越大,与词嵌入向量相加后,位置编码的权重占比将起主导地位。
- 从表达相对位置信息上来看:(1)相关性:词语间距离越近,相关性就越强,位置信息权重应该越大。随着距离的增大,前期下降较快,再远的时候下降就缓慢了。(2)一个词的含义不应该因为其所在的位置不同,其含义发生改变。例如“小明”这个词,在“我打了小明”和“小明打了我”中位置不同,但表达的意思应该是一样的。(3)相对性:两个词语的相对距离不能因为句子长度的改变而改变。比如,“我打了小明”和“我打了小明,小明哭了”这两句话,我和小明的相对距离应该是一样的。具体来说是,两个位置的关系只与相对位置有关,与序列长度无关。
四、位置编码
在transformer论文中给出的位置编码是采用三角函数计算得来的。如果让我们去想一种位置编码,通常是无法想到采用三角函数作为位置编码的。第一想法肯定是采用顺序序列编码1 2 3 4 5 6……来表示对应的位置信息。这种位置编码方式简单直观,它有什么缺点呢?
4.1 顺序序列编码
顺序序列编码一个很明显的缺点就是:在表示绝对位置信息方面,它是线性增加的,随着位置越远,位置编码越大。例如,位置为1000的编码为1000,若词嵌入向量的编码为1,那么位置编码的权重远远超过了词嵌入向量,这样模型就不能很好地学到词嵌入信息。其次,顺序序列编码很可能会遇到实际应用中的词语位置超过训练时的最大编码。因此,顺序序列编码不是一个好的位置编码。
4.2 归一化序列编码
可能有人会说,我把顺序序列编码进行归一化就可以解决上述问题了。每个序列编码都除以该句子的长度,这样就缩放至0和1之间,不会无限增大了。这样做存在的问题是:每个句子的长度是不同的,句子长度的不同会影响词语间的相对距离。例如“我和小明是好朋友”和“我和小明是好朋友,小明人很好”。第一个句子中,“我”、“小明”之间的距离是0.375-0.125=0.25,第二个句子中,“我”和“小明”之间的距离是0.214–0.07=0.207。此外,归一化后的序列编码所表达的信息有限。就像词嵌入向量,我们不会用一个数来表示某个词,而是用一个向量来表示某个词。假设位置3的位置编码归一化后变为了0.3,如果用一个向量表示时,位置编码为而每个维度的数值都一样。
4.3 二进制编码
可能有人会想到采用二进制编码的方式来改进顺序序列位置编码。例如,位置5的编码用二进制来表示就变为了0101。这样,就不会出现归一化序列编码的问题了。此外,二进制编码都是由0和1组成,解决了顺序序列编码无界的问题,并且它的维度可以和词嵌入向量维度看齐。不过,二进制编码有如下缺陷:(1)稀疏性:假设词嵌入向量的维度是512,那么二进制位置编码的维度也是512维。还是以5为例,采用512维的二进制表示后,00000...0000101,会有510维都是0。(2)离散性:二进制编码是处于离散空间的,不同位置的变化不是连续的。但神经网络的优化过程是喜欢平滑、连续的。
五、为什么采用正弦、余弦函数
作者为什么采用正弦和余弦函数来计算位置编码呢?主要有如下原因:一是这些函数的有界性,它们的值介于-1和1之间。二是可外推性,它们可以表示任意位置编码,即使在实际应用中某个位置的编码在训练中没有出现过,也能用三角函数表示。三是相对性,如果我们知道了某个位置x的位置编码,那相对距离其k的位置编码可用其x的位置编码表示。因为正弦余弦函数有如下特性:,
六、论文中的位置编码
transformer论文中,采用的位置编码公式为和
。为什么要设计成这样呢?以正弦函数为例,对公式的由来做个解析。
位置编码,与词语所处的具体位置pos相关。因此,较为简单的想法就是,然而由于sin函数具有周期性,标准sin的周期是
。因此,如果采用标准正弦函数,就会造成后面的某个词语的位置编码和前面的某个词语的位置编码重复。为此,需要将正弦函数的周期变得很大,确保前后词语的位置编码不会出现重叠。因此,可以变为
,其中x是比较大的数。
又由于位置编码的维度要和词嵌入编码的维度一致。因此,中需加入变量i,i为维度信息:
。这就要求
不能太小,太小的话,会造成后面的某个词语的位置编码和前面的某个词语的位置编码重复;太大的话,相邻位置信息变化又不明显。为此,作者取了10000的幂。我想,这也是作者经过多次尝试后选择的一个最优值。
那为什么还既要正弦又要余弦呢?可能的原因有这么几个吧:
- 1是如果单纯使用正弦或余弦函数,相邻词语之间位置信息变化不明显。毕竟正弦或余弦函数的取值范围是-1和1之间,再加上周期被拉的很长,所以相邻词语之间的位置数据变化不明显。正弦和余弦交替,可以进一步突显差异。
- 2是进一步拉大周期。交替使用正弦和余弦函数,周期又变大了2倍。
- 3是相对位置表示,
和
。正弦和余弦函数交替使用可以很容易计算出距离k的相对位置。
附:transformer的置换等变性
置换等变:如果对输入序列的元素进行置换(重新排序),那么输出序列也会以完全相同的方式进行置换。公式表示为:对于置换操作,有
。
设输入序列为 ,其中
。一个置换矩阵 P 作用于 X,得到置换后的序列 PX。
自注意力机制的计算过程:
线性投影:计算Query、Key、Value矩阵。
计算注意力分数:
现在,我们将置换操作P应用于输入X:
-
置换后的输入为
。
-
置换后的Query、Key、Value矩阵为:
因为矩阵乘法是线性的,置换矩阵 P 可以穿过线性投影。计算置换后的注意力分数矩阵:
应用softmax函数。关键点在于:softmax函数是按行进行的。置换矩阵 P 在左边相当于对行进行置换,而 在右边相当于对列进行相同的置换。对于一个方阵A,对它的行和列进行相同的置换,其每一行的元素集合是不变的,只是顺序变了。因此,softmax操作的结果是行置换的:
最后,计算置换后的自注意力输出:
(置换矩阵的性质:
)
。这完美满足了置换等变的定义。自注意力层输出的序列
只不过是原始输出 Z 经过相同的置换 P后的结果。
