大模型基础:Rotary Position Embedding(RoPE)

🎯 为什么需要位置编码?

Transformer 模型本身是 排列不变的(permutation-equivariant),也就是说:

❗ 它不知道"词的顺序"!

所以我们必须显式告诉它:

"这个 token 是第几个?"

这就是**位置编码(Positional Encoding)**的作用。


📚 传统方法 vs RoPE

方法 代表模型 缺点
绝对位置编码 BERT、原始 Transformer 无法外推,长度受限
相对位置编码 DeBERTa、T5 实现复杂
RoPE(旋转式) LLaMA、Qwen、Mistral、Phi ✅ 可外推、数学优雅、支持长上下文

📌 RoPE 已成为当前开源大模型的事实标准


🔍 RoPE 的核心思想

RoPE的核心思想,如下图所示:

❝ 用 二维向量的旋转 来建模 token 之间的相对位置关系,并通过 Q 和 K 的点积自然体现出"距离越远,影响越小"。 ❞


🧮 数学原理

Step 1:基本形式(单个维度)

假设我们有一个向量 x ∈ R d x \in \mathbb{R}^d x∈Rd,我们想给它加上位置信息。

RoPE 对每一对相邻维度进行"旋转"操作:

f m ( x ) = R ( θ m ) x f_m(x) = R(\theta^m) x fm(x)=R(θm)x

其中:

  • m m m:token 的位置索引(如第 5 个 token → m = 5 m=5 m=5)
  • θ m \theta^m θm:旋转角度,与位置相关
  • R ( θ ) R(\theta) R(θ):二维旋转矩阵:

R ( θ ) = [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} R(θ)=[cosθsinθ−sinθcosθ]


Step 2:角度如何定义?

RoPE 使用 频率递减的正弦波 来设置角度:

θ i = 1000 0 − 2 i / d , i = 0 , 1 , ... , d / 2 − 1 \theta_i = 10000^{-2i/d}, \quad i = 0,1,\dots,d/2-1 θi=10000−2i/d,i=0,1,...,d/2−1

然后对于位置 m m m,第 i i i 维的旋转角为:

θ i m = m ⋅ θ i = m ⋅ 1000 0 − 2 i / d \theta_i^m = m \cdot \theta_i = m \cdot 10000^{-2i/d} θim=m⋅θi=m⋅10000−2i/d

📌 这样做的好处:

  • 高频部分编码短距离差异
  • 低频部分编码长距离趋势
  • 支持插值和外推

Step 3:应用到 Q 和 K

在 attention 中,我们对 Query 和 Key 应用 RoPE:

Q m = RoPE ( W q x m , m ) K n = RoPE ( W k x n , n ) Q_m = \text{RoPE}(W_q x_m, m) \quad K_n = \text{RoPE}(W_k x_n, n) Qm=RoPE(Wqxm,m)Kn=RoPE(Wkxn,n)

然后计算点积:

Q m T K n = Func ( m − n ) Q_m^T K_n = \text{Func}(m - n) QmTKn=Func(m−n)

👉 关键结论:

点积结果只依赖于 m - n(相对位置),而不是绝对位置 mn

这就是 RoPE 能捕捉相对位置信息的数学基础。


🖼️ 图解:二维旋转示意

复制代码
      y
      ^
      |     P = (x, y)
      |    /
      |   / 
      |  /   θ = m * θ₀
      | /     
      |/__________> x

位置 m m m 的向量被旋转了 m ⋅ θ m \cdot \theta m⋅θ 角度。

不同位置的向量旋转角度不同,但它们之间的夹角反映了相对距离。


💡 为什么叫"旋转"?

因为:

  • 每个 token 的 embedding 被看作一组 2D 向量
  • 位置信息通过"旋转"这些向量来注入
  • 解码时,新 token 继续按规则旋转

就像钟表指针一样,每一步"走一格"。


🧱 在 Transformer 中的实际实现

输入:

  • x: [B, S, H] → batch, seq_len, hidden_size
  • position_ids: [B, S] → 每个 token 的位置索引(如 [0,1,2,...,31]

输出:

  • q_rotated, k_rotated: 注入位置信息后的 Q/K

PyTorch 伪代码:

python 复制代码
def rotate_half(x):
    """将 x 拆成两半,在最后维度上做旋转"""
    x1 = x[..., :x.size(-1)//2]
    x2 = x[..., x.size(-1)//2:]
    return torch.cat([-x2, x1], dim=-1)

def apply_rotary_pos_emb(q, k, cos, sin):
    # q, k: [B, H, S, D]
    q_embed = (q * cos) + (rotate_half(q) * sin)
    k_embed = (k * cos) + (rotate_half(k) * sin)
    return q_embed, k_embed

其中:

  • cos, sin 是预计算的 cos ⁡ ( m θ ) , sin ⁡ ( m θ ) \cos(m\theta), \sin(m\theta) cos(mθ),sin(mθ)

✅ 优势总结

优点 说明
显式建模相对位置 attention score 自然体现 m-n 关系
支持长度外推 只要 \\theta 设置合理,可处理比训练更长的序列
可逆且正交 旋转是正交变换,不改变向量长度,训练稳定
高效实现 可预先缓存 cos/sin,无需实时计算
兼容 KV Cache 推理时可动态扩展

⚙️ 扩展变体

名称 说明
ALiBi 不用 embedding,用线性偏置建模相对位置
NTK-aware RoPE 调整 θ \theta θ 分布,支持更长上下文
Dynamic NTK 推理时动态缩放,实现无限外推
YaRN 结合 RoPE 与 MoE,进一步提升长文本性能

📌 Qwen 系列就使用了 NTK-aware RoPE 来支持 32K+ 上下文


✅ 总结:

Rotary Embedding(RoPE)是一种通过"旋转"Query 和 Key 向量来注入位置信息的技术,它天然支持相对位置建模、长度外推和高效推理,是当前大语言模型中最先进、最主流的位置编码方式。

相关推荐
库库林_沙琪马9 小时前
SpringBoot内容协商机制
1024程序员节
元拓数智9 小时前
现代前端状态管理深度剖析:从单一数据源到分布式状态
前端·1024程序员节
大数据张老师9 小时前
数据结构——冒泡排序
数据结构·算法·排序算法·1024程序员节
Lzc7749 小时前
Linux网络的应用层协议HTTP
linux·1024程序员节·应用层协议http
赵_|大人9 小时前
Ubuntu开启SSH
1024程序员节
xie_zhr9 小时前
【PB案例学习笔记】-46在数据窗口中编辑数据
数据库·his·1024程序员节·干货分享·pb·powerbuilder
七夜zippoe9 小时前
压缩与缓存调优实战指南:从0到1根治性能瓶颈(六)
1024程序员节
Web3_Daisy9 小时前
冷换仓的隐性代价:从安全策略到地址信誉体系的重新思考
大数据·安全·web3·区块链·比特币·1024程序员节
狡猾大先生9 小时前
ESP32S3-Cam实践(OLED表情动画-手搓)
笔记·1024程序员节