RoPE:旋转位置编码的原理与推导

Transformer 的自注意力本身不理解顺序。给它一组 token,如果不加入位置信息,打乱顺序前后的集合在结构上没有本质区别。位置编码要解决的就是这个问题:让模型知道“谁在谁前面、相隔多远”。

但 RoPE(Rotary Position Embedding)11 Su et al., 2021 的关键不只是“加入位置信息”。它真正漂亮的地方在于:位置不以额外偏置的形式进入 Attention,而是通过旋转 query 和 key,让点积自然变成相对位置的函数。

这篇文章只抓住这一条主线:Attention 的核心分数是 𝑞𝑘,所以位置编码最理想的注入点,就是让位置改变 𝑞𝑘 的相位,并让两个相位相减。

Attention 需要什么样的位置?

自注意力的打分形式是:

𝑠𝑚,𝑛=𝑞𝑚𝑘𝑛

其中 𝑚 是 query 所在位置,𝑛 是 key 所在位置。若直接把绝对位置向量加到 token embedding 上,模型当然可以学习位置,但位置与内容被混在一起,Attention 分数未必天然关心相对距离。

更理想的目标是构造一个函数 𝑓,使位置编码后的点积满足:

𝑓(𝑞𝑚,𝑚),𝑓(𝑘𝑛,𝑛)=𝑔(𝑞𝑚,𝑘𝑛,𝑚𝑛)

也就是说,虽然每个 token 只知道自己的绝对位置 𝑚𝑛,但一旦进入 Attention 点积,绝对位置会自动合成为相对位移 𝑚𝑛

自然语言里很多关系首先是相对关系:修饰词离被修饰词多远,主谓宾的顺序如何,括号或引号在哪里闭合。绝对编号本身并不重要,重要的是 token 之间的相对结构。

RoPE 的构造就是为了满足这个式子。

旋转为什么天然产生相对位置?

先看二维向量。把 𝑞=(𝑞0,𝑞1) 看成复数:

𝑞̃=𝑞0+𝑖𝑞1

如果把它乘上 𝑒𝑖𝑚𝜃,几何意义就是旋转 𝑚𝜃

𝑓(𝑞,𝑚)=𝑞̃𝑒𝑖𝑚𝜃

对应的二维矩阵形式是:

𝑅𝑚=(cos(𝑚𝜃)sin(𝑚𝜃)sin(𝑚𝜃)cos(𝑚𝜃))

关键性质来自旋转矩阵的群结构:

𝑅𝑚𝑇𝑅𝑛=𝑅𝑛𝑚

因此两个旋转后的向量点积为:

(𝑅𝑚𝑞)𝑇(𝑅𝑛𝑘)=𝑞𝑇𝑅𝑚𝑇𝑅𝑛𝑘=𝑞𝑇𝑅𝑛𝑚𝑘

位置 𝑚𝑛 没有分别留下来,只留下了它们的差。RoPE 的“绝对位置实现相对位置”并不是口号,而是这个等式直接给出的结果。

如果用复数写,同一个事实更紧凑:

Re((𝑞̃𝑒𝑖𝑚𝜃)(𝑘̃𝑒𝑖𝑛𝜃))=Re(𝑞̃𝑘̃𝑒𝑖(𝑚𝑛)𝜃)

相位从 𝑚𝜃𝑛𝜃 变成了 (𝑚𝑛)𝜃。这就是 RoPE 的内核。

从二维到高维:把向量切成许多旋转平面

真实模型中的 query/key 不是二维,而是 𝑑 维。RoPE 的处理方式很直接:把相邻维度两两配对,让每一对维度构成一个二维平面,并在每个平面上使用不同频率的旋转。

对第 𝑗 个二维平面,定义频率:

𝜃𝑗=100002𝑗𝑑,𝑗=0,1,,𝑑21

位置 𝑚 上的二维分量 (𝑥2𝑗,𝑥2𝑗+1) 被变换为:

(𝑥2𝑗𝑥2𝑗+1)=(cos(𝑚𝜃𝑗)sin(𝑚𝜃𝑗)sin(𝑚𝜃𝑗)cos(𝑚𝜃𝑗))(𝑥2𝑗𝑥2𝑗+1)

写成坐标形式:

𝑥2𝑗=𝑥2𝑗cos(𝑚𝜃𝑗)𝑥2𝑗+1sin(𝑚𝜃𝑗)𝑥2𝑗+1=𝑥2𝑗sin(𝑚𝜃𝑗)+𝑥2𝑗+1cos(𝑚𝜃𝑗)

这就是实际实现里常见的 rotate_half + sin/cos 操作。RoPE 不需要可训练的位置向量,只需要按位置预先计算不同频率下的正弦和余弦。

