RoPE,全称是 Rotary Position Embedding,即旋转位置编码。它的核心思想可以概括为一句话:

不用“加法”把位置塞进词向量,而是用“旋转”把位置编码进 Query 和 Key 的几何关系里。

要真正理解 RoPE,需要依次搞清楚四件事:旋转矩阵是怎么来的,m,nm,nm,n 代表什么,RoPE 如何把位置变成旋转,以及为什么旋转后的点积只依赖相对位置。


零、旋转矩阵是怎么来的

二维旋转矩阵不是凭空记出来的,它来自一个基本事实:

任意线性变换,只要知道它把基向量变到哪里,就能确定整个矩阵。

二维平面中有两个标准基向量:

e1=(10),e2=(01) e_1= \begin{pmatrix} 1\\ 0 \end{pmatrix}, \quad e_2= \begin{pmatrix} 0\\ 1 \end{pmatrix} e1=(10),e2=(01)

其中 e1e_1e1 指向 xxx 轴正方向,e2e_2e2 指向 yyy 轴正方向。

现在我们希望把整个平面逆时针旋转角度 α\alphaα

先看第一个基向量 e1e_1e1。它原本在 0∘0^\circ0 方向,旋转 α\alphaα 后,会落到单位圆上角度为 α\alphaα 的位置,因此:

Rαe1=(cos⁡αsin⁡α) R_\alpha e_1= \begin{pmatrix} \cos\alpha\\ \sin\alpha \end{pmatrix} Rαe1=(cosαsinα)

再看第二个基向量 e2e_2e2。它原本在 90∘90^\circ90,也就是 π2\frac{\pi}{2}2π 方向。逆时针旋转 α\alphaα 后,它会到达:

π2+α \frac{\pi}{2}+\alpha 2π+α

所以它的新坐标是:

Rαe2=(cos⁡(π2+α)sin⁡(π2+α))=(−sin⁡αcos⁡α) R_\alpha e_2= \begin{pmatrix} \cos(\frac{\pi}{2}+\alpha)\\ \sin(\frac{\pi}{2}+\alpha) \end{pmatrix}= \begin{pmatrix} -\sin\alpha\\ \cos\alpha \end{pmatrix} Rαe2=(cos(2π+α)sin(2π+α))=(sinαcosα)

矩阵的两列正好就是两个基向量变换后的结果,因此旋转矩阵为:

Rα=(cos⁡α−sin⁡αsin⁡αcos⁡α) R_\alpha= \begin{pmatrix} \cos\alpha & -\sin\alpha\\ \sin\alpha & \cos\alpha \end{pmatrix} Rα=(cosαsinαsinαcosα)

其中第一列表示 xxx 轴基向量旋转后去了哪里,第二列表示 yyy 轴基向量旋转后去了哪里。

对于任意二维向量:

v=(xy)=xe1+ye2 v= \begin{pmatrix} x\\ y \end{pmatrix}= xe_1+ye_2 v=(xy)=xe1+ye2

旋转后就是:

Rαv=xRαe1+yRαe2 R_\alpha v= xR_\alpha e_1+yR_\alpha e_2 Rαv=xRαe1+yRαe2

代入上面的结果:

Rαv=x(cos⁡αsin⁡α)+y(−sin⁡αcos⁡α) R_\alpha v= x \begin{pmatrix} \cos\alpha\\ \sin\alpha \end{pmatrix} + y \begin{pmatrix} -\sin\alpha\\ \cos\alpha \end{pmatrix} Rαv=x(cosαsinα)+y(sinαcosα)

所以:

Rαv=(xcos⁡α−ysin⁡αxsin⁡α+ycos⁡α) R_\alpha v= \begin{pmatrix} x\cos\alpha-y\sin\alpha\\ x\sin\alpha+y\cos\alpha \end{pmatrix} Rαv=(xcosαysinαxsinα+ycosα)

这就是二维旋转矩阵的来源。RoPE 后面用到的所有公式,本质上都建立在这个旋转矩阵之上。


