-
假设序列长度为 L、模型维度为 dmodel,输入嵌入可表示为:
InputEmbedding[i]=TokenEmbedding[i]+PositionalEncoding[i]
-
Transformer 没有循环或卷积结构,所以无法天然知道 token 的顺序,因此需要给每个 token 添加位置信息
-
位置编码大体上分为两种方法:
- 绝对位置编码:通过给序列中的每个 token 分配 “某个固定位置的向量”,包括正余弦位置编码(Transformers 模型)、可学习位置编码(BERT 模型)、旋转位置编码(LlaMa 模型)
- 相对位置编码:显式地表示 token 之间 “距离” 的信息,而不是它们的绝对位置
-
用整型值标记位置
- 一种自然而然的想法是,给第一个 token 标记 1,给第二个 token 标记 2...,以此类推
- 这种方法产生了以下几个主要问题
- 模型可能遇见比训练时所用的序列更长的序列。不利于模型的泛化
- 模型的位置表示是无界的;随着序列长度的增加,位置值会越来越大
-
用 [0,1] 范围标记位置
- 为了解决整型值带来的问题,可以考虑将位置值的范围限制在 [0, 1] 之内,其中,0 表示第一个 token,1 表示最后一个 token
- 比如有 3 个 token,那么位置信息就表示成 [0, 0.5, 1];若有四个 token,位置信息就表示成 [0, 0.33, 0.69, 1]
- 但这样产生的问题是,当序列长度不同时,token 间的相对距离是不一样的;例如在序列长度为 3 时,token 间的相对距离为 0.5;在序列长度为 4 时,token 间的相对距离就变为 0.33
-
因此,需要这样一种位置表示方式,满足:
- 它能用来表示一个 token 在序列中的绝对位置
- 在序列长度不同的情况下,不同序列中 token 的相对位置 / 距离也要保持一致
- 可以用来表示模型在训练过程中从来没有看到过的句子长度
-
考虑到位置信息作用在 input embedding 上,因此比起用单一的值,更好的方案是用一个和 input embedding 维度一样的向量来表示位置
- 很容易想到可以使用二进制编码
- 但是这样编码出来的位置向量,处于一个离散的空间中,不同位置间的变化是不连续的
- 如果能把离散空间转换到连续空间,那么就能解决位置距离不连续的问题
- 同时,不仅能用位置向量表示整型,还可以用位置向量来表示浮点型
-
通过以上分析,需要一个有界又连续的函数,最简单的正弦函数可以满足这个条件
-
考虑将位置向量中的每个元素都用一个 sin 函数来表示,那么第 t 个 token 的位置向量可以表示为
PEt=[sin(201t),sin(211t),…,sin(2i−11t),…,sin(2dmodel−11t)]
-
显然,维度索引越大,对应的值随着 t 的变化程度越小
-
由于 sin 的周期函数,从不同的 t 的角度来看,如果函数的频率偏大,波长偏短,那么不同 t 下的位置向量可能重合,为了避免这种情况,可以将这个频率设置为很小的值
PEt=[sin(w0t),sin(w1t),…,sin(wi−1t),…,sin(wdmodel−1t)],wi=10000i/(dmodel−1)1
-
通过 sin 函数,实现了
- 每个 token 的向量唯一(每个 sin 函数的频率足够小)
- 位置向量的值是有界的,且位于连续空间中;模型在处理位置向量时更容易泛化,即更好处理长度和训练数据分布不一致的序列(sin 函数本身的性质)
-
现在有个新的需求,不同的位置向量是可以通过线性变换得到的,这样就可以表示一个 token 的相对位置
PEt+Δt=TΔt∗PEt
-
这里的 T 就是一个线性变换矩阵
-
将 t 想象为一个角度,那么 Δt 就是其旋转的角度,则有
(sin(t+Δt)cos(t+Δt))=(cosΔt−sinΔtsinΔtcosΔt)(sintcost)
-
由此,可以修改原来均为 sin 函数的位置编码,让位置两两一组,分别用 sin 和 cos 函数来表示
PEt=[sin(w0t),cos(w0t),sin(w1t),cos(w1t),…,sin(w2dmodel−1t),cos(w2dmodel−1t)]
-
从而得到一个线性变换公式
PEt+△t=T△t∗PEt=[cos(w0△t)−sin(w0△t)sin(w0△t)cos(w0△t)]...0.........0...[cos(w2dmodel−1△t)−sin(w2dmodel−1△t)sin(w2dmodel−1△t)cos(w2dmodel−1△t)]sin(w0t)cos(w0t)...sin(w2dmodel−1t)cos(w2dmodel−1t)=sin(w0(t+△t))cos(w0(t+△t))...sin(w2dmodel−1(t+△t))cos(w2dmodel−1(t+△t))
-
正弦 / 余弦位置编码(Sinusoidal Positional Encoding)最初由 Transformer 模型提出:
PE(pos,2i)PE(pos,2i+1)=sin(100002i/dmodelpos)=cos(100002i/dmodelpos)
-
pos 为 token 在序列中的位置(0,1,2,...,L-1)
-
i 为向量的维度索引(0,1,2,...,d_model/2 -1)
-
输入:序列长度 L、嵌入维度 d_model
-
输出:形状为 [L, d_model] 的位置编码矩阵,可以直接加到 token 嵌入上
-
正余弦位置编码的性质
-
当位置编码随着输入被送入 attention 层时,其映射方式为
PEtTWQTWKPEt+k
-
其推导如下
QKT=(EWQ+PEWQ)(EWK+PEWK)T=(EWQ)(EWK)T+(EWQ)(PEWK)T+(PEWQ)(EWK)T+(PEWQ)(PEWK)T
-
其中最后一项完全由位置编码确定
-
关注两个特定位置 t 和 t+k 之间的注意力分数,则有
(PEtWQ)(PEt+kWK)T=PEtWQWKTPEt+kT=PEtTWQTWKPEt+k
-
由此可见,位置编码在进入 attention 层后,内积的距离意识的模式遭到了破坏
-
分析
- 确定性
- 与需要通过训练获得的可学习位置编码不同,正余弦位置编码由预先定义的固定函数生成,因此是确定性的
- 对于任意位置
pos 和维度索引 i,其取值恒定,不依赖训练过程,也不引入额外的可学习参数
- 有界性
- 正弦和余弦函数的取值范围限制在 [−1,1] 内,在与词嵌入相加时,不会显著改变组合后表示的整体尺度
- 这种有界特性有助于保持表示的数值稳定性,从而使训练过程更加平稳
- 平滑性
- 正余弦函数随位置连续、平滑变化,因此相邻位置 pos 与 pos+1 的位置编码彼此相似
- 这一性质与自然语言中相邻词语往往具有强上下文相关性的直觉相一致
- 外推能力
- 由于正余弦位置编码由固定函数定义,而非从有限长度的训练数据中学习,它可以为任意位置生成编码
- 因此,在处理超过训练序列长度的输入时,位置编码本身不会失效或产生未定义表示,相较于学习型位置嵌入具备更好的外推性(尽管模型整体性能仍可能受其他因素限制)
-
尽管具备确定性和可外推的形式定义,正余弦位置编码在实践中并不能可靠地从训练序列长度泛化到显著更长的未见长度:
- 高频维度的周期性问题
- 正余弦位置编码由一组不同频率的正弦和余弦函数组成,其中高频分量的周期较短
- 当位置 pos 远超训练范围时,这些高频维度会发生周期性重复,导致不同位置之间出现相似甚至重叠的相位表示,从而削弱位置区分能力
- 语义解读能力受训练范围限制
- 模型在训练过程中仅在 [0,Ltrain] 的位置范围内接触到这些正余弦信号
- 因此,模型实际学到的是如何在该有限区间内解读不同维度的相位组合,例如哪些频率对应 “近距离” 关系,哪些反映 “远距离” 依赖,哪些维度刻画整体结构上的衰减模式
- 当位置超出训练长度时,虽然位置编码函数本身仍然定义良好,但这些相位组合落入了模型从未见过的分布区域,导致已学到的解读方式不再可靠
-
在正余弦位置编码中提到
(sinθ(t+Δt)cosθ(t+Δt))=(cosθΔt−sinθΔtsinθΔtcosθΔt)∗(sinθtcosθt)=RΔt∗(sinθtcosθt)
-
由于 RΔt 是一个表示顺时针旋转的正交矩阵(不改变向量的模长,只改变方向),则 PEt+Δt 其实就是以 PEt 为基础,顺时针旋转 θ∗Δt 角度而来,因此有
PEtT∗PEt+Δt=∥PEt∥∗∥PEt+Δt∥∗cos(θΔt)
-
固定某个 t 不变,慢慢增大 Δt 时,上式变小,因此相距较远的两个位置编码的内积越小,即内积可以用于反馈两个位置向量在绝对位置上的远近
-
为了避免周期过小,导致距离较远的位置编码反而内积接近,可以让每次位置变动时的转动角度小一些,也即把 θ 设置得小一些
-
上文推导得到,经过 attention 层后,位置编码真正起作用的是引入了线性变化后的 PEtTWQTWKPEt+k,而引入了这个线性变化后,会极大的破坏位置编码设计之初的各种优良性质
-
自然而然地,可以直接在 attention 层融入位置信息,也就是直接把位置编码作用于 qtTkt+Δt,下面用 m 和 n 表示两个位置
-
在计算 qmTkn 时,这个相关性分数就是两个特征向量之间的乘积,在一定程度上衡量了两个向量之间的相似性,那么希望可以直接将位置编码的信息直接引入其中,也即根据 |n-m| 的结果,给这个内积计算一定的惩罚,当 |n-m| 较小时,拉近两个向量的距离;否则拉远两者的距离
-
假如将 qm 逆时针旋转 m 度,kn 逆时针旋转 n 度,那么当 m 和 n 差距较大时,两个向量的角度也变大,其内积随之降低
-
这里同样需要引入参数 θ,通过拉长三角函数周期的方式确保不同位置的向量不会发生碰撞,由此定义了一个逆时针正交旋转矩阵
Ri=(cosiθsiniθ−siniθcosiθ)
-
其中,i 表示绝对位置,将上式作用于 attention 计算,得到
(Rmqm)T(Rnkn)=[(cosmθsinmθ−sinmθcosmθ)∗(q0q1)]T[(cosnθsinnθ−sinnθcosnθ)∗(k0k1)]=(q0q1)∗(cos((n−m)θ)sin((n−m)θ)−sin((n−m)θ)cos((n−m)θ))∗(k0k1)=qmTRn−mkn
-
可以发现
- Rmqm,Rnkm:两者分别赋予 qm,km 绝对位置信息
- Rn−m:绝对位置信息相乘的结果拥有了相对位置的概念
-
前述讨论均在二维特征空间下进行,那么到了高维特征空间,位置编码如何设计,也即(其中 d 就是 hidden_size)
qm=q0q1q2q3⋯qd−2qd−1
-
过小的 θ 会导致旋转角度十分微弱,不同位置的向量几乎重合,那么应该如何设计高维位置向量的每一个维度的值?
-
可以将 qm 中的维度两两为一组,这样每一组都可以视为一个旋转速度不一样的指针,因此可以用 d//2 个指针来表示 qm 的位置向量,即
Rmq=[cos(mθ0)sin(mθ0)−sin(mθ0)cos(mθ0)]⋯0⋯⋯⋯0⋯[cos(mθd/2−1)sin(mθd/2−1)−sin(mθd/2−1)cos(mθd/2−1)]q0q1⋯qd−2qd−1
-
由于 Rm 是一个稀疏矩阵,因此经常拆分为以下算式
q0q1q2q3⋯qd−2qd−1⊗cosmθ0cosmθ0cosmθ1cosmθ1⋯cosmθd/2−1cosmθd/2−1+−q1q0−q3q2⋯−qd−1qd−2⊗sinmθ0sinmθ0sinmθ1sinmθ1⋯sinmθd/2−1sinmθd/2−1
-
为了满足不同维度索引的旋转特性,又不能让 θ 太大,可以设
θi=10000−2i/d, i=0,1,2,…,d/2−1
-
其中,10000 这个数决定了 θ 的大小,称之为基数(base)
- 较大的 base 使得 θ 较小,相当于加大了分量的周期,使其变得更宽更平缓,此时训练范围内的可容忍位置距离都不会相位重合
- 如果用 “大基数 + 长文本” 训练模型,那么每个圆盘的旋转速度都变慢,这样训练完后大部分圆盘都没有转完一圈,位置编码信息训练不到位
- 如果用 “小基数 + 短数据” 训练模型,虽然有更多的圆盘旋转过一周,但并不是圆盘上的每个点都能训练到
- 在研究位置编码的外推性或者研究基数选择对外推性的影响时,可以从以上角度进行思考
-
目前训练长文本的一个常用方法:
- 先用 “小基数 + 短数据” 做训练(让每个圆盘都尽量转满一圈)
- 再用 “大基数 + 长文本” 做微调(弥补圆盘上的空隙)
-
当已经有一个训练后的模型,希望继续在更长的文本上继续预训练 / 推理时,希望能够
- 尽量不要便宜已经训练过的圆周范围,即尽可能利用已经训练好的位置相关信息
- 尽量学到比 pretrain 更多的位置信息
-
显然,当从位置 50 变动到 10000 时
- 靠前的圆盘
- 尽量让它学习到【绝对位置】信息,尝试突破 pretrain 看过的圆周部分(外推)
- 对应长距离依赖(比如段落间、上下文的关联),对缩放不敏感,适合外推(Extrapolation)(不压缩频率,保留长距离旋转信息)
- 靠后的圆盘
- 尽量让它学习到【相对位置】信息,保持在 pretrain 看过的圆周部分,只做精细角度的训练(内插)
- 对应短距离依赖(比如词内、相邻词的关联),对缩放更敏感,适合插值(Interpolation)(压缩频率,适配更长序列)
-
最后一个圆盘的推导
-
假设 pretrain 阶段的训练文本长度为 Spre,最后一个圆盘的转动角度为 θd//2−1,则绕着圆盘转动一周会经过 θd//2−12π 个 tokens,那么 pretrain 阶段转过的周数为:
2πSpre∗θd//2−1
-
假设 continue-pretrain/inference 阶段的文本长度为 Spost,理想的圆盘转动角度为 θd//2−1∗,那么希望:
2πSpre∗θd//2−1=2πSpost∗θd//2−1∗
-
求解得:
θd//2−1∗=SpostSpre∗θd//2−1
-
因此,对于最后一个圆盘,只需要对原始的旋转角度乘以缩放因子 SpostSpre 即可满足严格限制在预训练学习到的位置范围内
-
在实际操作时,一般通过控制 base 来实现这个需求,即令下式在 i=d//2−1 的条件下成立即可,其中 λ 即为 base 的缩放因子
(10000λ)2i/d1=SpostSpre∗100002i/d1
-
从而得到
λ=(SpreSpost)d−2d
-
事实上,将这个固定的 λ 值带入到前面的圆盘的基数中,也均可以实现位置的外推;同时受到 i 的影响,越往前的圆盘,超出 pretrain 训练过的位置越多

