RoPE 全景详解:标准 RoPE × YaRN × MLA 解耦 RoPE × 主流模型对比
从 GEMM 矩阵视角剖析 RoPE 的数学本质,深入讲解 DeepSeek MLA 使用的 YaRN 与常规 RoPE 的计算差异(三段式频率策略 + mscale 温度缩放), 并横向对比 DeepSeek、Qwen、GLM、ERNIE 四家主流模型的 RoPE 实现差异。
① 标准 RoPE本质是位置相关的块对角旋转
每个 head 的 d 维 Q/K 按每 2 维分组,第 i 组频率 θᵢ = base−2i/d,位置 m 的旋转角 = m·θᵢ。
⚙️ 工程实现不走 GEMM(99% 元素为 0),而用 q ⊙ cos + rotate_half(q) ⊙ sin 两次 Hadamard。
② YaRN三段频率 + 温度缩放
按 "波长 λ vs 训练长度 L" 把频率分成三段:
🟢 高频(λ ≪ L):原样外推不动 | 🔴 低频(λ ≫ L):除以 factor 压缩 | 🟡 中频:ramp 平滑过渡
再乘一个注意力温度 mscale = 0.1·ln(s) + 1,等价对 logits 缩放,把长序列分布"拉回"训练分布。
③ MLA + YaRN只作用 64 维,不碰 latent
DeepSeek MLA 把 K 拆成 ct (512, latent) + k_rope (64)。YaRN 只施加在 64 维 k_rope / q_rope 上。
⚠️ 不能对 ct 施加 RoPE — 否则 WUK 矩阵吸收失效。mscale 直接乘进 Q/K,省一次 logits 缩放。
④ 四家差异一张卡看懂
解耦 RoPE(64 维)+ YaRN (s=40)
→ 163K
全维 RoPE + base=1e6 + 可选 YaRN
→ 131K~1M
Partial RoPE (rotary_pct=0.5)
base=1e4 → 128K
标准 RoPE + base=5e5
可配置多种 scaling → 128K
⑤ 选型建议按场景对号入座
🎯 超长上下文 → 首选 YaRN(s≥32,配合 mscale)
🎯 已用 MLA 架构 → 必须走解耦 RoPE,不能偷懒
🎯 最小改动扩上下文 → 直接调大 base(Qwen 路线),≤4× 够用
❌ 超过 4× 单靠调 base 会导致困惑度爆炸,必须上 YaRN / NTK。
📖 1. 背景:RoPE 是什么
Rotary Position Embedding (RoPE) 由 Su et al. 在 RoFormer (2021) 提出,核心思想是: 通过对 Q 和 K 施加位置相关的旋转,使注意力 score 自然编码相对位置。 它不加到 embedding 上(像 sinusoidal 那样),也不是可学习的 bias(像 ALiBi 那样),而是嵌入到 Q/K 的线性变换阶段。
相比绝对位置编码,RoPE 有三个决定性优势:
- 相对性自动成立:⟨Rmq, Rnk⟩ = ⟨q, Rn-mk⟩,score 只依赖相对位置 n-m
- 长度可扩展:训练时未见过的位置也能算出旋转矩阵(只是效果会退化,这也是 YaRN 要解决的问题)
- 与 MHA/GQA/MLA 架构正交:只在 Q/K 上动手脚,不改变 attention 的 softmax 结构
R(a)T R(b) = R(b-a)。
所以 QmTKn = (Rmq)T(Rnk) = qT Rn-m k,
score 中自然出现 n-m 的相对位置差。
🧮 2. 标准 RoPE 数学
设 head_dim = d(通常 128),对每 head 的 Q/K 向量 q ∈ ℝd,位置 m。RoPE 把 d 维按 2 维分组,一共 d/2 对,每对有自己的频率:
第 i 对 (q2i, q2i+1) 在位置 m 的旋转角为 m · θi,旋转公式:
q'2i+1 = q2i · sin(m θi) + q2i+1 · cos(m θi) (2) 2 维旋转
2.1 GEMM 矩阵视角:RoPE 的"伪 GEMM"图
把整件事放到 GEMM 视角,RoPE 等价于 Q 矩阵 × 块对角位置旋转矩阵 Rm。下图展示单个 token 位置 m 下,head_dim = 8(4 对频率)的标准 RoPE 矩阵乘法:
q * cos + rotate_half(q) * sin 两次 element-wise 乘法 + 1 次加法,计算量从 O(d²) 降到 O(d)。
2.2 工程实现:两次 Hadamard 而非 GEMM
Hugging Face / vLLM / SGLang 通用实现(interleaved vs half-split 两种形态):
# 预计算:生成 [seq_len, d/2] 的 cos 和 sin 表(一次性,整个推理复用)
def build_cos_sin(seq_len, d, base=10000):
theta = 1.0 / (base ** (torch.arange(0, d, 2) / d)) # [d/2]
pos = torch.arange(seq_len) # [L]
freqs = pos[:, None] * theta[None, :] # [L, d/2]
return torch.cos(freqs), torch.sin(freqs) # 复制成 [L, d]
# RoPE 应用:two-Hadamard form(HuggingFace "half" 形态)
def apply_rope(x, cos, sin):
# x: [B, L, H, d]; cos/sin: [L, d]
x1, x2 = x[..., :d//2], x[..., d//2:]
rotated = torch.cat([-x2, x1], dim=-1) # rotate_half 技巧
return x * cos + rotated * sin # 两次 Hadamard + 一次加法
Python
🌐 3. YaRN 详解:长上下文救星
3.1 为什么朴素 RoPE 在训练长度外会烂
训练长度 Ltrain = 4K 的模型,在推理时直接塞 32K 会困惑度爆炸。原因:
- 频率波长 λi = 2π/θi。高频部分波长远小于 Ltrain,训练已经见过完整周期,外推没问题。
- 低频部分波长 λ ≫ Ltrain,训练时只见过 sin/cos 的一小段弧,模型误以为这段弧是"常量偏置"。推理到 32K 时这部分突然进入新的弧段,attention 的 q·k 内积分布骤变,数值直接崩溃。
3.2 三段频率策略(NTK-by-parts)
YaRN 的核心洞察:不同频率波段要不同对待。按 每波长能装下多少个训练 token ri = Ltrain / λi 分三段:
数学公式(DeepSeek-V3 中实际使用的 yarn_get_mscale、find_correction_range):
αi = ramp(ri, βslow, βfast)
θ'i = (1 − αi) · (θi / s) + αi · θi (3) NTK-by-parts
其中 s = factor = Ltarget / Ltrain(DeepSeek V3 用 40:163840 / 4096 ≈ 40);βfast=32, βslow=1 是 YaRN 论文推荐值。
3.3 注意力温度 mscale:为什么光改频率不够
即便频率调好了,长上下文下 q·k 的 绝对值 仍然偏大(序列越长,累加越多项)。YaRN 额外引入 注意力温度 t,等价于在 softmax 前把 logits 除以 √t:
attention_score = (q · k) / √d × mscale2 (4) 温度缩放
DeepSeek-V3 把这个等价放到前面:q_pe *= mscale; k_pe *= mscale,这样 q·k 出来的 logits 自动带上 mscale²,不需要在 softmax 前再乘一次。
mscale_all_dim 分别作用于所有维度 vs 只作用于 rope 维度,V2-Chat-0628 和 V3 对两者的配置略有不同。
🔀 4. MLA 中的 YaRN:只作用于 64 维 RoPE 子空间
DeepSeek-V2/V3 的 MLA 架构对 RoPE 做了"解耦":把 Q/K 拆成压缩 latent 部分(不加 RoPE)和 RoPE 部分(加 RoPE):
DeepSeek-V3 的具体 YaRN 配置(摘自官方 config.json):
"rope_scaling": {
"type": "yarn",
"factor": 40, # s = 163840 / 4096
"original_max_position_embeddings": 4096,
"beta_fast": 32,
"beta_slow": 1,
"mscale": 1.0, # 用于 q_rope / k_rope
"mscale_all_dim": 1.0 # 用于 q_nope / softmax 总缩放
},
"rope_theta": 10000, # base 仍是 10k(YaRN 基础上调整)
"qk_rope_head_dim": 64,
"qk_nope_head_dim": 128,
"v_head_dim": 128,
"max_position_embeddings": 163840
DeepSeek-V3 config.json
🏛️ 5. 四家主流模型 RoPE 对比
5.1 DeepSeek V2 / V3 — 解耦 RoPE + YaRN
- 架构:MLA,Q 拆为
q_nope (128) + q_rope (64),K 拆为c_t (512 共享) + k_rope (64 共享) - base = 10000(标准),YaRN factor = 40,有效 context = 128K~160K
- mscale = 0.1·ln(40)+1 ≈ 1.369,乘进 Q/K 而非 logits
- 独特之处:RoPE 只作用在 1/3 的 Q 维度(64/192)和 1/9 的 K 维度(64/576);矩阵吸收不受影响
5.2 Qwen 2.5 / Qwen 3 — 大 base + 可选 YaRN
- 架构:GQA,全维 RoPE(rotary_pct = 1.0),head_dim = 128
- base = 1,000,000(即 ABF RoPE,Attention Bias Function RoPE),Qwen 2 就已从 10k 调到 1M
- native context:Qwen3 原生 32K,启用 YaRN 后 131K;Qwen2.5-1M 进一步 + DCA 到 1M
- DCA (Dual Chunk Attention):长序列分块,块内用相对位置,块间用特殊偏置,与 YaRN 正交组合
- 独特之处:主要靠"预训练就用大 base"换取较好的长度外推性,YaRN 是锦上添花
5.3 GLM / ChatGLM — Partial RoPE
- 架构:MHA(GLM-4)或 MQA(ChatGLM3),partial_rotary_factor = 0.5
- head_dim = 128,但只有前 64 维做 RoPE,后 64 维原样保留
- base = 10000(GLM-4 标准),某些长文本变体会调大
- 独特之处:最早(ChatGLM-6B 时代)就采用半维 RoPE,设计动机是留一半维度承载"纯内容信息",不受位置干扰。GLM-4-9B-Chat-1M 在此基础上叠加 YaRN 扩到 1M
5.4 ERNIE 4.5 — 标准全维 RoPE + 多种 scaling
- 架构:MoE(ERNIE-4.5-300B-A47B 等)或 dense,全维 RoPE
- base = 500,000(rope_theta 默认 5e5,介于 Llama 的 1e4/5e5 与 Qwen 的 1e6 之间)
- rope_scaling 字段支持
default / linear / dynamic / yarn / longrope / llama3六种,由使用方按需开启 - 独特之处:HuggingFace 官方把 ERNIE 4.5 的 RoPE 抽象为通用
rope_parameters字典,配置非常"标准",没有像 DeepSeek/GLM 那样引入架构层面的 RoPE 变体
🖼️ 5.5 四家 QK 计算流程可视化对比
下面用统一的视觉语言画出四个模型在 Q/K 向量构造 → RoPE 施加 → QKT 打分 全流程的差异。颜色约定:
🅐 DeepSeek V3(MLA 解耦 RoPE + YaRN)
🅑 Qwen3(全维 RoPE + 大 base 1e6)
🅒 GLM-4(Partial RoPE:前 64 旋转 + 后 64 保持)
🅓 ERNIE 4.5(全维 RoPE + base 5e5 + 可配置 scaling)
四家一图并排:谁"染红"了 Q/K 的哪段?
Qwen3 / ERNIE = 简单粗暴,整条 Q/K 全染红,差异只在 base;
GLM-4 = 一人一半,前 64 染红、后 64 保蓝。
📊 6. 横向对比总表
| 模型 | RoPE 类型 | base (θ) | rotary ratio | 原生长度 | 扩展方法 | 极限长度 |
|---|---|---|---|---|---|---|
| DeepSeek V3 | 解耦 RoPE (Decoupled) |
10,000 | 64/192 Q 64/576 K |
4K | YaRN (s=40) β_fast=32, β_slow=1 |
163,840 |
| Qwen3 / Qwen2.5 | 全维 RoPE (ABF) |
1,000,000 | 1.0 (full) | 32K | YaRN+可选 DCA | 131K~1M |
| GLM-4 | Partial RoPE | 10,000 | 0.5 (前 64/128) | 128K | YaRN (1M 版本) | 1,000,000 |
| ERNIE 4.5 | 标准全维 RoPE | 500,000 | 1.0 (full) | 128K | 可配置 (default/linear/yarn/llama3) |
128K+ |
数值直观感受
用 head_dim = 128 时 base 对最低频波长的影响(λmax = 2π · base(d-2)/d):
base 越大 → 最低频波长越长 → 模型"见过"的相对位置跨度越大 → 天然外推能力越强。这是 Qwen 直接把 base 调到 1M 的底层逻辑。
✅ 7. 结论与建议
从算法视角,RoPE 家族的演化可以用一张图概括:
已有 4K/8K 模型想扩到 128K+:YaRN,factor = target/train,β_fast=32 / β_slow=1,再配 mscale。
KV cache 内存吃紧:走 MLA 架构,RoPE 必须解耦成 k_rope 独立 64 维。
切忌:单纯线性插值 (PI) 对困惑度有肉眼可见的损伤;动态 NTK 在边界频率不连续;YaRN 目前在效果 / 实现复杂度平衡上最好。
📚 参考资料 / References
- RoFormer: Enhanced Transformer with Rotary Position Embedding (Su et al., 2021) — RoPE 原始论文
- YaRN: Efficient Context Window Extension of Large Language Models (Peng et al., 2023) — YaRN 三段策略与 mscale 推导
- DeepSeek-V2 Technical Report — MLA 与解耦 RoPE 首次提出
- DeepSeek-V3 inference/model.py — YaRN + MLA 官方实现
- vLLM deepseek_scaling_rope API — 生产级 YaRN 实现参考
- HuggingFace GLM-4 Model Doc — partial_rotary_factor=0.5 官方说明
- HuggingFace ERNIE 4.5 Model Doc — rope_parameters / rope_scaling 配置字段
- Qwen3-32B on HuggingFace — rope_theta=1e6 与 YaRN 使用说明
- Qwen2.5-1M Blog Post — DCA + YaRN 扩 1M 上下文
- Qwen2 Technical Report — ABF RoPE(base 从 10k 提到 1M)
- How LLMs Scaled from 512 to 2M Context — RoPE 外推方法综述
- DeepSeek-V2 Discussion: mscale calculation — mscale 公式的官方讨论