看完肯定懂,可能会更新
一看位置编码公式,感觉很懵逼
懵逼四点:(或者你还有其他不懂的点)
1、为什么使用正弦余弦公式?不可以使用其他公式?
2、为什么奇数位置使用余弦,偶数位置使用正弦?
3、为什么不单独使用正弦,或者单独使用余弦?
4、正弦余弦公式到底是怎么影响原词向量的?怎么进行计算的?
如果原词向量为下图,你打算怎么给词向量叠加上位置编码呢?(假设词向量只有5位,实际上gpt是几万位)
我来告诉你几种脑子突然出现的想法。
1、给每个词向量的每一个位置都加上位置号码,例如have = [0.1,0.4,0.8 …] …day[4.8, 4.1, 4.4, 4.6, 4.6],发现一个问题,当我们的句子很长例如500个字的时候,后面词语位置编码会很大,本来词向量大部分都是0-1的数字,你这么大,位置编码会严重覆盖掉原有的词向量语义,词向量会丢失原有的语义。
2、等比例缩小行不行,假设100个词语,第1个词汇叠加0,第2个词汇叠加0.01,第3个词汇叠加0.02,第100个词汇叠加0.99,这样确实是可以的,没有问题,但是在实际训练中词与词之间的距离是0.01,太小了,位置信息太弱了,实际训练效果不好也不行。
。。。。或者你还想到其他的办法
总结:太强不行,太弱也不行
先看三角函数为什么可以,我们看下三角函数的图像
先提一个点:位置信息肯定是唯一的,或者是在很长的文字当中,起码重复度不会太高,x轴代表位置,y轴代表叠加上去的值
假设只使用一个三角函数sin,我们将第2和第14两个位置输入到sin,他们的值很像,在神经网络的训练中,很容易把第2个位置和第14个位置当成是一个位置,不满足我们上面说到的要求位置唯一性。
sin2
sin14
怎么将sin变得具有唯一性呢,把sin函数的波长拉长,拉长到10000,这就是公式里面的10000那个数字,大家可以看一看公式,下图我拉长了4,假设拉长到10000,然后将位置x=0,1,2,3…n对应sin(x/10000)叠加到词向量上面,就保证了词与词之间的位置编码具有唯一性。虽然唯一性是保证了,但是词与词之间的位置编码间隔还是太小,不行不行。
所以,重点来了,原公式在每个词向量的倒数第1维,使用的是波长为10000的sin公式,在每个词向量的倒数第2维,使用的是波长为5000的sin公式,维度越靠前,使用的波长越短。单看最后一维,词与词之间的距离非常小,间隔可能在0.00001之间,但是可以保证唯一性。越到前面波长越短,倒数第2个维度,词与词之间间隔可能在0.0001之间,依次类推,间隔可以看作 [0.5, 0.1, 0.05, 0.001 …0.0001,0.00001],维度越靠前,不同词语的同等维度数字差距越大,这就能明显的区分出词与词之间的间隔,同时靠后的维度又保证了位置的唯一性。那为什么又要使用cos呢,我的理解是主要还是为了提取更多的位置特征,增加一点复杂性,让位置编码拥有更多的位置特征。
看个例子,不同维度使用的是不同波长的三角函数
总结:
所以我们设计位置编码必须遵守三个规则
1、位置信息不可比语义信息要强势。
2、位置信息必须有界,防止越到后面位置信息太大覆盖语义信息。
3、文字太长的情况下,相邻字之前的位置信息也不会太弱势。
下图借助了一个博主的图: