Transformer 的核心计算是 Self-Attention。它擅长在序列内部建立全局依赖,但注意力本身并不知道 token 出现在第几个位置。如果不额外注入位置信息,模型很难区分“我喜欢你”和“你喜欢我”这类由顺序决定语义的句子。
本文先从注意力的置换等变性出发说明位置编码的必要性,再梳理两类经典绝对位置编码——可学习位置向量与 Sinusoidal 位置编码,最后分析它们的局限,并引出相对位置编码与 RoPE 的发展动机。
一、位置编码的必要性
1. 注意力形式
给定输入序列表示 ,Self-Attention 首先通过线性变换得到:
然后计算注意力输出:
其中第 个 token 与第 个 token 的交互,主要由 决定。
也就是说,没有位置编码时,attention score 只依赖 token 内容向量之间的相似性。
2. 置换等变
如果只看 token embedding,Self-Attention 并不会天然知道 token 的顺序。假设对输入序列做一个置换矩阵 ,得到 ,则:
注意力矩阵变为:
输出也会相应变为:
这说明 Self-Attention 对输入是置换等变的(Equivariant):输入顺序被置换,注意力矩阵的行列和输出也按同一置换移动。注意力权重仍可随 token 内容而不同;关键在于,没有位置编码时,置换输入只会同步置换内容关系和输出,模型无法从中识别排列顺序本身。
3. 位置注入
因此需要给每个 token 注入一个位置相关的向量 ,使输入从原来的 token embedding 变为:
其中 表示第 个位置的位置编码。加入位置编码后,即使两个 token 的内容向量相同,只要它们位于不同位置,最终输入向量也会不同:
这样一来,后续计算得到的 不再只依赖 token 内容,也依赖 token 所在位置:
由于位置向量 在输入层直接加到 上,发生在 投影之前。意味着 三者都是由同一个 变换而来,位置信息会无差别地混入 ,模型无法只让 带位置信息而不影响 。
注意:RoPE 旋转位置编码 只旋转 ,不改动 。
位置编码的作用不是替代 token 内容,而是让 attention 的相似性计算从“只看内容”变成“同时看内容与位置”,但代价是 Q、K、V 会被同等程度地卷入位置信息,没有选择性。
把这个思路推广到整段长度为 的序列,就得到了绝对位置编码(Absolute Positional Encoding)——直接为每一个绝对位置分配一个向量,堆叠成位置矩阵:
token embedding 告诉模型“这个词是什么”,position embedding 告诉模型“这个词在哪里”。
下面分别介绍两种经典实现:可学习位置向量与 Sinusoidal 位置编码。
二、可学习绝对位置编码
1. 参数形式
最直接的方法是把位置编码当作模型参数学习。设最大上下文长度为 ,隐藏维度为 ,则定义一个可学习矩阵:
第 个位置直接取矩阵第 行:
模型训练过程中, 会和 token embedding、attention 参数一起通过反向传播更新。
2. 特点
- 表达能力强:每个位置都有独立参数,模型可以自由学习位置模式。
- 实现简单:本质上就是一个 embedding table。
- 适合固定长度训练:当训练长度和推理长度基本一致时,可学习位置编码通常足够有效。
3. 外推问题
可学习位置编码的主要问题是长度外推能力弱。若训练时最大长度为 ,则模型只学习了位置 到 的向量。
当推理长度超过 时,位置 没有对应的已训练参数。即使强行扩展表格,新位置向量也没有经过训练,模型未必知道如何使用。
可学习绝对位置编码对训练长度内的位置记忆能力强,但对训练长度外的位置泛化能力较弱。
三、Sinusoidal 位置编码
1. 公式
原始 Transformer 使用的是固定的 Sinusoidal 位置编码。对于位置 和维度索引 ,定义:
其中:
- :token 在序列中的绝对位置;
- :模型隐藏维度;
- 和 :一组相邻的偶数/奇数维度;
- :控制不同维度的波长。
2. 频率
将公式改写为:
其中:
不同维度对应不同频率 :
- 低维度 较小, 较大,变化更快;
- 高维度 较大, 较小,变化更慢。
将纵轴设为 token 位置、横轴设为维度组,可以同时观察所有频率随位置的变化。由于 按指数规律衰减,横轴实际表示维度组 ,上方标出对应的频率方向:
左侧高频列随 token 位置快速交替,适合区分局部位置;右侧低频列变化缓慢,提供更大尺度的位置信号。
3. 实现
import torch
def sinusoidal_position_embedding(seq_len: int, dim: int, base: float = 10000.0):
position = torch.arange(seq_len).float().unsqueeze(1) # [seq_len, 1]
index = torch.arange(0, dim, 2).float() # [dim / 2]
inv_freq = base ** (-index / dim) # [dim / 2]
angles = position * inv_freq # [seq_len, dim / 2]
pe = torch.zeros(seq_len, dim)
pe[:, 0::2] = torch.sin(angles)
pe[:, 1::2] = torch.cos(angles)
return pe
4. 正弦余弦性质
周期表示:对于一个固定频率 ,位置 被映射到:
这可以理解为单位圆上的一个点。随着 增大,该点绕单位圆旋转。因此,每一组 sin/cos 维度都可以看成一个二维旋转平面。
位移线性化:Sinusoidal 位置编码还有一个重要性质:位置 的编码可以由位置 的编码线性表示。
根据三角恒等式:
写成矩阵形式:
这个矩阵只依赖相对位移 ,不依赖绝对位置 。
即 Sinusoidal 位置编码虽然形式上是绝对位置编码,但它具备表达相对位移的线性结构。
这个性质是理解 RoPE 的前置直觉。Sinusoidal 位置编码把位置写入输入向量,而 RoPE 则更进一步:直接把 query 和 key 按位置旋转,使相对位置自然进入注意力点积,具体可见 RoPE 旋转位置编码。
四、绝对位置编码的局限
1. 加法混合
绝对位置编码通常采用:
这种方式简单有效,但也带来一个问题:位置信息和内容信息在输入层被混合, 会无差别地同时带上位置信息(详见「一」),后续层需要自己学习如何区分二者。
2. 相对距离
很多语言现象更依赖相对距离,而不是绝对位置。例如:
- 当前词与前一个词的关系;
- 主语和谓语之间相隔多少 token;
- 局部短语内部的相邻依赖。
绝对位置编码提供的是“第几个位置”,而不是“两个位置相隔多远”。模型可以从绝对位置中间接推断相对距离,但这不是显式结构。
3. 长度外推
对于可学习位置编码,超过训练长度的位置没有训练过。
对于 Sinusoidal 位置编码,虽然任意长度都能计算出位置向量,但模型训练时只见过有限范围内的位置组合。推理时出现更长位置,注意力分布仍可能发生明显漂移。
核心问题:能为更长位置生成编码,不等于模型学会了如何使用更长位置。
五、总结
绝对位置编码解决了 Transformer 不感知顺序的问题。可学习位置编码简单直接,适合固定长度场景;Sinusoidal 位置编码无需训练,利用多频率 sin/cos 波形表示位置,并具备一定的相对位移线性结构。
但绝对位置编码用加法把位置信息和内容信息混在一起, 无差别地带上位置信息,重点也停留在“每个 token 位于第几个位置”,而不是“两个 token 之间相隔多远”。这也是后来相对位置编码、RoPE 等方法继续发展的重要动机。