一、mmmnnn 从哪里来

RoPE 中的 mmmnnn 并不神秘,它们就是 Token 在序列中的位置编号。

比如输入一句话:

“我 喜欢 吃 烤肉” \text{“我 喜欢 吃 烤肉”}  喜欢  烤肉

那么可以编号为:

我→0,喜欢→1,吃→2,烤肉→3 \text{我}\rightarrow 0,\quad \text{喜欢}\rightarrow 1,\quad \text{吃}\rightarrow 2,\quad \text{烤肉}\rightarrow 3 0,喜欢1,2,烤肉3

所以 mmmnnn 本质上就是 Token 的索引。第 mmm 个 Token 的 Query 记作 qmq_mqm,第 nnn 个 Token 的 Key 记作 knk_nkn

模型不需要额外“推理”出 mmmnnn,它们天然来自输入序列的位置。


二、RoPE 如何把位置变成旋转

RoPE 的做法不是把位置向量加到词向量上,而是根据位置编号旋转 Query 和 Key。

二维情况下,如果原始 Query 向量是:

q=(q1q2) q= \begin{pmatrix} q_1\\ q_2 \end{pmatrix} q=(q1q2)

mmm 个位置就让它旋转角度:

mθ m\theta mθ

也就是:

q~m=Rmθq \tilde q_m= R_{m\theta}q q~m=Rmθq

其中:

Rmθ=(cos⁡(mθ)−sin⁡(mθ)sin⁡(mθ)cos⁡(mθ)) R_{m\theta}= \begin{pmatrix} \cos(m\theta)&-\sin(m\theta)\\ \sin(m\theta)&\cos(m\theta) \end{pmatrix} Rmθ=(cos(mθ)sin(mθ)sin(mθ)cos(mθ))

所以:

q~m=(q1cos⁡(mθ)−q2sin⁡(mθ)q1sin⁡(mθ)+q2cos⁡(mθ)) \tilde q_m= \begin{pmatrix} q_1\cos(m\theta)-q_2\sin(m\theta)\\ q_1\sin(m\theta)+q_2\cos(m\theta) \end{pmatrix} q~m=(q1cos(mθ)q2sin(mθ)q1sin(mθ)+q2cos(mθ))

同理,对于第 nnn 个位置的 Key:

k=(k1k2) k= \begin{pmatrix} k_1\\ k_2 \end{pmatrix} k=(k1k2)

RoPE 会让它旋转角度 nθn\thetanθ

k~n=Rnθk \tilde k_n= R_{n\theta}k k~n=Rnθk

即:

k~n=(k1cos⁡(nθ)−k2sin⁡(nθ)k1sin⁡(nθ)+k2cos⁡(nθ)) \tilde k_n= \begin{pmatrix} k_1\cos(n\theta)-k_2\sin(n\theta)\\ k_1\sin(n\theta)+k_2\cos(n\theta) \end{pmatrix} k~n=(k1cos(nθ)k2sin(nθ)k1sin(nθ)+k2cos(nθ))

因此,RoPE 的本质就是:

位置编号 m⟶旋转角度 mθ \text{位置编号 }m \quad\longrightarrow\quad \text{旋转角度 }m\theta 位置编号 m旋转角度 mθ

位置不再是一个额外加进去的向量,而是变成了向量空间中的旋转角度。


三、旋转后的点积为什么只依赖相对位置

注意力分数来自 Query 和 Key 的点积。经过 RoPE 后,计算的是:

q~m⋅k~n \tilde q_m\cdot \tilde k_n q~mk~n

把上面的两个旋转向量代入:

