Skip to main content

位置编码

如何理解LLM sin cos位置编码中,依据三角函数的基本性质,可以得知pos+kpos+k个位置编码是第pospos个位置编码的线性组合,这就意味着位置编码中蕴涵着单词之间的距离信息

理解这个问题的关键在于三角函数的和角公式。让我们一步步拆解:

1. 三角函数位置编码公式

对于 Transformer 中的位置编码,第 pos 个位置、第 i 个维度的编码为:

PE(pos,2i)=sin(pos100002i/d)PE(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d}}\right) PE(pos,2i+1)=cos(pos100002i/d)PE(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d}}\right)

其中 d 是模型维度。

2. 核心数学性质:和角公式

三角函数的关键性质

sin(α+β)=sinαcosβ+cosαsinβ\sin(\alpha + \beta) = \sin\alpha\cos\beta + \cos\alpha\sin\beta cos(α+β)=cosαcosβsinαsinβ\cos(\alpha + \beta) = \cos\alpha\cos\beta - \sin\alpha\sin\beta

3. 推导线性组合关系

令:

  • α = pos / 10000^{2i/d}
  • β = k / 10000^{2i/d}

那么:

PE(pos+k,2i)=sin(α+β)=sinαcosβ+cosαsinβ=PE(pos,2i)cosβ+PE(pos,2i+1)sinβPE(pos+k, 2i) = \sin(\alpha + \beta) = \sin\alpha\cos\beta + \cos\alpha\sin\beta = PE(pos, 2i) \cdot \cos\beta + PE(pos, 2i+1) \cdot \sin\beta PE(pos+k,2i+1)=cos(α+β)=cosαcosβsinαsinβ=PE(pos,2i+1)cosβPE(pos,2i)sinβPE(pos+k, 2i+1) = \cos(\alpha + \beta) = \cos\alpha\cos\beta - \sin\alpha\sin\beta = PE(pos, 2i+1) \cdot \cos\beta - PE(pos, 2i) \cdot \sin\beta

4. 矩阵形式表示

将这两个公式写成矩阵形式:

[PE(pos+k,2i)PE(pos+k,2i+1)]=[cosβsinβsinβcosβ][PE(pos,2i)PE(pos,2i+1)]\begin{bmatrix} PE(pos+k, 2i) \\ PE(pos+k, 2i+1) \end{bmatrix} = \begin{bmatrix} \cos\beta & \sin\beta \\ -\sin\beta & \cos\beta \end{bmatrix} \cdot \begin{bmatrix} PE(pos, 2i) \\ PE(pos, 2i+1) \end{bmatrix}

这就是一个旋转矩阵!

5. 物理意义解读

5.1 距离信息的编码

  • β 只依赖于 相对位置 k维度 i
  • pos+k 的位置编码可以由 pos 的位置编码线性变换得到
  • 变换矩阵的系数 (cosβ, sinβ) 只与相对距离 k 有关

这意味着:模型可以学习到相对位置关系,而不仅仅是绝对位置。

5.2 实际例子

假设我们想计算位置 10 和位置 13 之间的关系:

  • 相对距离 k = 3
  • 对于每个维度 i,都有一个旋转角度 βi=3/100002i/dβ_i = 3 / 10000^{2i/d}
  • 位置 13 的编码 = 旋转矩阵 βiβ_i × 位置 10 的编码

5.3 为什么这是"线性组合"

因为:

# pos+k 的编码可以由 pos 的编码线性表示
PE_pos_k = a * PE_pos_even + b * PE_pos_odd

其中 a, b 是常数(对固定 k 和 i 是固定的)。

6. 可视化理解

对于固定的维度 i:

  • 每个位置编码是单位圆上的一个点
  • 位置 pos(sin(ωpos),cos(ωpos))pos → (sin(ω·pos), cos(ω·pos)),其中 ω=1/100002i/dω = 1/10000^{2i/d}
  • 相对距离 k 对应旋转角度 ωkω·k
  • 所有位置都在同一个圆上,只是角度不同

