RoPE(旋转位置编码):把位置信息编码进复数旋转,为什么成了主流选择

位置编码这件事,我在很长一段时间里以为它很无聊——无非是往词向量里加一个表示位置的数。直到我读完RoPE那篇论文,才发现自己连基本假设都搞错了:位置信息,在今天的Transformer里不是加进去的,是出来的。

AI technology illustration

RoPE的全名是RoFormer: Enhanced Transformer with Rotary Position Embedding,2021年由苏剑林等人提出。当时它只是众多位置编码方案中的一个。但现在回看,几乎所有主流开源大模型——LLaMA、Mistral、Qwen、Gemma——都用它来解决位置问题。为什么?这篇我来把原理拆开讲一遍。

位置不是加出来的,是转出来的

先回忆一下位置编码要解决的问题。Transformer的注意力机制是集合操作,对token的顺序天然无感。《我爱你》和《你爱我》在注意力眼里毫无区别。早期方案很直接:给每个位置分配一个向量,加到token的embedding上——这就是加性绝对位置编码,BERT、GPT-2都这么干。但用加法编码,模型只能记住绝对位置,两个位置的相对关系全靠参数硬背。

RoPE的核心思路,用一个字概括:

我一开始也想不通——为什么不用加法,偏用乘法?后来我想通了:加法留下的位置痕迹,是向量叠加后的绝对坐标,模型得自己分辨哪些是语义、哪些是位置;而旋转是一种只改变方向、不改变长度的变换,把语义和位置干脆利落地分开了。位置是一个角度,语义还在长度里。

旋转是怎么把位置写进向量的

把d维词向量拆成d/2个二维子空间。每个子空间里,向量相当于一根指针,乘一个旋转矩阵来决定指向的角度:

R(m·θ_i) = [[cos(mθ_i), sin(mθ_i)],[ -sin(mθ_i), cos(mθ_i)]]

m是token在句子中的位置,θ_i是这个子空间的旋转速度。速度和通道i有关,按论文的公式分布:θ_i = base^{-2i/d},base=10000。换句话说,不同的二维子空间转得不一样快,这样各个维度才能编码不同粒度的位置关系——近距离靠前面的子空间,远距离靠后面转得慢的子空间。

这一步是很多人卡住的地方。理解的关键是:所谓RoPE,就是在q和k进入注意力计算前,用一系列旋转矩阵把它们各自拧一下。语义不变,方向变成位置的函数。

相对位置,藏在一个角度差里

接下来是RoPE最漂亮的地方:相对位置不是显式学习出来的,而是从旋转的减法里自然浮现的。

假设q在位置m,k在位置n,注意力分数是它们的点积。旋转矩阵是正交矩阵,所以内积会自动化简成:

<q_m, k_n> = q · R(n-m) · k

结果只取决于n-m,两个位置的相对距离。位置差变成了角度差,模型天然知道“隔了两步的那个词”和“挨着的那个词”不是一回事。

这也是标题里复数旋转四个字的来历:数学上,二维旋转等价于乘单位复数e^{iθ},把每个子空间看成复平面,RoPE就是让向量乘以e^{i m θ_i}。复数不是一个好看的修饰词,它就是旋转本身。

你可能会问:它和更早的Sinusoidal位置编码有什么区别?区别在作用方式。Sinusoidal把三角函数值加进向量,RoPE却把三角函数值变成了作用于向量的旋转算子。前者是加法,后者是乘法;前者改变了向量长度,后者只改变方向。这个差别,决定了注意力计算能不能在相对位置上获得精确的几何解释。

一张表看清几种位置编码

方案 编码方式 相对位置 外推能力 代表模型
绝对位置 加向量 需要学习 BERT、GPT-2
Sinusoidal 加三角函数 隐含三角恒等式 有限 Transformer原版
RoPE 旋转 角度差 配合插值可用 LLaMA、Mistral、Qwen
ALiBi 注意力分数惩罚 距离衰减 MPT

RoPE成为主流大模型默认方案的原因,可以归结为三点:

  • 推理开销低。q和k在进入注意力前就完成了旋转,注意力计算本身无需感知位置,KV cache逻辑完全不受影响。
  • 相对位置天然。注意力分数只依赖位置差,模型能更高效地利用有限的训练长度。
  • 给外推留了接口。位置是一系列连续角度,后续的长度扩展技术基本都是在这组角度上做重标定。

软肋:外推没有想象中美好

这里必须说句大实话:RoPE的外推能力,远没有论文标题那么乐观。位置插值论文一开始就在描述一个现象:直接把位置延伸到训练长度之外,模型困惑度会急剧上升,注意力分布开始混乱。

原因其实也简单。训练时模型见过的最大角度范围是有限的,超出这个范围的旋转状态对它来说是陌生的。旋转角度可以无限加,但模型并没有见过那些角度下的向量方向组合。后来大家用位置插值(PI)把角度整体压回训练范围,或者用NTK-aware scaling改旋转速度,本质上都是把长距离位置重标定到模型熟悉的区域里。

RoPE论文提出时设想的结构性外推能力,实际行动时需要PI、NTK、YaRN这些技术来“辅助”,没有一个是无代价的。

这也是我在实际使用中提醒自己的:看到一个模型声称直接支持128K上下文,先看它的config里有没有rope_scaling。很多情况下,是偷偷换了一种角度映射,而不是真的让RoPE自己长出外推能力。YaRN论文里对这种能力和代价的权衡写得很清楚。

它为什么赢,以及它的边界

如果只用一个词总结RoPE的设计哲学,我会选:几何。它把离散的token位置变成了连续的旋转角度,把相对位置变成了角度差,把外推问题变成了角度映射问题。这种干净的性质,让它成为工程和理论的共同选择。

但边界同样清楚:RoPE编码的是一个角度,角度是有周期性的。一旦位置跨度大到旋转角度自身混淆,模型就会失效。这也是为什么RoPE体系下,大家都在研究如何“重标定”而不是“让模型更聪明”的原因。位置编码的下一轮变革,大概率还是围绕“什么几何结构最能描述文本顺序”展开的。

还想再深挖?

RoPE的数学推导我建议直接读苏剑林的博客,他给出了原始推导过程,对数学恐惧者也友好。补充阅读:RoFormer原始论文、位置插值论文、YaRN论文。

你现在应该能分辨了:RoPE不是玄学,是一堂旋转几何课。

原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/609.html

(0)
上一篇 1天前
下一篇 1天前

相关推荐