q~m⋅k~n=(q1cos⁡mθ−q2sin⁡mθ)(k1cos⁡nθ−k2sin⁡nθ)+(q1sin⁡mθ+q2cos⁡mθ)(k1sin⁡nθ+k2cos⁡nθ) \begin{aligned} \tilde q_m\cdot \tilde k_n =& (q_1\cos m\theta-q_2\sin m\theta) (k_1\cos n\theta-k_2\sin n\theta)\\ &+ (q_1\sin m\theta+q_2\cos m\theta) (k_1\sin n\theta+k_2\cos n\theta) \end{aligned} q~mk~n=(q1cosmθq2sinmθ)(k1cosnθk2sinnθ)+(q1sinmθ+q2cosmθ)(k1sinnθ+k2cosnθ)

展开并整理后得到:

q~m⋅k~n=(q1k1+q2k2)cos⁡((m−n)θ)+(q1k2−q2k1)sin⁡((m−n)θ) \tilde q_m\cdot \tilde k_n= (q_1k_1+q_2k_2)\cos((m-n)\theta) + (q_1k_2-q_2k_1)\sin((m-n)\theta) q~mk~n=(q1k1+q2k2)cos((mn)θ)+(q1k2q2k1)sin((mn)θ)

这里用到了两个三角恒等式:

cos⁡Acos⁡B+sin⁡Asin⁡B=cos⁡(A−B) \cos A\cos B+\sin A\sin B=\cos(A-B) cosAcosB+sinAsinB=cos(AB)

sin⁡Acos⁡B−cos⁡Asin⁡B=sin⁡(A−B) \sin A\cos B-\cos A\sin B=\sin(A-B) sinAcosBcosAsinB=sin(AB)

这一步就是 RoPE 的关键。

最终公式中不再单独出现 mmm,也不再单独出现 nnn,只剩下:

m−n m-n mn

也就是说,RoPE 影响注意力分数的不是“这个词在第几个位置”,而是“两个词相隔多远”。

比如两个词分别在位置 111333,相对距离是:

3−1=2 3-1=2 31=2

如果整句话整体平移到位置 100011000110001100031000310003,相对距离仍然是:

10003−10001=2 10003-10001=2 1000310001=2

RoPE 会让这两种情况对应同一个相对旋转角:

(m−n)θ (m-n)\theta (mn)θ

所以它天然具有一种平移不变性:整体位置变了,但相对距离不变,注意力中的位置关系也保持一致。


四、为什么一个数字 mmm 能表示位置

这里还有一个容易卡住的问题:mmm 只是一个整数,为什么它能变成有效的位置特征?

如果只在一个二维平面上旋转,确实会有重复问题。

假设:

θ=10∘ \theta=10^\circ θ=10

那么:

m=1⇒10∘ m=1\Rightarrow 10^\circ m=110

而:

m=37⇒370∘=10∘ m=37\Rightarrow 370^\circ=10^\circ m=37370=10

111 个位置和第 373737 个位置在这个二维平面上重合了。也就是说,单个旋转平面无法唯一表示长序列位置。

真实大模型的做法是使用 多频旋转

假设一个 attention head 的维度是 128128128,RoPE 会把它拆成 646464 组二维平面:

(q1,q2), (q3,q4), …, (q127,q128) (q_1,q_2),\ (q_3,q_4),\ \dots,\ (q_{127},q_{128}) (q1,q2), (q3,q4), , (q127,q128)

每一组二维平面都有自己的旋转频率:

θ1,θ2,…,θ64 \theta_1,\theta_2,\dots,\theta_{64} θ1,θ2,,θ64

iii 组的旋转角度是:

mθi m\theta_i mθi

通常这些频率按指数规律衰减,例如:

θi=10000−2i/d \theta_i=10000^{-2i/d} θi=100002i/d

其中 ddd 是 head dimension。

直观理解,RoPE 给每个位置安排了一组“多频时钟”。

高频维度转得快,适合捕捉相邻 Token 的细粒度顺序;低频维度转得慢,适合区分长距离位置。即使某个高频平面转了一圈重合了,其他中低频平面通常还没有重合。

所以位置 mmm 最终不是由一个角度表示,而是由一串角度组合表示:

