手推 ROPE 的核心公式

第一步:设定初始变量(准备画布)

假设我们有两个词,分别位于序列的第 mmm 个位置和第 nnn 个位置。

  • 位于位置 mmm 的词,它的 Query 向量是一个二维特征:q=(q1q2)\mathbf{q} = \begin{pmatrix} q_1 \\ q_2 \end{pmatrix}q=(q1q2)
  • 位于位置 nnn 的词,它的 Key 向量也是一个二维特征:k=(k1k2)\mathbf{k} = \begin{pmatrix} k_1 \\ k_2 \end{pmatrix}k=(k1k2)

RoPE 规定,针对位置 mmm,我们需要旋转的角度是 mθm\thetamθ;针对位置 nnn,旋转角度是 nθn\thetanθ。(θ\thetaθ 是预设的常数基频)。

对应的二维旋转矩阵为:
R(mθ)=(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}R(mθ)=(cos(mθ)sin(mθ)sin(mθ)cos(mθ))


第二步:分别施加旋转位置编码

现在,我们把绝对位置 mmmnnn 分别“注入”到 q\mathbf{q}qk\mathbf{k}k 中。在纸上写下这两组矩阵乘法:

1. 带有位置 mmm 的 Query 向量(记为 q~m\mathbf{\tilde{q}}_mq~m):
q~m=R(mθ)q=(cos⁡(mθ)−sin⁡(mθ)sin⁡(mθ)cos⁡(mθ))(q1q2)=(q1cos⁡(mθ)−q2sin⁡(mθ)q1sin⁡(mθ)+q2cos⁡(mθ))\mathbf{\tilde{q}}_m = R(m\theta) \mathbf{q} = \begin{pmatrix} \cos(m\theta) & -\sin(m\theta) \\ \sin(m\theta) & \cos(m\theta) \end{pmatrix} \begin{pmatrix} q_1 \\ q_2 \end{pmatrix} = \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=R(mθ)q=(cos(mθ)sin(mθ)sin(mθ)cos(mθ))(q1q2)=(q1cos(mθ)q2sin(mθ)q1sin(mθ)+q2cos(mθ))

2. 带有位置 nnn 的 Key 向量(记为 k~n\mathbf{\tilde{k}}_nk~n):
k~n=R(nθ)k=(cos⁡(nθ)−sin⁡(nθ)sin⁡(nθ)cos⁡(nθ))(k1k2)=(k1cos⁡(nθ)−k2sin⁡(nθ)k1sin⁡(nθ)+k2cos⁡(nθ))\mathbf{\tilde{k}}_n = R(n\theta) \mathbf{k} = \begin{pmatrix} \cos(n\theta) & -\sin(n\theta) \\ \sin(n\theta) & \cos(n\theta) \end{pmatrix} \begin{pmatrix} k_1 \\ k_2 \end{pmatrix} = \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=R(nθ)k=(cos(nθ)sin(nθ)sin(nθ)cos(nθ))(k1k2)=(k1cos(nθ)k2sin(nθ)k1sin(nθ)+k2cos(nθ))

手推提示: 此时,q~m\mathbf{\tilde{q}}_mq~mk~n\mathbf{\tilde{k}}_nk~n 都只包含了自己的绝对位置信息。它们对彼此毫无感知。


第三步:计算注意力得分(核心多项式展开)

在 Transformer 的注意力机制中,我们要计算这两个向量的点积(内积):q~m⋅k~n\mathbf{\tilde{q}}_m \cdot \mathbf{\tilde{k}}_nq~mk~n
二维向量的点积就是 “第一行乘第一行” 加上 “第二行乘第二行”

为了书写方便,我们令 α=mθ\alpha = m\thetaα=mθβ=nθ\beta = n\thetaβ=nθ

第一项乘积(横坐标相乘):
(q1cos⁡α−q2sin⁡α)(k1cos⁡β−k2sin⁡β)(q_1\cos\alpha - q_2\sin\alpha)(k_1\cos\beta - k_2\sin\beta)(q1cosαq2sinα)(k1cosβk2sinβ)
展开后得到:
q1k1cos⁡αcos⁡β−q1k2cos⁡αsin⁡β−q2k1sin⁡αcos⁡β+q2k2sin⁡αsin⁡β— (式 A)q_1k_1\cos\alpha\cos\beta - q_1k_2\cos\alpha\sin\beta - q_2k_1\sin\alpha\cos\beta + q_2k_2\sin\alpha\sin\beta \quad \text{--- (式 A)}q1k1cosαcosβq1k2cosαsinβq2k1sinαcosβ+q2k2sinαsinβ— ( A)

