从正余弦位置编码到 RoPE
其实对位置编码的理解一直处在一个比较感性的位置,比如我大概知道正余弦位置编码和 RoPE 的区别,但是当询问一些细节的时候就不行,比如手撕位置编码。因此今天就再系统的梳理一下吧。
直观理解标准的正余弦位置编码
对于标准的正余弦位置编码,公式如下:
乍一看其实涉及到很多变量,这个时候我们最好还是从感性理解入手。pos
其实就是我们的 Token 位置索引,然后
然后我们加上一个维度,第二个维度,从 Token 维度看过去也是一个周期函数,只不过这次换成了 余弦函数,但是频率和第一个维度是相同的。
然后我们加上第三个维度,这次又回到正弦函数,但是频率更慢了一些…
相当于:低纬度 Token 捕获的是相邻 Token 之间的细微的位置变化(快节奏),而高纬度 Token 捕获的是长距离的宏观的位置关系(慢节奏)。
为什么要正余弦交叉?
但是这就引出了一个问题:为什么要正余弦交叉呢?
要知道标注的正余弦位置编码是加在 Embedding 上的,当计算位置
可以看到,这里的公式是可以解析成三部分:
- 语义-语义
- 语义-位置
- 位置-位置
受限语义-语义比较好理解,语义-位置网上也有人解释,但是比较牵强,我感觉更像噪声。然后就是最重要的位置-位置,用来确定相对距离。
那么我们现在关注一下下面这个公式,这个如何计算呢?
我们取一对相邻的维度,比如第 0 维度和第 1 维度。
- 位置
的向量:维 度 维 度 - 位置
的向量:维 度 维 度
我们要计算相似度点积,也就是:
可以看到,点积结果直接反应了相对距离 k。
存在哪些问题?
既然加法这么好,为什么现在的 RoPE 又回到乘法旋转了?
注意看注意力得分公式:
里面存在大量单独的位置编码
注意看在低纬度里,比如
看到了吗,虽然低纬度的编码在重复,但是加上高维,模型还是会遇到未见过的位置向量。
RoPE 如何解决?
RoPE 并不是直接作用在 Embedding 层,而是作用在
- Token 先转换成语义向量语义向量
- 经过
矩阵投影,得到原始的 。 - 旋转操作:
- 对
进行旋转操作: - 对
进行旋转操作: 保持不变: 向量直接进入下一步。
- 对
- 使用旋转后的
和 计算点积得分。