从零理解 RoPE:大模型位置编码的革命
RoPE(Rotary Position Embedding,旋转位置编码)最早来自 2021 年论文《RoFormer: Enhanced Transformer with Rotary Position Embedding》,作者是苏剑林等人。论文提出了一种新的位置编码方法,通过旋转向量的方式把位置信息融入 Attention 计算中。
论文地址:
Rotary Position Embedding(RoPE)是目前大多数主流大模型(Llama、Qwen、DeepSeek、Mistral 等)采用的位置编码方案。
它最大的特点是:
将位置信息直接融入 Attention 计算过程,而不是简单地加到 Embedding 上。
本文将从 Transformer 为什么需要位置编码开始,一步一步推导 RoPE 的数学原理,并最终理解它为什么能够成为现代 LLM 的标准配置。
1. Transformer 为什么需要位置编码
Transformer 的核心是 Self-Attention:
A t t e n t i o n ( Q , K , V ) = S o f t m a x ( Q K T d ) V Attention(Q,K,V)= Softmax\left( \frac{QK^T}{\sqrt d} \right)V Attention(Q,K,V)=Softmax(d QKT)V
其中:
- Q Q Q:Query
- K K K:Key
- V V V:Value
Attention 计算的本质是:
s c o r e i j = q i T k j score_{ij}= q_i^T k_j scoreij=qiTkj
即两个向量的内积。
假设有两个句子:
text
我 爱 你
和
text
你 爱 我
如果只看词向量:
text
我
爱
你
Attention 根本不知道:
- 谁在前面
- 谁在后面
- 两个词之间距离多远
因为 Self-Attention 本身是置换不变(Permutation Invariant)的。
所以 Transformer 必须额外引入:
Position Encoding(位置编码)
来告诉模型词语顺序信息。
2. 传统位置编码方案
2.1 Learned Position Embedding
BERT、GPT-2 等模型采用的方法:
对于位置 p p p:
P E p PE_p PEp
训练一个可学习向量。
输入变成:
x p = E m b e d d i n g ( t o k e n p ) + P E p x_p= Embedding(token_p) + PE_p xp=Embedding(tokenp)+PEp
例如:
text
位置0 → P0
位置1 → P1
位置2 → P2
优点
简单有效。
缺点
模型只能学习训练过程中出现的位置。
例如:
训练长度:
text
2048
推理长度:
text
10000
模型从未见过:
text
P2049
P2050
...
外推能力很差。
2.2 Sinusoidal Position Encoding
Transformer 原论文提出:
P E ( p o s , 2 i ) = sin ( p o s 10000 2 i / d ) PE(pos,2i)= \sin\left( \frac{pos}{10000^{2i/d}} \right) PE(pos,2i)=sin(100002i/dpos)
P E ( p o s , 2 i + 1 ) = cos ( p o s 10000 2 i / d ) PE(pos,2i+1)= \cos\left( \frac{pos}{10000^{2i/d}} \right) PE(pos,2i+1)=cos(100002i/dpos)
特点:
- 无需学习参数
- 能够外推到更长长度
- 不依赖训练长度
但它有一个问题:
位置编码只是简单加法:
x p = E m b e d d i n g p + P E p x_p= Embedding_p + PE_p xp=Embeddingp+PEp
Attention 仍然计算:
Q K T QK^T QKT
位置关系只是间接参与计算。
于是人们开始思考:
能否直接把位置编码放进 Attention 里面?
RoPE 正是在这种背景下诞生的。
3. RoPE 的核心思想
RoPE 的名字:
text
Rotary Position Embedding
翻译:
text
旋转位置编码
它的思想非常简单:
不再把位置加到向量上,而是让向量按照位置旋转一定角度。
4. 二维空间中的旋转
先看一个二维向量:
x = x 1 x 2 x= \begin{bmatrix} x_1\\ x_2 \end{bmatrix} x=x1x2
二维旋转矩阵:
R ( θ ) = cos θ − sin θ sin θ cos θ R(\theta)= \begin{bmatrix} \cos\theta & -\sin\theta\\ \sin\theta & \cos\theta \end{bmatrix} R(θ)=cosθsinθ−sinθcosθ
旋转后:
x ′ = R ( θ ) x x'=R(\theta)x x′=R(θ)x
即:
x 1 ′ = x 1 cos θ − x 2 sin θ x'_1=x_1\cos\theta-x_2\sin\theta x1′=x1cosθ−x2sinθ
x 2 ′ = x 1 sin θ + x 2 cos θ x'_2=x_1\sin\theta+x_2\cos\theta x2′=x1sinθ+x2cosθ
如果:
θ = p o s \theta = pos θ=pos
那么:
text
位置不同
↓
旋转角度不同
↓
向量方向不同
位置编码就被编码进了向量方向中。
5. 将旋转应用到 Attention
假设:
第 m m m 个位置的 Query:
q m q_m qm
第 n n n 个位置的 Key:
k n k_n kn
RoPE 之后:
q ~ m = R m q m \tilde q_m=R_m q_m q~m=Rmqm
k ~ n = R n k n \tilde k_n=R_n k_n k~n=Rnkn
其中:
R m = R ( m θ ) R_m = R(m\theta) Rm=R(mθ)
R n = R ( n θ ) R_n = R(n\theta) Rn=R(nθ)
Attention Score 变成:
q ~ m T k ~ n = ( R m q m ) T ( R n k n ) \tilde q_m^T \tilde k_n = (R_m q_m)^T (R_n k_n) q~mTk~n=(Rmqm)T(Rnkn)
利用矩阵性质:
( A x ) T = x T A T (Ax)^T= x^TA^T (Ax)T=xTAT
得到:
= q m T R m T R n k n = q_m^T R_m^T R_n k_n =qmTRmTRnkn
由于旋转矩阵满足:
R ( α ) T = R ( − α ) R(\alpha)^T= R(-\alpha) R(α)T=R(−α)
所以:
R m T R n = R ( − m θ ) R ( n θ ) R_m^T R_n= R(-m\theta) R(n\theta) RmTRn=R(−mθ)R(nθ)
根据旋转矩阵群性质:
R ( a ) R ( b ) = R ( a + b ) R(a)R(b)= R(a+b) R(a)R(b)=R(a+b)
得到:
R m T R n = R ( ( n − m ) θ ) R_m^T R_n= R((n-m)\theta) RmTRn=R((n−m)θ)
于是:
q ~ m T k ~ n = q m T R ( ( n − m ) θ ) k n \tilde q_m^T \tilde k_n= q_m^T R((n-m)\theta) k_n q~mTk~n=qmTR((n−m)θ)kn
注意:
这里已经没有:
m m m
和
n n n
单独出现。
而只剩:
n − m n-m n−m
也就是说:
Attention Score 天然包含:
相对位置 = n − m 相对位置= n-m 相对位置=n−m
这正是 RoPE 最重要的性质。
6. 为什么这很重要
传统 Position Embedding:
text
位置信息
↓
加到Embedding
↓
Attention间接学习
RoPE:
text
位置信息
↓
直接作用于Q和K
↓
Attention天然感知距离
例如:
text
猫 在 吃 鱼
位置:
text
猫 0
在 1
吃 2
鱼 3
距离:
3 − 2 = 1 3-2=1 3−2=1
再看:
text
昨天 猫 在 吃 鱼
位置:
text
昨天 0
猫 1
在 2
吃 3
鱼 4
距离:
4 − 3 = 1 4-3=1 4−3=1
虽然绝对位置变化了:
text
2 → 3
3 → 4
但是:
text
吃 和 鱼
之间的相对距离仍然是:
1 1 1
RoPE 能保持这种关系。
7. 从二维推广到高维
真实模型:
text
hidden_size = 4096
不可能只使用二维。
RoPE 的做法:
把向量两两分组。
例如:
x 0 , x 1 , x 2 , x 3 , x 4 , x 5 \] \[x_0,x_1,x_2,x_3,x_4,x_5\] \[x0,x1,x2,x3,x4,x5
变成:
( x 0 , x 1 ) (x_0,x_1) (x0,x1)
( x 2 , x 3 ) (x_2,x_3) (x2,x3)
( x 4 , x 5 ) (x_4,x_5) (x4,x5)
每一组都是一个二维平面。
分别进行旋转:
R ( θ 0 ) R(\theta_0) R(θ0)
R ( θ 1 ) R(\theta_1) R(θ1)
R ( θ 2 ) R(\theta_2) R(θ2)
最终形成:
d / 2 d/2 d/2
个旋转平面。
8. 为什么需要不同频率
如果所有维度都用同一个角度:
θ \theta θ
表达能力有限。
因此:
RoPE 为每组维度设置不同频率:
ω i = 10000 − 2 i / d \omega_i= 10000^{-2i/d} ωi=10000−2i/d
其中:
- i i i 表示第几个二维平面
- d d d 为 hidden size
位置 p p p 的旋转角:
θ i = p ⋅ ω i \theta_i= p \cdot \omega_i θi=p⋅ωi
于是:
高维向量中同时存在:
- 高频旋转
- 中频旋转
- 低频旋转
类似于:
text
短距离特征
+
中距离特征
+
长距离特征
共同编码。
这是理解 RoPE 最关键的问题之一。
很多人第一次看到:
ω i = 10000 − 2 i / d \omega_i = 10000^{-2i/d} ωi=10000−2i/d
都会产生疑问:
后面的频率越来越低,旋转角度几乎不变,这些维度还有作用吗?
答案是:
不但有作用,而且这些低频维度恰恰是 RoPE 能够建模长距离依赖的关键。
下面从信号处理和位置编码的角度来理解。
8.1 先看频率公式到底意味着什么
RoPE 中:
θ i = p ⋅ ω i \theta_i = p \cdot \omega_i θi=p⋅ωi
其中:
ω i = 10000 − 2 i / d \omega_i = 10000^{-2i/d} ωi=10000−2i/d
假设:
python
d = 4096
那么:
第一个维度对:
i = 0 i=0 i=0
对应:
ω 0 = 1 \omega_0 = 1 ω0=1
第二个维度对:
i = 1 i=1 i=1
大约:
0.995 0.995 0.995
中间维度:
i = 1024 i=1024 i=1024
大约:
0.01 0.01 0.01
最后维度:
i = 2047 i=2047 i=2047
大约:
10 − 4 10^{-4} 10−4
甚至更小。
因此:
不同维度旋转速度完全不同。
8.2 高频维度在干什么
假设:
ω = 1 \omega=1 ω=1
位置:
text
0
1
2
3
4
旋转角:
0 1 2 3 4 rad 0 \ 1 \ 2 \ 3 \ 4 \ \ \text{rad} 0 1 2 3 4 rad
变化非常快。
相邻 token:
Δ θ = 1 \Delta\theta = 1 Δθ=1
差异明显。
因此高频维度特别擅长区分:
text
位置100
位置101
位置102
这种局部差异。
类似于:
text
显微镜
看细节。
8.3 高频维度的问题
如果只有高频:
例如:
ω = 1 \omega=1 ω=1
那么:
位置:
text
10000
10001
10002
对应角度:
10000 10001 10002 rad 10000\ 10001\ 10002\ \text{rad} 10000 10001 10002 rad
实际上已经绕圆转了无数圈。
因为:
2 π ≈ 6.28 2\pi \approx 6.28 2π≈6.28
所以:
text
10000rad
和:
text
10006.28rad
完全一样。
出现:
text
位置混叠(Aliasing)
问题。
模型无法区分:
text
位置100
位置10000
8.4 为什么需要低频维度
现在看:
ω = 10 − 4 \omega = 10^{-4} ω=10−4
位置:
text
100
角度:
0.01 0.01 0.01
位置:
text
10000
角度:
1 1 1
位置:
text
100000
角度:
10 10 10
变化非常慢。
因此:
即使很长距离:
text
10000 → 20000
仍然能观察到稳定差异。
低频维度实际上在记录:
text
大尺度位置信息
类似于:
text
望远镜
看整体结构。
8.5 为什么必须同时存在
如果只有高频:
text
局部精确
全局混乱
如果只有低频:
text
全局稳定
局部模糊
RoPE 实际上是在构造:
text
高频
+
中频
+
低频
的组合。
类似傅里叶变换:
f ( x ) = ∑ i A i sin ( ω i x ) f(x)= \sum_i A_i \sin(\omega_i x) f(x)=i∑Aisin(ωix)
一个复杂信号:
text
短周期变化
长周期变化
共同组成。
位置编码也是一样。
8.6 一个更直观的例子
想象有三个时钟。
时钟1(高频):
text
1分钟转一圈
时钟2(中频):
text
1小时转一圈
时钟3(低频):
text
1天转一圈
问:
text
现在是什么时间?
只看时钟1:
text
12:01
1:01
2:01
一样。
因为已经绕了很多圈。
只看时钟3:
text
12:01
12:02
12:03
又几乎一样。
三个时钟一起看:
text
唯一确定时间
RoPE 本质就是:
text
数千个不同转速的时钟
共同编码位置。
8.7 从 Attention 的角度看
回忆推导:
s c o r e = q T R ( ( m − n ) θ i ) k score= q^T R((m-n)\theta_i) k score=qTR((m−n)θi)k
对于某个频率:
θ i = ( m − n ) ω i \theta_i= (m-n)\omega_i θi=(m−n)ωi
如果:
∣ m − n ∣ = 1 |m-n|=1 ∣m−n∣=1
高频维度响应最明显。
如果:
∣ m − n ∣ = 10000 |m-n|=10000 ∣m−n∣=10000
高频维度已经振荡无数次。
信息接近随机。
此时:
低频维度仍保持平滑变化。
因此:
对于不同距离:
| 距离 | 主要工作的频率 |
|---|---|
| 1~10 | 高频 |
| 10~100 | 中频 |
| 100~1000 | 低频 |
| 1000+ | 超低频 |
这实际上形成了:
text
多尺度距离感知
(Multi-scale Distance Modeling)
8.7 为什么频率是指数衰减
论文没有严格证明:
10000 − 2 i / d 10000^{-2i/d} 10000−2i/d
一定最优。
它继承自 Transformer 的 Sin/Cos 编码。
原因是:
指数分布能够均匀覆盖:
text
1
0.1
0.01
0.001
0.0001
多个数量级。
如果改成线性:
1
0.9
0.8
...
大量频率会集中在高频区域。
远距离信息表达能力下降。
指数分布能同时覆盖:
text
短距离
中距离
长距离
超长距离
8.8 为什么后来会出现 NTK、YaRN、LongRoPE
当上下文从:
text
4K
扩展到:
text
128K
时。
即使最低频率:
10 − 4 10^{-4} 10−4
也开始不够用了。
因为:
text
128000 × 10^-4 ≈ 12.8
已经转了很多角度。
于是出现:
- NTK Scaling
- Position Interpolation
- YaRN
- LongRoPE
本质都是:
让低频部分变得更低频。
即:
text
旋转更慢
从而支撑:
text
32K
64K
128K
1M
上下文。
8.8 RoPE中频率的总结
RoPE 中后面的维度虽然频率越来越低,但它们并不是"没用的维度"。
恰恰相反:
- 高频维度负责区分相邻 Token;
- 中频维度负责建模中距离关系;
- 低频维度负责保持长距离位置信息;
- 所有频率共同构成一种类似傅里叶基函数的多尺度位置表示。
因此 RoPE 可以理解为:
用大量不同转速的"位置时钟"共同描述 Token 的位置,而低频时钟正是模型理解长上下文的关键。
9. 复数形式理解 RoPE
RoPE 最优雅的推导来自复数。
定义:
z = x 1 + i x 2 z=x_1+ix_2 z=x1+ix2
旋转:
z ′ = z e i θ z'= ze^{i\theta} z′=zeiθ
因为:
e i θ = cos θ + i sin θ e^{i\theta}= \cos\theta+i\sin\theta eiθ=cosθ+isinθ
展开:
z ′ = ( x 1 + i x 2 ) ( cos θ + i sin θ ) z'= (x_1+ix_2) (\cos\theta+i\sin\theta) z′=(x1+ix2)(cosθ+isinθ)
得到:
( x 1 cos θ − x 2 sin θ ) + i ( x 1 sin θ + x 2 cos θ ) (x_1\cos\theta-x_2\sin\theta) + i(x_1\sin\theta+x_2\cos\theta) (x1cosθ−x2sinθ)+i(x1sinθ+x2cosθ)
这与二维旋转矩阵完全一致。
因此:
RoPE 本质上可以看成:
在复数空间对 Query 和 Key 乘以位置相关的相位因子。
10. 为什么 Llama 全面采用 RoPE
Llama、Qwen、DeepSeek、Mistral 几乎都使用 RoPE。
原因主要有四个。
1. 零额外参数
无需学习位置向量。
参数量增加:
0 0 0
2. 天然支持相对位置
Attention 中自动出现:
n − m n-m n−m
无需额外设计 Relative Position Bias。
3. 长文本效果优秀
不同频率旋转能够同时表达:
- 短距离关系
- 长距离关系
4. 容易扩展上下文长度
后续大量工作都建立在 RoPE 之上:
- NTK RoPE
- Linear Scaling
- YaRN
- LongRoPE
实现:
text
4K
→ 32K
→ 128K
→ 1M Context
的超长上下文。
11. 总结
RoPE 的核心思想可以概括为一句话:
不再给 Token 添加位置向量,而是根据位置对 Query 和 Key 进行旋转。
对于位置 m m m 和 n n n:
q ~ m = R ( m θ ) q m \tilde q_m= R(m\theta)q_m q~m=R(mθ)qm
k ~ n = R ( n θ ) k n \tilde k_n= R(n\theta)k_n k~n=R(nθ)kn
Attention Score:
q ~ m T k ~ n = q m T R ( ( n − m ) θ ) k n \tilde q_m^T\tilde k_n= q_m^T R((n-m)\theta) k_n q~mTk~n=qmTR((n−m)θ)kn
最终自然得到:
Attention ∝ ( n − m ) \text{Attention} \propto (n-m) Attention∝(n−m)
即:
Attention 直接感知相对位置关系。
这使得 RoPE 同时具备:
- 绝对位置编码能力
- 相对位置编码能力
- 零参数开销
- 优秀的长度外推能力
因此成为现代大语言模型位置编码方案的事实标准。