RNN 天生按时间步串行处理,所以自带前后顺序感;但 Transformer 为了并行,把所有 token 一股脑扔进了矩阵。这时出现了一个诡异的 Bug:如果你把「猫追狗」打乱成「狗追猫」,自注意力算出的结果居然完全相同!为了让模型感知语序,作者给每个 token 发了一张神奇的「正弦波座位号」——位置编码(Positional Encoding)。
位置编码的设计哲学,就像电影院里的排座系统:
| 你已经会的 | AI 世界里对应的东西 |
|---|---|
| 菜篮子买菜:先放番茄还是先放鸡蛋,篮子里东西完全一样 | 置换不变性(Permutation Invariance):自注意力对输入顺序天然脱敏 |
| 电影票座位号:「3排5座」贴在每个观众身上 | 位置编码(Positional Encoding):直接把位置向量加进词嵌入中 |
| 时钟指针:秒针转得极快、分针转得慢、时针几乎不动 | 几何级数波长:高频正弦波区分相邻细微距离,低频波刻画全篇长距离 |
三角公式:cos(α + β) = cos α · cos β − sin α · sin β | 相对距离线性变换:固定偏移 k 的位置编码可以由当前编码线性表示 |
| 排队时不说「我是 37 号」,而说「我前面还有 3 个人」 | 相对位置:比起绝对排位,语言规律更依赖两个 token 之间隔了多远 |
| 死记硬背某句话在课本第 58 页,换一本页码不同的书就找不到 | 绝对位置编码的外推短板:只见过训练长度的编号,遇到更长文本就失灵 |
考虑两个语义完全相反的句子:
Q 都要去和序列中所有 token 的 K 做点积并加权汇总。
为了注入位置,2017 论文在输入嵌入层(Embedding)上直接加(Add)了一个同维度的位置向量 PE:
最终输入向量 = Word Embedding + PE
PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
其中 pos 是 token 在句子里的排位(第 0, 1, 2... 个),i 是特征维度的索引(第 0 到 255 维)。
10000^(2i/d_model)?
i=0 时,分母是 1,正弦波波长是 2π ≈ 6.28,像秒针一样疯狂震荡——用来精细分辨第 1 个 token 和第 2 个 token 的微小差异;
i 逐渐增大,波长呈几何级数急剧拉长,直到最大波长变成 10000 × 2π ≈ 62800,像时针一样极其缓慢地变化——用来感知长篇大论中宏观的全局距离。
作者之所以不用简单的一维数字(如 1, 2, 3...),也不用纯随机编号,是因为三角函数自带一条奇妙的数学性质:两角和差公式。
cos(α + β) = cos α · cos β − sin α · sin β
sin(α + β) = sin α · cos β + cos α · sin β
k(比如两个 token 相隔 5 个位置):
PE(pos + k) = M_k · PE(pos)
M_k 是一个只和相对距离 k 有关的常数旋转矩阵!
sin 与 cos 各占一个维度(2i 与 2i+1),两个分量配合才能凑出完整的旋转矩阵——只留下一个的话,相差半个波长的两个位置会读出相同的值,相对偏移就算不准了。在 2017 年论文的消融实验中,作者对比了「正弦固定编码」和「可学习位置嵌入(Learned Embedding)」,发现两者在 WMT 翻译任务上效果几乎平手。作者在论文里写下一句著名推测:「我们选择正弦版本,是因为它可能允许模型外推到比训练更长的序列。」
k 的编码可表示为当前编码的线性变换 M_k · PE(pos);③ 历史缺陷与淘汰原因:2017 版将绝对位置以加法(Additive)形式混入输入 Embedding,在深层传播中位置信号被反复稀释,且在自注意力内积时会产生语义-位置交叉杂项,更无法真正外推到未见长度,最终在近十年被将旋转矩阵直接作用于 Q/K 的 RoPE 所全面取代。」逐词翻译:「由于我们的模型不包含循环和卷积,为了让模型利用序列的顺序信息,我们必须注入相对或绝对位置信息……我们之所以选择这个函数,是因为假设它能让模型轻松学会按相对位置关注,因为对任意固定偏移 k,PE(pos+k) 都可以表示为 PE(pos) 的线性函数。」
输入 = Embedding + PE。因此 PE 的维度必须与模型维度 d_model = 512 严格相等。