RoPE原理:旋转如何表达相对位置
RoPE把位置信息写进query和key的旋转角度。看似使用的是绝对位置m与n,但两者做内积时,旋转角之差会留下n−m。因此模型能在注意力分数中表达相对位置,而不是仅给向量追加一个位置编号。
先看一个二维旋转
用R(a)表示逆时针旋转a弧度。对二维向量(x,y),旋转后的两个分量为 (cos(a)x−sin(a)y, sin(a)x+cos(a)y)。旋转保持长度,改变方向。
让query旋转mθ、key旋转nθ,分数成为 (R(mθ)q)ᵀ(R(nθ)k) = qᵀR((n−m)θ)k。原因是R(mθ)的转置等于R(−mθ),两个旋转相乘时角度相加。这是相对位置进入内积的关键。
旋转60°
旋转150°
相对距离 n−m=3
把两个位置同时加7,角度各自多转210°,但差仍为90°。这个相同的位移不改变本例分数。注意此处保持内容向量q、k不变;真实上下文发生改变时,模型内部的q、k也可能变化。
把等式变成可以运行的检查
下面用Python核对相对旋转等式、共同平移不变性,以及旋转保持长度。代码已执行,输出约为0;使用绝对误差容限,避免把浮点舍入当成恒等式失效。
import math
def rotate(x, angle):
c, s = math.cos(angle), math.sin(angle)
return (c*x[0]-s*x[1], s*x[0]+c*x[1])
def dot(a,b):
return sum(x*y for x,y in zip(a,b))
q, k = (1.0,0.0), (1.0,0.0)
theta = math.pi/6
m, n = 2, 5
score = dot(rotate(q,m*theta),rotate(k,n*theta))
relative = dot(q,rotate(k,(n-m)*theta))
shifted = dot(rotate(q,(m+7)*theta),
rotate(k,(n+7)*theta))
assert math.isclose(score,relative,abs_tol=1e-12)
assert math.isclose(score,shifted,abs_tol=1e-12)
assert math.isclose(dot(rotate(q,m*theta),rotate(q,m*theta)),
dot(q,q),abs_tol=1e-12)
print(round(score,6))
这是单个二维子空间的教学验证,没有执行完整Transformer,也没有测量长文本任务质量。选择θ=π/6是为了易于计算,不是指定某个模型的频率配置。
高维向量不是一起转一个角度
原始RoFormer工作于2021年提交arXiv。RoPE可在二维子空间上分别旋转,不同子空间采用不同频率。采用相同维度配对方式、频率及位置约定时,相对旋转关系逐对成立。
实际实现的通道布局可能不同:相邻分量配对或将两半对应配对,必须与权重和库的约定一致。检查实现时,建议先用一个小向量确认配对,再确认位置索引、频率表和KV缓存中的位置推进。不能仅凭函数都叫RoPE就认为可以互换。
| 检查项 | 本例验证了什么 |
|---|---|
| 维度配对 | 只用一个二维对 |
| 相对位置 | 内容向量固定时的旋转内积恒等式 |
| 长上下文质量 | 没有测试 |
可以算更远,不等于能理解更远
旋转公式能接受较大的位置索引,这是数学可计算性;模型是否能在超出训练长度的上下文中正确检索和推理,是另一项证据要求。上面的三个断言不能证明长上下文效果。
评估扩展上下文时,可以在不同长度和证据位置上设置同一类检索任务,记录正确率与延迟。还要记录模型版本、位置配置、输入截断规则以及可用的KV缓存预算。能接收一段很长的输入与能可靠利用全部内容,应分别验证。
RoPE适合从“两个旋转为何只剩角度差”开始理解。把这个局部恒等式核对清楚,再讨论模型层面的长上下文,能减少对公式能力的过度推断。
资料来源
RoFormer原始预印本(2021);作者官方实现。本文不复现论文评测,不把历史原理包装成新消息。
支持
如果这篇文章对你有帮助,欢迎支持本站。
二维码可点击放大。更多支持方式见支持页面。


