RoPE 旋转位置编码完整讲解(贴合Qwen3 手搓代码)

一、RoPE 是什么,解决什么痛点

全称 Rotary Positional Embedding,旋转位置编码 传统 Transformer 正弦 PE、BERT 可学习 PE:

  1. 采用加法嵌入位置:emb + pos_emb
  2. 注意力分数混杂绝对位置,超长文本外推效果差;
  3. 无法天然表达 token 之间的相对距离。

RoPE 核心思路: 不把位置向量加到词嵌入,而是对 Q、K 向量做二维正交旋转,用乘法注入位置相位; 数学保证:Q、K 旋转后的点积仅由两者相对位置差决定,天然适配长文本、外推能力强,LLaMA/Qwen/Mistral 全系标配。

关键规则:只旋转 Q、K,V 不做任何旋转

二、底层二维旋转数学(差角公式推导)

1. 旋转矩阵

二维向量 (a,b) 逆时针旋转角度 ϕ:

[a′b′​]=

\begin{bmatrix} \cos\phi & -\sin\phi \ \sin\phi & \cos\phi \end{bmatrix} \begin{bmatrix}a\b\end{bmatrix}

展开:

\begin{cases} a' = a\cos\phi - b\sin\phi \ b' = a\sin\phi + b\cos\phi \end{cases}

2. 复数等价视角(极简理解)

把二维向量 z=a+bi 视为复数,旋转等价乘 eiϕ:

z′=z⋅eiϕ=(a+bi)(cosϕ+isinϕ)

3. 核心:相对位置不变性(差角公式)

设:

  • m:Query 绝对位置,旋转角 mθ,q~​=q⋅eimθ
  • n:Key 绝对位置,旋转角 nθ,k~=k⋅einθ

注意力分数取复共轭内积实部:

Re(q~​​⋅k~)=Re(q​e−imθ⋅keinθ)=Re(q​k⋅ei⋅(n−m)θ)

式子只含 Δ=n−m(相对距离),与 m、n 绝对位置无关,这是 RoPE 最核心优势。

展开后完全依赖三角函数差角公式,印证仅相对位置生效。

三、高维拆分规则(代码实现前提)

每个注意力头维度 head_dim 必须是偶数(如 Qwen3=128):

(对每个注意力头的每一对维度,按指数衰减的频率计算旋转角度,用于给 token 位置注入相对位置信息。)

  1. 将一整组向量按两个维度一组切分,每组独立旋转;
  2. 每组分配独立基础频率 θi​,高低频区分远近位置:

  • 原版 base=10000,Qwen3 调大 base=500000,减缓高频旋转,提升长文本能力;
  • i 为分组索引,低频组(i 小)旋转慢,捕捉远距离依赖;高频组捕捉局部依赖。
  1. 位置 pos 第 i 组总旋转角:

ϕpos,i​=pos⋅θi​

  1. 预计算全部位置的 cos(ϕ),sin(ϕ),缓存复用,不用实时计算。

四、对应你代码里的 RoPE 实现 apply_rotary_pos_emb

1. rotate_half 函数(实现矩阵旋转后半段)

def rotate_half(x):
    x1, x2 = x.chunk(2, dim=-1)
    return torch.cat((-x2, x1), dim=-1)
  • x1:每组前半维;x2:每组后半维
  • 输出 [−x2​, x1​],对应旋转矩阵的 、 项。

2. 完整旋转公式

q_embed = q * cos + rotate_half(q) * sin
k_embed = k * cos + rotate_half(k) * sin

完美匹配二维旋转展开式: x' = x\cdot\cos\phi + \text{rotate_half}(x)\cdot\sin\phi

3. 张量维度匹配(Qwen3 Attention)

Q/K 形状:[batch, num_heads, seq_len, head_dim] cos/sin 预计算为 [1,1,seq_len,head_dim],广播匹配多头、批量维度。

五、Qwen3 完整执行顺序(重点,面试高频)

Qwen3 独有 QK-Norm 在 RoPE 之前,流程:

  1. 隐藏层经过 q_proj/k_proj/v_proj 线性投影;
  2. 重塑多头,交换维度 transpose(1,2)
  3. 逐头 QK-Norm(RMSNorm)归一化 Q、K,约束向量模长;
  4. 送入 apply_rotary_pos_emb 做 RoPE 旋转;
  5. K/V 分组复制匹配 GQA 头数;
  6. 缩放点积注意力打分。
# 你代码中对应片段
query_states = self.q_norm(query_states).transpose(1, 2)
key_states = self.k_norm(key_states).transpose(1, 2)
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)

V 全程不做归一化、不做 RoPE。

六、RoPE 三大核心优势

  1. 天然相对位置建模 注意力分数只看 token 间隔,不看绝对序号,长文本语义更合理;
  2. 极强长度外推能力 训练最大长度 8k,推理可直接跑 32k/64k(搭配 YaRN / 线性缩放优化);
  3. 轻量无训练参数 cos/sin 是预计算常量,不增加可学习权重,推理开销极低。

七、RoPE 缺陷与行业优化

  1. 原生长文本外推衰减:相对位置越大,注意力分数衰减严重;
    • 优化:Linear Scaling、YaRN、Llama3 增大 base theta;
  2. 高频维度远距离区分度差;
  3. 仅作用于 Q/K,V 无位置信息,依赖打分传递位置。

八、RoPE vs 传统位置编码对比

编码方案嵌入方式相对位置长度外推可训练参数
正弦 PE向量相加
BERT 可学习 PE向量相加不支持
RoPE向量旋转(乘性)强(数学保证)优秀

九、一句话总结

RoPE 将 Q/K 向量按二维分组做位置相关正交旋转,利用复数 / 三角差角公式让注意力分数仅依赖 token 相对距离;Qwen3 在旋转前增加 QK-Norm 稳定数值,是当前大模型标准位置编码方案。

更多推荐