Bert模型是自然语言处理方面里程碑式的进步,其核心是transformer层, 而transformer采用自注意力编码器摒弃了循环网络,循环网络天生的顺序信息在自注意力编码器中没有了,而语言往往是顺序不同意思相差很大。所以transformer的作者设计了一种三角函数位置编码方式,为每个不同位置的token单独生成一个位置向量(或者位置嵌入,即position embedding,缩写为PE)。下面的公式是位置编码的公式,但是论文及网上其他文章对公式解释不是很清楚,所以我在此采用例子来帮助初学者理解。

transformer位置编码直接加上embedding吗 transformer 位置编码_三角函数

式中pos为token在序列中的位置号码,它的取值是0到序列最大长度max_que_length-1之间的整数。比如“[cls] 我 爱 中 华 [sep]”是6个token组成的序列,[cls]的pos值为0,“我”的pos值为1,“爱”的pos为2,“中”为3,“华”为4,'[sep]'为5 。bert base最大长度max_que_length是512,pos取值还能一直到511。当然如果序列真实长度小于最大长度时,后面的位置号没有意义,最终会被mask掉。

dmodel是位置向量的维度,与整个模型的隐藏状态维度值相同,这解释了为什么起dmodel这个名字,这个维度在bert base模型里设置为768。

i 是从0到dmodel/2-1之间的整数值,即0,1,2,...383。

2i  是指向量维度中偶数维,即第0维,第2维,第4维,直到第766维。

2i+1 是维度中奇数维,即第1维,第3维,第5维,直到第767维。

PE是一个矩阵,行数是最大的序列长度max_que_length,列数是dmodel,即它的形状为[max_que_length,dmodel]

PE(pos,2i)是PE矩阵中第pos行,第2i列的数值,是个标量。这里是在第偶数列上的值,偶数列用正玄函数计算。

PE(pos,2i+1) 是PE矩阵中第pos行,第2i+1列的数值,是个标量。这里是在第奇数列上的值,奇数列用余玄函数计算。

仍然以序列“[cls] 我 爱 中 华 [sep]”为例,现在计算序列中"我"的位置向量,这个向量有768维,我考虑前面4维的值和最后2维做为例子,其他维度则省略:

"我"在序列中位置pos的值是1,当i=0时,2i表示第0维,2i+1表示第1维,dmodel=768,为简洁,此处小数点后只取2位

PE(1,0)= sin(1/(10000)^(0/768)) = sin(1/1) = sin(1) = 0.84

PE(1,1) = cos(1/(10000)^(0/768)) = cos(1/1)=cos(1) = 0.54

再看当i=1时的第2维和第3维

PE(1,2) = sin(1/(10000^(2/768))) = sin(1/(10000^(1/384)))=sin(1/1.02)=0.83

PE(1,3) = cos(1/(10000^(2/768))) = cos(1/1.02) = 0.56

再看最后两维的情况,这时i=383:

PE(1,766) = sin(1/(10000^(766/768))) = sin(1/9763.00) = 0.00

PE(1,767) = cos(1/(10000^(766/768))) = cos(1/9763.00) = 1.00

那token"我"的位置向量大概样子是

[0.84,0.54,。。。,0.00,1.00]

再看看当位置号pos不断增大时,某一维比如第0维的值是怎么变化的。因为三角函数是关于2倍圆周率Pi的周期函数,所以把数值转为Pi的倍数

P(1,0)=sin(1)=sin(0.31Pi)

P(2,0)=sin(2)=sin(0.64Pi)

P(3,0)=sin(3)=sin(0.96Pi)

P(6,0)=sin(6)=sin(1.91Pi)

P(7,0)=sin(7)=sin(2.23Pi)=sin(0.23Pi)

P(8,0)=sin(8)=sin(2.54Pi)=sin(0.54Pi)

由此可看出,由于三角函数是周期函数,随着位置号的增加,相同维度的值有周期性变化的特点。

 

transformer为什么设计这样的编码方式来生成位置向量呢? 因为三角函数有个性质

                   sin(a+b) = sin(a) * cos(b) + cos(a) * sin(b)

                  cos(a+b) = cos(a) * cos(b) - sin(a) * sin(b)

 因此可以推导出,两个位置向量的点积是一个与他们两个位置差值(即相对位置)有关,而与绝对位置无关。这个性质使得在计算注意力权重的时候(两个向量做点积),使得相对位置对注意力发生影响,而绝对位置变化不会对注意力有任何影响,这更符合常理。

比如”我爱中华“这句话,”华“与”中“相对位置为1,华与中的相关性程度取决于相对位置值1。而如果这句话前面还有其他字符,那华和中两个字的绝对位置会变化,这个变化不会影响到中华这两个字的相关程度。

但是这里似乎有个缺陷,就是这个相对位置没有正负之分,比如"华"在"中"的后面,对于"中"字,"华"相对位置值应该是1,而"爱"在"中"的前面,相对位置仍然是1,这就没法区分到底是前面的还是后面的。

 

transformer的位置向量还有一种生成方式是可训练位置向量。即随机初始化一个向量,然后由模型自动训练出最可能的向量。transformer的作者指出这种可训练向量方式的效果与正玄余玄编码方式的效果差不多。在bert的代码中采用的是可训练向量方式。