高频维度对短距离变化敏感,低频维度对长距离变化更稳定。这与正弦位置编码的频率设计同源,但 RoPE 把这些频率放进了 q/k 的旋转,而不是直接加到 embedding 上。

为什么要对 q 和 k 做,而不是对 v 做?

Attention 中的位置关系主要通过权重决定:

softmax(𝑞𝑚𝑘𝑛𝑑)

query 和 key 决定“当前位置应该看向哪里”,value 决定“看过去后读出什么内容”。RoPE 作用在 𝑞𝑘 上,就等于让注意力权重带有相对位置信息;如果把同样的位置旋转放到 𝑣 上,它改变的是被聚合的内容表示,而不是选择关系本身。

所以 RoPE 的位置不是给 token 内容贴标签,而是改变 token 之间的匹配几何:两个位置越不同,𝑞𝑘 的相对旋转越大,Attention 分数就会按相对位移发生系统性变化。

它和普通正弦位置编码差在哪里?

正弦位置编码通常是:

𝑥𝑚=𝑥𝑚+𝑝𝑚

位置向量 𝑝𝑚 被加进内容向量。这样做简单,也能让模型知道绝对位置;但 Attention 分数展开后会混合出多种项:

(𝑥𝑚+𝑝𝑚)(𝑥𝑛+𝑝𝑛)=𝑥𝑚𝑥𝑛+𝑥𝑚𝑝𝑛+𝑝𝑚𝑥𝑛+𝑝𝑚𝑝𝑛

其中哪些项表示内容,哪些项表示相对位置,需要模型自己学会分辨。

RoPE 则更干净。它不把位置作为一个额外向量加进去,而是把位置变成一个正交变换:

𝑥𝑚=𝑅𝑚𝑥𝑚

于是 Attention 分数天然变成:

(𝑅𝑚𝑞)𝑇(𝑅𝑛𝑘)=𝑞𝑇𝑅𝑛𝑚𝑘

位置只通过相对旋转进入分数。这就是 RoPE 相比“加法式位置编码”的核心差别。

RoPE 为什么适合长上下文?

RoPE 本身并不等于“无限外推”。它提供的是一种可外推的函数形式:任意位置 𝑚 都能计算 cos(𝑚𝜃𝑗)sin(𝑚𝜃𝑗),不像 learned position embedding 那样只能查训练过的位置表。

但长度外推仍然会遇到问题。训练时模型只见过有限范围的相位差;推理时若位置远超训练长度,高频维度会经历许多次周期缠绕,模型看到的相位组合可能落在训练分布之外。

所以实践中的长上下文技术往往不是抛弃 RoPE,而是调整 RoPE 的频率尺度。例如位置插值、NTK-aware scaling、YaRN 等方法,本质上都在控制一个问题:让推理时的相位变化不要比训练时剧烈太多,同时尽量保留短距离分辨率。

可以把 RoPE 的长上下文扩展理解成“重新标定位置到相位的映射”。困难不在于算不出更长位置的 sin/cos,而在于模型是否理解那些新的相位范围。

一个实现层面的细节:旋转不改变范数

旋转矩阵是正交矩阵,因此:

𝑅𝑚𝑥=𝑥

这意味着 RoPE 不会因为位置变大而直接放大或缩小向量范数。它改变的是方向,也就是 query/key 的相对角度。这个性质对训练稳定性很重要:位置信息被注入进几何关系,而不是通过数值尺度强行压过内容表示。

当然,旋转不改变范数并不意味着 Attention 分数不变。因为分数看的是两个向量之间的相对方向:

(𝑅𝑚𝑞)𝑇(𝑅𝑛𝑘)

𝑚𝑛 改变时,相对旋转改变,点积也随之改变。

RoPE 的局限

RoPE 很优雅,但它不是所有位置问题的终点。

这些限制并不削弱 RoPE 的价值,反而说明它的本质:RoPE 是一种把位置嵌入到内积几何里的方式,而不是一个自动解决所有长度泛化问题的魔法常数。

总结

RoPE 的核心可以压缩成一个等式:

(𝑅𝑚𝑞)𝑇(𝑅𝑛𝑘)=𝑞𝑇𝑅𝑛𝑚𝑘

它利用旋转矩阵的性质,把 query 和 key 的绝对位置 𝑚,𝑛 转换成 Attention 分数里的相对位移 𝑚𝑛。这就是“用绝对位置编码实现相对位置效果”的精确含义。

从实现上看,RoPE 只是把 q/k 的相邻维度两两配对,并按不同频率旋转;从原理上看,它是在改变 Attention 的匹配几何,让 token 之间的关系带上相对相位差。

如果只记一句话,可以记这个:RoPE 不是给 token 加位置标签,而是让 q 和 k 在位置决定的坐标系里相遇;它们相遇时,绝对位置自动抵消,只留下相对距离。