第二项乘积(纵坐标相乘):
(q1sin⁡α+q2cos⁡α)(k1sin⁡β+k2cos⁡β)(q_1\sin\alpha + q_2\cos\alpha)(k_1\sin\beta + k_2\cos\beta)(q1sinα+q2cosα)(k1sinβ+k2cosβ)
展开后得到:
q1k1sin⁡αsin⁡β+q1k2sin⁡αcos⁡β+q2k1cos⁡αsin⁡β+q2k2cos⁡αcos⁡β— (式 B)q_1k_1\sin\alpha\sin\beta + q_1k_2\sin\alpha\cos\beta + q_2k_1\cos\alpha\sin\beta + q_2k_2\cos\alpha\cos\beta \quad \text{--- (式 B)}q1k1sinαsinβ+q1k2sinαcosβ+q2k1cosαsinβ+q2k2cosαcosβ— ( B)


第四步:合并同类项与三角恒等式(见证奇迹)

现在,把 (式 A) + (式 B),并将含有相同 qqqkkk 组合的项合并在一起。你会在纸上看到一个极其对称的结构:

1. 提取 q1k1q_1k_1q1k1 的项:
q1k1(cos⁡αcos⁡β+sin⁡αsin⁡β)q_1k_1(\cos\alpha\cos\beta + \sin\alpha\sin\beta)q1k1(cosαcosβ+sinαsinβ)
根据初中学的差角余弦公式,括号里正好是 cos⁡(α−β)\cos(\alpha - \beta)cos(αβ)
所以这一项等于:q1k1cos⁡(α−β)q_1k_1\cos(\alpha - \beta)q1k1cos(αβ)

2. 提取 q2k2q_2k_2q2k2 的项:
q2k2(sin⁡αsin⁡β+cos⁡αcos⁡β)q_2k_2(\sin\alpha\sin\beta + \cos\alpha\cos\beta)q2k2(sinαsinβ+cosαcosβ)
同样,它等于:q2k2cos⁡(α−β)q_2k_2\cos(\alpha - \beta)q2k2cos(αβ)

3. 提取 q1k2q_1k_2q1k2 的项:
q1k2(sin⁡αcos⁡β−cos⁡αsin⁡β)q_1k_2(\sin\alpha\cos\beta - \cos\alpha\sin\beta)q1k2(sinαcosβcosαsinβ)
根据差角正弦公式,括号里正好是 sin⁡(α−β)\sin(\alpha - \beta)sin(αβ)
所以这一项等于:q1k2sin⁡(α−β)q_1k_2\sin(\alpha - \beta)q1k2sin(αβ)

4. 提取 q2k1q_2k_1q2k1 的项:
q2k1(cos⁡αsin⁡β−sin⁡αcos⁡β)q_2k_1(\cos\alpha\sin\beta - \sin\alpha\cos\beta)q2k1(cosαsinβsinαcosβ)
注意这里的符号,提取一个负号出来变成 −(sin⁡αcos⁡β−cos⁡αsin⁡β)-(\sin\alpha\cos\beta - \cos\alpha\sin\beta)(sinαcosβcosαsinβ),正好是 −sin⁡(α−β)-\sin(\alpha - \beta)sin(αβ)
所以这一项等于:−q2k1sin⁡(α−β)-q_2k_1\sin(\alpha - \beta)q2k1sin(αβ)


第五步:得出最终结论

把上面四项全部加起来:
q~m⋅k~n=(q1k1+q2k2)cos⁡(α−β)+(q1k2−q2k1)sin⁡(α−β)\mathbf{\tilde{q}}_m \cdot \mathbf{\tilde{k}}_n = (q_1k_1 + q_2k_2)\cos(\alpha - \beta) + (q_1k_2 - q_2k_1)\sin(\alpha - \beta)q~mk~n=(q1k1+q2k2)cos(αβ)+(q1k2q2k1)sin(αβ)

此时,把我们刚才简写的 α=mθ\alpha = m\thetaα=mθβ=nθ\beta = n\thetaβ=nθ 代回去:
α−β=mθ−nθ=(m−n)θ\alpha - \beta = m\theta - n\theta = (m - n)\thetaαβ=mθnθ=(mn)θ

最终的数学展开项定格为:
q~m⋅k~n=(q1k1+q2k2)cos⁡((m−n)θ)+(q1k2−q2k1)sin⁡((m−n)θ)\mathbf{\tilde{q}}_m \cdot \mathbf{\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)θ)

为什么说这是“绝妙之处”?

当你推导到最后一步时,你会发现一个震撼的事实:
等式的右边,绝对位置 mmmnnn 彻底消失了! 整个算式只受 (m−n)(m - n)(mn) 这一个变量的影响。

这意味着:
无论你的 Query 在第 10 个位置,Key 在第 15 个位置 (10−15=−510-15 = -51015=5);
还是你的 Query 在第 1000 个位置,Key 在第 1005 个位置 (1000−1005=−51000-1005 = -510001005=5);
只要这两个 Token 的相对距离相同,它们在注意力机制里计算出的关于位置的得分加成,就是完全一样的!

这就是所谓的平移不变性(Translation Invariance)。模型不需要刻意去学习长序列中每一个绝对位置的含义,它只需要关注 Token 之间的相对远近,这让模型处理超长上下文(Long Context)的泛化能力得到了前所未有的提升。

