transformer的Position encoding的总结

transformer的Position encoding的总结

前言
rnn中,建模是有序的,位置信息天然就学习了,但transformer中,由于self-attention的计算方式,导致位置信息丢失,需要补充学习。
在如何补充上,大体有两种方法。
第一种,embeding,大体思路是给定初始值,然后跟着学习,具体参看文章《Convolutional Sequence to Sequence Learning》。
第二种,encoding,位置信息是直接靠公式算出来,也是这篇笔记重点。


版本一 pos=encoding

前三个版本可以参考这个回答,说的很详细——zhihu.com/question/3476

pos直接作为编码,1,2,3..n,这样的问题很明显,没有上界。过大的位置embeding,跟词embeding相加,很容易导致词向量本身含义的丢失。
所以,我们期望位置向量值不要太大,最好在限定在一个区间内。

版本二 pos/sentense_len——pos做归一


如何把值限定在一个区间内,归一即可,这样词向量的区间就变成[0,1]且具有可比性了,但是问题来了。在长文本和短文本的的情况下,同样是差两个字,数值差却不同。
所以,我们有没有一个方法,保证值域固定,且不同长度文本,相差相同字数,差相同值。


版本三 Sin(pos/x)——周期性函数


Sin的值域[-1,1],且我们可以看到差两个字,什么长度的文本,差值都是相同的。
问题又来了,x取值大,则波长大,导致相邻位置的差值变小。x取值过小,则对于长文本来说,很容易就走了几个波峰,导致不同距离,但差值相同。

所以,如何取合适的x是一个很关键的问题。

版本四 周期性函数增加多样性


transformer为了解决这个问题,人工增加了多样性。不同维度不同波长,且sin,cos轮着来。


从数学上来看,PE(pos+k)和PE(pos),在给定k的情况下,是线形关系。
由sin,cos的和角公式
Sin(pos + k) = sin(pos)cos(k) + sin(k)cos(pos)
Cos(pos + k) = cos(pos)cos(k) - sin(k)sin(pos)
即可推得

但这样仍旧有一个核心的问题,相对位置是线形关系,但是位置的方向信息其实是丢失的。

以及,这种做法看起来并没有特别强的数学理论依据,更多的是凭经验拍的。(所以,bert最后采用的是position embeding,扔海量的语料让model来学习看来效果也不差)


版本五 加上方向信息


参看paper——TENER: Adapting Transformer Encoder for Named Entity Recognition
推导公式如下(详情看paper)


如上公式可知,transformer的encoding方式是天然丢失方向信息的。解决方案如下。

核心公式在于

原始的self-attention是只有Qt*Kj,这里把位置信息也跟Qt相乘了。且Rt-j的设定方式也决定它能反映出位置信息。
假设t=5,j分别为0,10,则t-j分别为5和-5。已知sin(-x)=-sin(x),cos(-x)=cos(x)。很明显,我们可以发现对于0和10,值是互为正反,通过这种方式把方向信息就学到了。


总结——在看的过程中,我一直在思考的是,在大样本下,这种encoding是否真的有意义,切换成poistion embeding一起学效果估计不一定差。因为这种encoding带了太多的先验知识且没有跟着样本学习。后期有时间实验会给个结论。






编辑于 2019-12-03