Transformer 的位置编码是怎样的?
Transformer 的位置编码是怎样的?
这道题考的是 Transformer 中位置编码的设计原理,核心是理解为什么需要位置编码以及正弦位置编码是怎么工作的。面试官想看你能不能把 Self-Attention 的"位置不感知"问题说清楚,并且把公式讲明白。
我从四个方面来讲:为什么需要位置编码、正弦位置编码的原理、可学习与固定编码的对比、以及容易被忽略的性质和局限。
为什么 Transformer 需要位置编码
先说一个关键事实:Self-Attention 本身不感知序列位置。
Attention 的计算逻辑是这样的:输入是一堆 token 的向量表示,计算每两个 token 之间的相似度,然后加权求和。问题在于,这个计算过程跟 token 的顺序没关系——把句子打乱,Attention 算出来的权重完全一样。
举个例子:
- 原始句子:"我爱你"
- 打乱顺序:"你爱我"
对于 Attention 来说,"我→爱→你" 和 "你→爱→我" 的注意力分布是一样的。它只知道"我"和"你"都应该关注"爱",但不知道谁在前面谁在后面。
这就是所谓的置换不变性(Permutation Invariance)。对于需要理解语序的任务来说,这是个致命缺陷。"我打你"和"你打我"意思完全相反,没有位置信息模型根本分不清。
RNN 天然能感知位置,因为它是顺序处理的——"我"处理完才轮到"打","打"处理完才轮到"你"。但 Transformer 是一次性把所有 token 一起处理,所以必须在输入层面就把位置信息塞进去。
位置编码就这么来的:不是让模型自己学位置,而是人为给每个位置造一个"身份证",然后把这个身份证加到词向量上。
正弦位置编码的设计原理
Attention is all you need 论文里用的是一种叫 Sinusoidal Position Encoding 的方法。公式长这样:
$$PE(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d}}\right)$$
$$PE(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d}}\right)$$
看着复杂,我来拆解一下:
- pos 是位置,从 0 开始
- d 是编码向量的维度(和词向量维度一样)
- i 是维度索引,从 0 开始
- 偶数维度用 sin,奇数维度用 cos
核心思想:用不同频率的正弦/余弦函数来编码位置。低频信号捕捉长距离关系,高频信号捕捉精细位置。
打个比方。就像音乐里的泛音:一个音符不只有基频,还有2倍频、3倍频……叠加在一起形成独特的音色。每个位置也有一组不同频率的 sin/cos 叠加,形成独特的"位置指纹"。
10000 这个数字是论文里的经验值。它决定了低频有多低——频率 = 1/10000 意味着波长很长,能表示很远的位置差异。
为什么奇偶维度要用 sin 和 cos 交替?
因为这样可以让任意两个位置的编码通过线性组合互相表示。什么意思?
假设你知道位置 pos 的编码 PE(pos),以及位置 k 的编码 PE(k),你可以用简单的线性变换算出位置 pos+k 的编码:
$$PE(pos + k) = PE(pos) \cdot W + PE(k) \cdot W'$$
这个性质叫线性可组合性。它意味着模型理论上能通过线性层学习到相对位置关系,而不只是绝对位置。
可学习位置嵌入 vs 固定位置编码
原论文用的 sin/cos 固定编码,但后来很多模型换成了可学习的位置嵌入。
两种方法的对比:
| 固定 sin/cos | 可学习位置嵌入 | |
|---|---|---|
| 实现 | 手工设计,用公式算出 | 随机初始化,像词向量一样训练 |
| 参数量 | 0(不占参数) | 需要学习的参数 |
| 灵活性 | 对任意长度都适用 | 训练时固定最大长度 |
| 效果 | 大多数任务表现相近 | 大多数任务表现相近 |
BERT 用的就是可学习位置嵌入。GPT 系列也是。
实际差别大吗?
其实差别不大。论文里做过实验,两种方法在翻译、分类等任务上效果差不多。选哪个更多是工程考量,而不是效果考量。
固定编码的好处是不占参数,而且能泛化到训练没见过的长度。可学习编码的好处是实现简单,直接当参数训练就行。
位置编码的隐藏性质与局限
距离感知性
正弦位置编码理论上具有距离感知性:位置越近,编码越相似;位置越远,编码差异越大。
这可以通过计算编码向量之间的余弦相似度验证。相近位置的编码点积大,远距离位置的编码点积小。
这个性质本来是设计目标,让模型能感知 token 之间的相对距离。
但有个问题
进入多层 Attention 之后,这个性质可能会被破坏。
Attention 的计算是 query 和 key 做点积。如果位置编码经过线性变换和非线性激活,原有的几何关系可能被扭曲。
有研究做过可视化:看多层 Transformer 后,位置编码的热力图模式是否还保持。结论是前面的层还好,后面的层可能会乱掉。
所以位置编码的作用可能没你想的那么直接。它不是保证位置关系,而是提供一种"初始偏差",模型自己学怎么用。
新的位置编码方式
最近几年出现了几种改进方案:
RoPE(Rotary Position Embedding)
LLaMA、GLM 在用。不是把位置编码加到向量里,而是让 query 和 key 做旋转。这样Attention 计算天然就带上了位置信息,而且相对位置关系不会被破坏。
ALiBi(Attention with Linear Biases)
不学位置编码,而是在 Attention 分数上加一个与距离有关的线性偏置。适合处理超长序列。
面试怎么答
基础版
Transformer 需要位置编码是因为 Self-Attention 本身不感知序列位置——把句子打乱,Attention 计算结果完全一样。原论文用的是正弦位置编码,用不同频率的 sin 和 cos 函数对每个位置进行编码,偶数维度用 sin,奇数维度用 cos。这个设计的优点是任意两个位置的编码可以通过线性组合表示第三个位置,让模型能学到相对位置关系。后来 BERT 等模型改用了可学习的位置嵌入,和固定编码效果差不多。
加分版
除了基本原理,正弦编码还有一个重要性质是线性可组合性——可以用两个位置的编码通过线性变换得到第三个位置的编码,这让模型能表达相对位置。另外需要知道的是,位置编码进入多层 Attention 后,原有的几何性质可能会被破坏,所以它更多是提供一种初始偏差。进入面试加分可以说一下 RoPE 和 ALiBi,这些是现在更常用的方案。
一句话总结
位置编码是为了解决 Self-Attention 的置换不变性问题,正弦编码用不同频率的 sin/cos 叠加让每个位置有唯一标识,且相邻位置的编码具有线性可组合性。
