RoPE 的基本思想
RoPE 全称为 Rotary Position Embedding ,中文通常称为旋转位置编码。
传统 Transformer 的位置编码通常采用加法:
输入向量 = token embedding + position embedding
RoPE 不再把位置编码直接加到输入向量中,而是在生成 Q、K 后,根据 token 的位置对 Q、K 进行旋转:
q = Wq × hidden
k = Wk × hidden
v = Wv × hidden
q = RoPE(q, position)
k = RoPE(k, position)
然后再计算注意力分数:
score = q × k^T
完整的注意力计算通常为:
Attention(Q,K,V) = softmax(QK^T / sqrt(d)) × V
因此,RoPE 的位置编码发生在:
隐藏状态
→ 生成Q、K、V
→ 对Q、K应用RoPE
→ 计算注意力分数
→ 根据注意力权重聚合V
Q、K 是如何旋转的
将高维向量拆成二维组
旋转矩阵本身通常用于二维向量,但 Q、K 是高维向量,因此 RoPE 会把向量的维度两两分组。
假设某个注意力头中的 Q 是 8 维:
Q = [q0,q1,q2,q3,q4,q5,q6,q7]
可以分成四个二维组:
第0组:(q0,q1)
第1组:(q2,q3)
第2组:(q4,q5)
第3组:(q6,q7)
每个二维组分别进行旋转。
二维向量 (x1,x2) 旋转角度 α 后:
x1' = x1 × cos(α) - x2 × sin(α)
x2' = x1 × sin(α) + x2 × cos(α)
旋转只会改变向量的方向和各维度的具体数值,不会改变向量的维度和模长,并且该操作是可逆的。
不同二维组使用不同旋转速度
对于位置 pos 上的 token,其第 i 个二维组旋转:
angle(pos,i) = pos × θ_i
其中,θ_i 表示:
在第 i 个二维组中,token 的位置每增加 1,该组需要增加多少旋转角度。
不同二维组具有不同的 θ_i:
第0组使用 θ_0
第1组使用 θ_1
第2组使用 θ_2
......
经典 RoPE 中通常使用:
θ_i = base^(-2i/d)
其中:
-
i:二维组编号; -
d:应用 RoPE 的向量维度; -
base:预设的频率基数,经典值通常为 10000。
随着组编号增加,θ_i 通常逐渐减小:
-
前面的二维组旋转较快;
-
后面的二维组旋转较慢。
可以理解为:
位置决定旋转多少步
θ_i决定每一步旋转多少
最终角度 = token位置 × 该组旋转速度
为什么能表示相对位置
假设位置 m 上的 Q 和位置 n 上的 K,在第 i 个二维组中分别旋转:
Q的角度 = m × θ_i
K的角度 = n × θ_i
计算旋转后的 Q、K 点积时,最终与两者的角度差有关:
n × θ_i - m × θ_i
= (n-m) × θ_i
其中 n-m 就是两个 token 的相对位置。
因此,RoPE 的特点是:
使用 token 的绝对位置决定旋转角度,但在 Q、K 点积中自然表现出相对位置差。
例如:
token A位于位置3
token B位于位置8
相对距离为8-3=5
如果二者整体向后移动:
token A位于位置103
token B位于位置108
相对距离仍然为108-103=5
它们在注意力计算中的相对位置关系仍然保持一致。
常见疑问
旋转 10° 和 370° 不会重合吗
会。在单个二维组中:
370° = 10° + 360°
因此它们旋转后的方向相同。
但 RoPE 同时使用很多个旋转速度不同的二维组。某一组发生重合时,其他组通常不会同时重合。
例如:
第0组每个位置旋转10°
第1组每个位置旋转1°
第2组每个位置旋转0.1°
比较位置1和位置37:
第0组:
位置1为10°
位置37为370°
两者重合
第1组:
位置1为1°
位置37为37°
两者不同
第2组:
位置1为0.1°
位置37为3.7°
两者不同
注意力分数由所有维度组共同计算:
总注意力分数
= 第0组的贡献
+ 第1组的贡献
+ 第2组的贡献
+ ...
因此,单个二维组发生周期性重合,并不意味着整个 Q、K 表示重合。
不同频率的作用可以理解为:
快速旋转组:
对较小的位置变化敏感,适合区分近距离关系,
但容易较快转完一圈。
慢速旋转组:
相邻位置变化较小,但很长距离内不容易转完一圈,
适合表示较远的位置关系。
RoPE 通过快慢不同的频率,同时兼顾局部位置分辨率和较长距离的位置表示。
旋转会不会破坏语义
旋转会改变 Q、K 每个维度的具体数值,但不等于语义信息被破坏。
原因主要有三点:
-
旋转不会改变向量的维度和模长,并且可以反向恢复,是可逆操作。
-
大模型的语义通常分布在大量维度中,不是"一个维度固定对应一个语义"。
-
Q、K 本身也不是完整的 token 内容,而是用于计算 token 之间匹配关系的检索特征。
可以简单理解为:
Q:当前token想查找什么
K:当前token可以通过什么特征被匹配
V:当前token真正向其他位置传递什么信息
RoPE 改变的是 Q、K 之间的匹配方式,使注意力同时考虑语义关系和位置关系,而不是直接修改真正传递的内容。
为什么只旋转 Q、K,不旋转 V
注意力权重由 Q、K 的点积计算:
score = Q × K^T
token 之间的位置关系主要需要影响:
当前token应该关注其他token多少
因此,位置信息应该进入 Q、K 的匹配过程。
V 表示注意力确定之后真正需要传递的内容:
输出 = 注意力权重 × V
所以经典 RoPE 通常只旋转 Q 和 K,不旋转 V。
可以概括为:
Q、K决定从哪里读取信息
V决定具体读取什么信息
RoPE 的整体理解
RoPE 并不是给每个 token 单独添加一个位置标签,而是:
-
将每个注意力头的 Q、K 分成多个二维组;
-
不同二维组使用不同的旋转速度;
-
token 的位置决定每组最终旋转多少;
-
旋转后的 Q、K 点积自然包含两个 token 的相对位置;
-
最终使用注意力权重从 V 中读取并传递内容。
一句话概括:
RoPE 根据 token 的位置旋转 Q、K 的不同二维维度组,使 Q、K 的注意力匹配同时包含语义关系和相对位置关系。