不同维度的不同"频率":

# 低频维度(i 小)
ω_small = 1/10000^{2*0/512}1.0 # 缓慢变化

# 高频维度(i 大)
ω_large = 1/10000^{2*255/512}1/100000.0001 # 快速振荡

7. 在注意力机制中的作用

在注意力计算中,QKTQ·K^T会包含位置编码的信息:

QposKpos+kT=(ContentVector+PosEncodepos)(ContentVector+PosEncodepos+k)TQ_{pos}·K_{pos+k}^T = ( ContentVector + PosEncode_{pos})·(ContentVector + PosEncode_{pos+k})^T

由于 位置编码 pos+k_{pos+k} 是 位置编码 pos_{pos}的线性函数,模型可以学会:

  1. 相对位置模式:如"动词后面常跟名词"(距离1)
  2. 句法结构:如主谓一致(固定距离关系)
  3. 局部依赖:相邻词有强关联

8. 与可学习位置编码的对比

特性三角函数编码可学习编码
外推性✅ 好(可计算任意位置)❌ 差(只训练过固定长度)
相对位置✅ 内置(三角公式)❌ 需要显式学习
距离信息✅ 明确编码❌ 隐含在参数中
长序列✅ 支持(周期性)❌ 可能过拟合

9. 现代变体:RoPE(旋转位置编码)

RoPE 直接将这个思想扩展到复数域:

qpos=qeiωposkpos=keiωposq_{pos} = q \cdot e^{i\omega pos} k_{pos} = k \cdot e^{i\omega pos}

这样 Q·K 内积自然包含相对位置信息:

qposkpos+k=(qk)eiωkq_{pos}·k_{pos+k} = (q·k) \cdot e^{i\omega k}

相对位置 k 只影响相位,不改变模长。

10. 实际验证代码

import numpy as np

def sinusoidal_position_encoding(pos, d_model=512):
"""计算sinusoidal位置编码"""
position = np.arange(pos)[:, np.newaxis]
div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000.0) / d_model))

pe = np.zeros((pos, d_model))
pe[:, 0::2] = np.sin(position * div_term) # 偶数维度
pe[:, 1::2] = np.cos(position * div_term) # 奇数维度
return pe

# 验证线性关系
d_model = 512
pos = 10
k = 3
i = 10 # 看第10个维度对(实际是第20、21维)

pe = sinusoidal_position_encoding(pos + k + 1, d_model)

# 提取两个维度
dim_even = 2*i
dim_odd = 2*i + 1

# 计算β
div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000.0) / d_model))
beta = k * div_term[i]

# 验证公式
pe_pos_even = pe[pos, dim_even]
pe_pos_odd = pe[pos, dim_odd]
pe_pos_k_even = pe[pos + k, dim_even]
pe_pos_k_odd = pe[pos + k, dim_odd]

# 根据公式计算
calc_even = pe_pos_even * np.cos(beta) + pe_pos_odd * np.sin(beta)
calc_odd = pe_pos_odd * np.cos(beta) - pe_pos_even * np.sin(beta)

print(f"实际值: [{pe_pos_k_even:.6f}, {pe_pos_k_odd:.6f}]")
print(f"计算值: [{calc_even:.6f}, {calc_odd:.6f}]")
print(f"误差: [{abs(pe_pos_k_even - calc_even):.6f}, {abs(pe_pos_k_odd - calc_odd):.6f}]")

总结

核心洞见:三角函数位置编码通过和角公式,使得相对位置关系被编码为线性变换。这意味着:

  1. 位置 pos+k 的编码 = 线性矩阵 × 位置 pos 的编码
  2. 变换矩阵只依赖于相对距离 k,与绝对位置 pos 无关
  3. 模型可以学习到"距离为k的两个词之间的关系"
  4. 这种编码具有外推性,可以处理比训练时更长的序列

这正是为什么原始 Transformer 论文说这种编码可以让模型"轻松学习到相对位置信息"。后续的 RoPE、ALiBi 等位置编码方法都是基于类似的洞见发展而来。