-
该设计使得:
-
对于任意一对位置 (i,j),ALiBi 只关注它们的相对距离 ∣i−j∣,并对注意力得分施加线性、无参数增长的惩罚
-
具体而言,注意力分数会额外减去一项与距离成正比的偏置:
Δij=m⋅∣i−j∣
- 其中 m 为固定斜率,不随序列长度增长
- 因此在任意长度的序列中,例如距离为 5000 的位置对,惩罚始终为 5000×m,与训练时的最大上下文无关
- 这一机制使模型在长序列推理时仍能保持稳定表现
- 同时,模型不需要额外训练位置编码,偏置直接作用于 attention 分数,使得远距离 token 的位置信息依然可区分
- 因此,Alibi 在长序列外推时表现比 RoPE 更稳定
-
实际设计中,ALiBi 为每个注意力头分配不同的线性斜率(H 是注意力头个数):
mh=2h/H1
-
低序号头 (h 小):衰减快,偏向捕捉局部依赖
-
高序号头 (h 大):衰减慢,偏向捕捉长距离依赖
-
这种设计使多头注意力在序列长度上天然分工,提高模型对不同范围依赖的建模能力
1. RoPE 的核心目标
2. 用复数形式推导
3. 分解模长和长度
-
得到两组条件
{Rf(q,m)Rf(k,n)=Rg(q,k,m−n)Θf(q,m)−Θf(k,n)=Θg(q,k,m−n)
-
对模长:当 m=n 时有
Rf(q,m)Rf(k,m)=∥q∥∥k∥ ⇒ Rf(q,m)=∥q∥
-
对角度,说明位置相关性仅体现在角度差:
Θf(q,m)−Θf(k,m)=Θ(q)−Θ(k)
4. 角度的等差结构
-
若位置递增的角度增量为常数 θ,则
φ(m)=mθ.
-
因此得到复数形式的旋转位置编码
f(q,m)=q,eimθf(k,n)=k,einθ
5. 转为 2D 旋转矩阵形式
- 对二维向量 (q0,q1),旋转 mθ 等价于
f(q,m)=(cos(mθ)sin(mθ)−sin(mθ)cos(mθ))(q0 q1).
6. 注意力分数依赖相对位置
7. 直观理解
- 将每个 token 的某个维度对映成二维子向量
- 每个位置对该子向量施加固定角度增量
- 注意力内积的有效位置信息来自旋转差,即 (m−n)
- 高频维度捕获局部依赖;低频维度捕获长程依赖
-
RoPE(Rotary Position Embedding)把每个 token 的表示按维度两两分组,当成复数:
x=(x1,x2,x3,x4,…)⇒(x1+ix2,x3+ix4,…)
-
对第 p 个位置,引入一个角度 θp,做旋转:
xp′=xp⋅eiθp
-
展开成实数就是:
x2k′x2k+1′=x2kcosθp−x2k+1sinθp=x2ksinθp+x2k+1cosθp
-
关键在 attention 的内积:
⟨qp′,kq′⟩
-
代入旋转:
qp′=qp⋅eiθpkq′=kq⋅eiθq
-
内积变成:
⟨qp′,kq′⟩=⟨qp,kq⟩⋅ei(θp−θq)
-
attention 的结果只依赖 相对位置差 p−q,而不是绝对位置 —— 这就是 RoPE 能编码相对位置的本质