Transformer升级之路:19、第二类旋转位置编码
By 苏剑林 | 2025-04-18 | 17355位读者 |持续将“Transformer升级之路”系列关注到本篇的读者,想必都已经对旋转位置编码(RoPE)有所了解。简单来说,RoPE是施加在Attention的Query($\boldsymbol{Q}$)和Key($\boldsymbol{K}$)上的旋转变换,形式上属于绝对位置编码,但结合Attention的内积(Dot-Product)特性,能够自动实现相对位置的效果。
那么,RoPE可以加在Value($\boldsymbol{V}$)上吗?看上去不可以,因为对$\boldsymbol{V}$旋转后就不是相对位置编码了。然而事情并没有那么绝对,本文就来讨论加在$\boldsymbol{V}$上RoPE,我们可以称之为“第二类旋转位置编码”。
基础回顾 #
我们将Dot-Product Attention分解为
\begin{equation}\boldsymbol{o}_i = \sum_j a_{i,j}\boldsymbol{v}_j,\qquad a_{i,j} = \frac{e^{s_{i,j}}}{\sum\limits_j e^{s_{i,j}}},\qquad s_{i,j} = \boldsymbol{q}_i^{\top}\boldsymbol{k}_j\end{equation}
简单起见,这里省去了$s_{i,j}$的缩放因子。RoPE应用在$\boldsymbol{q}_i,\boldsymbol{k}_j$上:
\begin{equation}\boldsymbol{q}_i \to \boldsymbol{\mathcal{R}}_i\boldsymbol{q}_i,\qquad \boldsymbol{k}_j \to \boldsymbol{\mathcal{R}}_j\boldsymbol{k}_j\end{equation}
这将导致Attention Logits也就是$s_{i,j}$变成
\begin{equation}s_{i,j} = (\boldsymbol{\mathcal{R}}_i\boldsymbol{q}_i)^{\top} (\boldsymbol{\mathcal{R}}_j\boldsymbol{k}_j) = \boldsymbol{q}_i^{\top}\boldsymbol{\mathcal{R}}_i^{\top}\boldsymbol{\mathcal{R}}_j\boldsymbol{k}_j=\boldsymbol{q}_i^{\top}\boldsymbol{\mathcal{R}}_{j-i}\boldsymbol{k}_j\end{equation}
也就是说$s_{i,j}$只依赖于相对位置$j-i$,从而通过绝对位置形式达到相对位置的效果。这个变换过程利用了旋转矩阵的特性$\boldsymbol{\mathcal{R}}_i^{\top}\boldsymbol{\mathcal{R}}_j=\boldsymbol{\mathcal{R}}_{j-i}$。
除了旋转矩阵外,在《Transformer升级之路:4、二维位置的旋转式位置编码》中我们证明了它的一般解是$\boldsymbol{\mathcal{R}}_i = \boldsymbol{O}^i$,其中$\boldsymbol{O}$是任意正交矩阵,上标是矩阵的幂运算。不过后来我们在《Transformer升级之路:6、旋转位置编码的完备性分析》也证明了其实一般的正交矩阵解本质上也同构于旋转矩阵解。
新的用法 #
如果将RoPE加在$\boldsymbol{v}_j$上,即$\boldsymbol{v}_j\to\boldsymbol{\mathcal{R}}_j\boldsymbol{v}_j$,那又如何呢?显然Attention的结果是
\begin{equation}\boldsymbol{o}_i = \sum_j a_{i,j} \boldsymbol{\mathcal{R}}_j\boldsymbol{v}_j\label{eq:v-rope-abs}\end{equation}
这将会导致Attention显式依赖于绝对位置$j$。如果我们只想要一种位置编码,那么也许问题不大,但如果我们是想要一种相对位置编码,那么它就不能满足我们的目的。
然而,有一个简单的技巧可以解决这个缺陷!我们可以给$\boldsymbol{o}_i$再加一次逆向的RoPE:
\begin{equation}\boldsymbol{o}_i = \boldsymbol{\mathcal{R}}_i^{\top}\left(\sum_j a_{i,j} \boldsymbol{\mathcal{R}}_j\boldsymbol{v}_j\right)=\sum_j a_{i,j} \boldsymbol{\mathcal{R}}_i^{\top}\boldsymbol{\mathcal{R}}_j\boldsymbol{v}_j=\sum_j a_{i,j} \boldsymbol{\mathcal{R}}_{j-i}\boldsymbol{v}_j\label{eq:vo-rope}\end{equation}
这样它再次变成了一个相对位置编码!而形式上同样也是两次绝对位置编码,跟已有的RoPE异曲同工,所以我们称之为“第二类旋转位置编码”,也可以更直观地称为“VO-RoPE”,因为它分别在Value和Output都加了一次RoPE,相应地,标准的RoPE我们可以称之为“QK-RoPE”。
简单实验 #
在一个1B左右的类LLAMA模型上快速做了一波实验,对比的几个设置为:
1、NoPE:完全不加位置编码;
2、QK-RoPE:标准的旋转位置编码;
3、VO-RoPE:本文新提出的第二类旋转位置编码;
4、Q/K/V/O-RoPE:单独在Q、K、V、O之一加旋转位置编码;
5、QKV-RoPE:Q、K、V都加上旋转位置编码;
6、QKVO-RoPE:Q、K、V、O都加上旋转位置编码。
注意,第4、5点都算是绝对位置编码。大致结论是:
$$\text{QK-RoPE}\approx \text{QKVO-RoPE} > \text{K-RoPE}\approx \text{VO-RoPE} > \text{QKV-RoPE} > \text{NoPE} > \text{Q/V/O-RoPE}$$
具体损失函数差异是:
\begin{array}{c|c}
\hline
& \text{Loss} \\
\hline
\text{QK-RoPE} & 2.712 \\
\text{QKVO-RoPE} & 2.719 \\
\text{K-RoPE} & 2.769 \\
\text{VO-RoPE} & 2.770 \\
\text{QKV-RoPE} & 2.783 \\
\text{NoPE} & 2.795 \\
\text{O-RoPE} & 2.841 \\
\text{Q-RoPE} & 2.851 \\
\text{V-RoPE} & 2.856 \\
\hline
\end{array}
一些思考 #
从上述结果可以看出,VO-RoPE优于NoPE,但不如QK-RoPE,而且VO-RoPE和QK-RoPE叠加并不没有增益。这样看来,VO-RoPE似乎没有提出的必要了?
在笔者看来,将RoPE的用法补充完整,回答“RoPE可以加在Value上吗”这个问题,然后实验清楚“没有什么收益”这件事,本身就很有价值。而且,从长远来看它不见得就一直没有收益,只是在我们当前主流言语模型设置下它可能体现不出什么作用。当时笔者提出RoPE时,动机也单纯是好玩而已,并没有期望它是有竞争力的位置编码(后来的事则是幸运了)。
就当前来看,VO-RoPE也有一个潜在应用场景,它跟《缓存与效果的极限拉扯:从MHA、MQA、GQA到MLA》介绍的MLA有关。我们知道,MLA在推理阶段约等于一个K、V共享的MQA:
\begin{equation}\boldsymbol{o}_i = \sum_{j=1}^i a_{i,j}\boldsymbol{c}_j,\qquad a_{i,j} = \frac{e^{s_{i,j}}}{\sum\limits_{j=1}^i e^{s_{i,j}}},\qquad s_{i,j} = \exp(\boldsymbol{q}_i^{\top}\boldsymbol{c}_j)\end{equation}
这个特性使得它的KV Cache只有一个$\boldsymbol{c}$。然而,这个重要特性与QK-RoPE并不兼容,因为一旦给Attention矩阵里边的$\boldsymbol{c}_j$加上RoPE,那么就有两种结果:
1、Value这边的$\boldsymbol{c}_j$不加RoPE,那么K、V就不完全共享了,这就导致了要不KV Cache翻倍(RoPE前后都要Cache),要不K实时注入RoPE(带来了延迟);
2、如果Value这边的$\boldsymbol{c}_j$加RoPE,倒是可以达到K、V共享的效果,但此时就不是相对位置编码了。
MLA为了解决这个问题,采用了“大部分NoPE+小部分RoPE”拼接的做法。但是,从本文的第二类旋转位置编码我们知道,只需要再给Output加一次O-RoPE就行了:
\begin{equation}\boldsymbol{o}_i = \boldsymbol{\mathcal{R}}_i^{\top}\sum_{j=1}^i a_{i,j}(\boldsymbol{\mathcal{R}}_j\boldsymbol{c}_j),\qquad a_{i,j} = \frac{e^{s_{i,j}}}{\sum\limits_{j=1}^i e^{s_{i,j}}},\qquad s_{i,j} = (\boldsymbol{\mathcal{R}}_i\boldsymbol{q}_i)^{\top} (\boldsymbol{\mathcal{R}}_j\boldsymbol{c}_j)\end{equation}
不过,这个思路还没完全走通,还无法直接用在MLA的训练形式上,只是先写出来给大家参考。
相关工作 #
事实上,VO-RoPE还巧妙地提供了一个从Attention到复线性RNN(如LRU、RetNet)的中间形式。我们从式$\eqref{eq:vo-rope}$出发,考虑Causal场景,然后取一个特殊例子$a_{i,j}=\gamma^{i-j}$,其中$0 < \gamma < 1$,那么得到
\begin{equation}\boldsymbol{o}_i = \sum_{j=1}^i \gamma^{i-j} \boldsymbol{\mathcal{R}}_{j-i}\boldsymbol{v}_j\end{equation}
我们知道旋转矩阵$\boldsymbol{\mathcal{R}}_{j-i}$用复数形式写其实就是$e^{\mathbb{I}\theta (j - i)}$的对角阵,其中$\mathbb{I}$是虚数单位(即$\mathbb{I}^2=-1$),为了区别$i,j$的$i$这里写成了$\mathbb{I}$。这样一来,上式相当于
\begin{equation}\boldsymbol{o}_i = \sum_{j=1}^i \gamma^{i-j} e^{\mathbb{I}\theta (j - i)} \boldsymbol{v}_j = \sum_{j=1}^i (\gamma e^{-\mathbb{I}\theta})^{i-j} \boldsymbol{v}_j\end{equation}
这其实就是最简单的带有复数Decay的线性RNN。从《Google新作试图“复活”RNN:RNN能否再次辉煌?》的推导来看,这种RNN在理论上比纯实数Decay的RNN更完备。
所以说,给RoPE补上VO-RoPE形式,相当于从实线性RNN到复线性RNN的一般推广,理论上能让它能力更完整,尽管这种更完整在语言模型任务上不见得有什么帮助,正如引入复数的LRU并没有比纯实数的RWKV有优势。但,理论上的完备也许隐含着某些场景的特殊价值,谁知道呢~
番外:在推特分享本文后,有一些读者反馈他们曾经尝试过VO-RoPE,包括
1、@gharik 表示他在之前曾尝试过QKVO-RoPE,并取得了一些正面的结果,他当时命名为“RoPER”,更多细节可以参考这里和这里;
2、@vinam_arora 指出他在“脑部解码任务”尝试过VO-RoPE,并且结果也是正面的,论文为《A Unified, Scalable Framework for Neural Population Decoding》。
文章小结 #
本文围绕着“RoPE可以加在V上吗”进行展开,讨论了RoPE的第二种用法。
转载到请包括本文地址:https://kexue.fm/archives/10862
更详细的转载事宜请参考:《科学空间FAQ》
如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!
如果您需要引用本文,请参考:
苏剑林. (Apr. 18, 2025). 《Transformer升级之路:19、第二类旋转位置编码 》[Blog post]. Retrieved from https://kexue.fm/archives/10862
@online{kexuefm-10862,
title={Transformer升级之路:19、第二类旋转位置编码},
author={苏剑林},
year={2025},
month={Apr},
url={\url{https://kexue.fm/archives/10862}},
}
April 18th, 2025
很巧妙的idea!但是苏老师我有一个问题:如果说,QK-RoPE将相对位置编码在attention weight中,那么VO-RoPE将相对位置编码在了$v$上,可能会导致“特征”偏移?换句话说,$i,j$如果离得更远的话,$v_j$的特征会被转动一个很大的角度?这种转动在attention上是可接受的,毕竟最终只得到$qk$相乘之后的标量的weight值,但是放到$v$上面,可能会导致特征要表达的语义改变了?
损失函数差异的结果显示QKVO-RoPE > QKV-RoPE并且VO-RoPE > V-RoPE,我的理解是:这个结果可能不只是因为加了相对位置,还有一种可能的原因是,self-attention中对角线上面的attention weight往往比其他位置的attention weight更大,然后VO-RoPE对对角线上面的$v_j$不做任何旋转偏移,那么即使对其他位置的$v_j$进行旋转并且可能导致语义“偏移”,但是因为其他位置的softmax weight很小,因此对最终的output特征不会产生太大的偏移影响。但是V-RoPE对对角线上面的$v_j$采用$j$位置的绝对位置旋转,那么这种偏移影响可能就被放大了,因此导致效果下降。也就是说,加在$v$上面的位置编码还有一种可能,会导致上述“语义偏移”的问题,并且我认为抛弃了QK-RoPE的“长程衰减”的性质。
请问您是怎么看待这个问题的呢?
位置也可能是语义的一部份,所以是否“语义偏移”还是看场景吧,自然语言这种场景对位置和顺序的依赖并不是十分苛刻,所以没有效果甚至有负面效果都是可接受的。BTW,VO-RoPE其实也有一定的远程衰减能力。
另外就是这里实验的还是跟QK-RoPE一样的固定$\theta$,说不准将$\theta$改为可训练参数会更好。总之目前我个人的实验还比较简陋,有兴趣的同学可以多尝试。比如 https://research.labml.ai/RoPER.html 之前的尝试,就表明QKVO-RoPE在某些任务上有一定的正面效果。
受教了,谢谢苏老师!
April 21st, 2025
从逻辑上来说,QK-ROPE是对query和key加入位置信息,使得attention的相关性结果带有相对位置信息,这个过程感觉很make sense。但是VO-ROPE是对attention相关性的结果来加入位置信息,从逻辑上来说怎么解释?
我来尝试回答下你的问题,对于式(5)的形式:$o_{i}=\sum_j a_{i,j} \boldsymbol{\mathcal{R}}_{j-i}\boldsymbol{v}_j$
一方面可以按照本文的方式,理解成对$v_j$和$o_i$分别进行了旋转位置编码;另一方面,还可以理解成仅对$v_j$矩阵进行了相位位置旋转位置编码, 即对$v_j$进行了$R_{j-i}$编码。
按照第二种理解方式谷歌的一篇文章中也有类似的操作《Self-Attention with Relative Position Representations》,区别是这篇论文中的$R_{j-i}$是学出来的,并且是加给$v_j$,而不是乘给$v_j$。
以前BERT的绝对位置信息就直接加在hidden state上呀,没什么稀奇的。第一篇相对位置编码的工作 https://arxiv.org/abs/1803.02155 ,所加的相对位置编码也是有hidden state部分的,只不过后来只加在attention矩阵上变成了主流,就没有人关注了。
April 21st, 2025
苏神好,我有一些关于上文实验的猜想想跟你交流请教一下~
我之前也尝试过苏神上面的这些实验,得到了类似的效果(QKVO-RoPE的效果弱于QK-RoPE)。我之前做这些实验的初衷是,我认为在RoPE-based Attention下,RoPE前的token embedding的物理意义是频谱系数,RoPE前的token embedding的物理意义时域系数。也就是说,输入进Attention的QK对应时域,V对应频域,如果我们不对V做变换而直接对其进行加权,可能对应关系不强。
但看到QKVO-RoPE效果不好之后,我又进一步分析,猜想是因为LLM中token embedding的频谱系数“不纯净”导致这样的反变换不够好。不纯净是指,token embedding的每一维并不满足RoPE的先验(亦即每一维只对应一个频率),所以这样一对正反变换操作会造成信息丢失。
于是我设计了下面的方法来验证我关于“频谱不纯净”的猜想:https://arxiv.org/abs/2412.17739,发现这个现象确实是存在的。我觉得这个做法迁移到QKVO-RoPE上同样有希望work,不知道苏神感觉如何?
欢迎作者!Fourier Position Embedding很精彩的工作,我正打算结合最近RoPE相关的一些文献,一起拜读一下,迟点我们再来交流这个问题。
但是就“每一维只对应一个频率”而言,我的理解是 https://kexue.fm/archives/9403 ,就是反对称矩阵实际上都同构于分块旋转矩阵,所以理论上RoPE的当前形式是完备的。更多细节请等我读完 Fourier Position Embedding 再来请教。
感谢苏神推荐~之前没有关注到这篇博文,我也去仔细学习一下,再来跟你请教
请问一下论文附带的代码是不是写错了fourier_sin = F. pad ( input = fourier_sin , pad =(0 , self . head_dim //2 - fourier_sin .
size ( -1) ) , mode =" constant " , value =1) 这个value 应该是0 吧?
这块应该确实是1,因为RoPE和FoPE都是要乘到Embedding上,不是加上去(另外,论文实验的代码中也使用的是1)
不好意思,发现第一段有笔误的地方,应该是:
'''
我之前也尝试过苏神上面的这些实验,得到了类似的效果(QKVO-RoPE的效果弱于QK-RoPE)。我之前做这些实验的初衷是,我认为在RoPE-based Attention下,RoPE之前的token embedding的物理意义是频谱系数,RoPE之后的token embedding的物理意义是时域系数。也就是说,输入进Attention的QK对应时域,V对应频域,如果我们不对V做变换而直接对其进行加权,可能对应关系不强。
'''
April 28th, 2025
如果 RoPE 结合 Givens rotation method 的变体,Transformer 的 performance 会不会更好?
不是很了解Givens rotation,具体怎么用?
https://algowiki-project.org/en/Givens_method
怎么用?
April 29th, 2025
mla出来之后就知道苏神一定会念念不忘。hah。没注意到公众号不更了,才发现……我说咋好久不见更新。。