在刚才的推导中,我们把一个 2D 向量当作了一个完整的特征。但在真实的,例如 3072 维(或者切分后的 768 维、1152 维)张量中,RoPE 绝对不是去构造一个 3072×30723072 \times 30723072×3072 的巨型旋转矩阵来进行高维空间旋转。

它的工程实现核心秘诀就八个字:两两分组,多频旋转

为了让你彻底看透这个机制,我们直接拿 CogVideoX 切分出来的**时间维度特征块 ztz_tzt(768 维)**来开刀。假设当前这个 Token 位于第 2 帧(即绝对位置 m=2m = 2m=2)。

第一步:将高维特征“两两分组”

我们手里有一个 768 维的特征向量:
zt=[x1,x2,x3,x4,…,x767,x768]z_t = [x_1, x_2, x_3, x_4, \dots, x_{767}, x_{768}]zt=[x1,x2,x3,x4,,x767,x768]

RoPE 的第一步,是把这 768 个标量按顺序切分成 384 对 2D 向量。你可以把它们想象成 384 个独立的小平面:

  • 第 0 组:(x1,x2)(x_1, x_2)(x1,x2)
  • 第 1 组:(x3,x4)(x_3, x_4)(x3,x4)
  • 第 383 组:(x767,x768)(x_{767}, x_{768})(x767,x768)

第二步:引入“多频率”基座(核心灵魂)

这是高维 RoPE 最精妙的地方。如果我们让这 384 组 2D 向量都按照同一个基频 θ\thetaθ 去旋转,那它们携带的位置信息就完全冗余了。

因此,RoPE 为每一组 2D 向量分配了不同大小的旋转频率 θi\theta_iθi
公式通常定义为(以 LLaMA 等主流实现为例):
θi=10000−2id\theta_i = 10000^{-\frac{2i}{d}}θi=10000d2i
其中,d=768d = 768d=768(特征维度),iii 是分组的索引(从 000383383383)。

  • i=0i = 0i=0 时(第 0 组)θ0=100000=1\theta_0 = 10000^0 = 1θ0=100000=1。频率最高,旋转步子迈得最大。
  • i=383i = 383i=383 时(最后一组)θ383≈10000−1=0.0001\theta_{383} \approx 10000^{-1} = 0.0001θ383100001=0.0001。频率极低,位置怎么变它都几乎不动。

直觉理解: 这就像一个包含 384 根指针的超级时钟。第一组是秒针(转得飞快),中间是分针,最后一组是走得极慢的世纪针。哪怕是一万年后的绝对位置,这个超级时钟上的 384 根指针的组合状态也是全球唯一的

第三步:在 384 个 2D 平面上同时执行旋转

现在,绝对位置 m=2m = 2m=2 来了。我们要对这 384 组向量同时进行 2D 旋转。

对于第 0 组 (x1,x2)(x_1, x_2)(x1,x2)
旋转角度是 m⋅θ0=2×1=2m \cdot \theta_0 = 2 \times 1 = 2mθ0=2×1=2 弧度。
(x1′x2′)=(cos⁡(2)−sin⁡(2)sin⁡(2)cos⁡(2))(x1x2)\begin{pmatrix} x_1' \\ x_2' \end{pmatrix} = \begin{pmatrix} \cos(2) & -\sin(2) \\ \sin(2) & \cos(2) \end{pmatrix} \begin{pmatrix} x_1 \\ x_2 \end{pmatrix}(x1x2)=(cos(2)sin(2)sin(2)cos(2))(x1x2)

对于第 1 组 (x3,x4)(x_3, x_4)(x3,x4)
假设 θ1=0.976\theta_1 = 0.976θ1=0.976,旋转角度是 m⋅θ1=2×0.976=1.952m \cdot \theta_1 = 2 \times 0.976 = 1.952mθ1=2×0.976=1.952 弧度。
(x3′x4′)=(cos⁡(1.952)−sin⁡(1.952)sin⁡(1.952)cos⁡(1.952))(x3x4)\begin{pmatrix} x_3' \\ x_4' \end{pmatrix} = \begin{pmatrix} \cos(1.952) & -\sin(1.952) \\ \sin(1.952) & \cos(1.952) \end{pmatrix} \begin{pmatrix} x_3 \\ x_4 \end{pmatrix}(x3x4)=(cos(1.952)sin(1.952)sin(1.952)cos(1.952))(x3x4)

…… 以此类推,直到第 383 组。

第四步:重新拼接为 768 维

384 组 2D 旋转全部做完后,把它们重新按顺序拼成一根长向量:
zt′=[x1′,x2′,x3′,x4′,…,x767′,x768′]z_t' = [x_1', x_2', x_3', x_4', \dots, x_{767}', x_{768}']zt=[x1,x2,x3,x4,,x767,x768]

此时,这个 768 维的 zt′z_t'zt 就完美注入了“第 2 帧”的时间位置信息。

Logo

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

更多推荐