(mθ1, mθ2, …, mθ64) (m\theta_1,\ m\theta_2,\ \dots,\ m\theta_{64}) (mθ1, mθ2, , mθ64)

这串多频角度就是位置 mmm 的高维旋转指纹。

更准确地说,它不是保证在无限长度上永不重复,而是在模型设计的上下文长度和数值精度范围内,提供了足够丰富、足够可区分的位置表示。


五、RoPE 和绝对位置编码的本质区别

传统绝对位置编码,例如 BERT、GPT-2 一类方法,通常是把位置向量直接加到词向量中。

设第 mmm 个 Token 的词向量是 xmx_mxm,位置向量是 pmp_mpm,则输入表示为:

hm=xm+pm h_m=x_m+p_m hm=xm+pm

然后生成 Query 和 Key:

qm=(xm+pm)Wq q_m=(x_m+p_m)W_q qm=(xm+pm)Wq

kn=(xn+pn)Wk k_n=(x_n+p_n)W_k kn=(xn+pn)Wk

注意力分数为:
Scoreabs=qmknT \text{Score}_{abs} = q_m k_n^\mathrm{T} Scoreabs=qmknT

展开后:
Scoreabs=(xm+pm)WqWkT(xn+pn)T \text{Score}_{abs} = (x_m+p_m) W_q W_k^\mathrm{T} (x_n+p_n)^\mathrm{T} Scoreabs=(xm+pm)WqWkT(xn+pn)T

其中会出现一个纯绝对位置项:
pmWqWkTpnT p_m W_q W_k^\mathrm{T} p_n^\mathrm{T} pmWqWkTpnT

其中会出现一个纯绝对位置项:

pmWqWkTpnT p_mW_qW_k^Tp_n^T pmWqWkTpnT

这个项直接依赖 pmp_mpmpnp_npn

因此,位置 111 和位置 333 的关系由 p1,p3p_1,p_3p1,p3 决定;位置 100011000110001 和位置 100031000310003 的关系由 p10001,p10003p_{10001},p_{10003}p10001,p10003 决定。即使它们的相对距离都等于 222,绝对位置编码也不能天然保证这两种位置关系完全一致。

RoPE 则不同。

RoPE 不把位置作为额外向量加进去,而是把位置变成旋转角度:

m→mθi m\rightarrow m\theta_i mmθi

然后通过旋转后的 Query 和 Key 做点积,使绝对位置 m,nm,nm,n 在公式中自然合并成相对位置:

m−n m-n mn

所以 RoPE 不是简单地告诉模型“这个词在第几个位置”,而是让模型在注意力分数中直接感知“两个词之间相隔多远”。


总结

RoPE 的逻辑可以串成一条完整链路:

首先,二维旋转矩阵来自标准基向量的旋转结果:

Rα=(cos⁡α−sin⁡αsin⁡αcos⁡α) R_\alpha= \begin{pmatrix} \cos\alpha&-\sin\alpha\\ \sin\alpha&\cos\alpha \end{pmatrix} Rα=(cosαsinαsinαcosα)

然后,RoPE 把 Token 的位置编号 mmm 映射成旋转角度 mθm\thetamθ

m→mθ m\rightarrow m\theta mmθ

接着,它对第 mmm 个位置的 Query 和第 nnn 个位置的 Key 分别旋转:

q~m=Rmθq,k~n=Rnθk \tilde q_m=R_{m\theta}q, \quad \tilde k_n=R_{n\theta}k q~m=Rmθq,k~n=Rnθk

最后,两者点积后,绝对位置 m,nm,nm,n 消失,只留下相对距离:

m−n m-n mn

因此,RoPE 的本质是:

用旋转矩阵把位置编号变成几何角度,再通过 Query 和 Key 的点积,把绝对位置自然转化为相对位置。

相比绝对位置编码,RoPE 更符合语言中的结构规律:很多时候,真正重要的不是一个词出现在第几个座位,而是它和另一个词之间隔了多远。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