多头注意力与位置编码
约 14 分钟
上一节的自注意力还缺两块拼图,补上它们,Transformer 的核心就完整了。
一、多头注意力:同时从多个角度看
一次注意力只能学一种「关注模式」。但语言里的关系是多层次的:
The tired animal that lived near the street didn't cross it.
- 有的关系是语法的(主语—谓语)
- 有的是指代的(it—animal)
- 有的是语义的(tired—didn't cross)
多头的做法:把向量切成 份(比如 8 或 16 头),每一份独立做一次注意力,最后把结果拼接起来再过一个线性层。
关键点:每个头的维度是 ,所以总计算量和单头基本相同——多头几乎是免费的。
实际观察到的现象:训练后不同的头确实分工了——有的头专门关注相邻词,有的追踪句法依存,有的负责指代。这是可以可视化出来的。
二、位置编码:告诉模型词的顺序
自注意力有个容易被忽略的性质:它对顺序不敏感。
把「狗咬人」的词序打乱成「人咬狗」,每个词的 Q、K、V 完全没变,注意力算出来的结果也一样。这显然不行。
RNN 天然有顺序(因为它是逐步读的),Transformer 把顺序丢掉了,必须显式补回来。
解法:给每个位置加一个「位置向量」
原论文用正弦和余弦函数生成:
为什么用三角函数(两个理由):
- 不同频率的组合能唯一编码每个位置,类似二进制用不同位表示数字
- 相对位置可以通过线性变换得到—— 能表示成 的线性组合,这让模型更容易学「相对距离」
位置编码直接加到词向量上,然后一起送进网络。
位置编码的演进
| 方式 | 特点 |
|---|---|
| 正弦位置编码 | 原论文方案,不用学,理论上可外推到更长序列 |
| 可学习位置嵌入 | 当成参数训练(BERT 用这个),简单但长度写死 |
| 相对位置编码 | 直接建模「词与词的距离」而非绝对位置 |
| 旋转位置编码(RoPE) | 用旋转矩阵注入位置,外推性好,被很多现代模型采用 |
为什么这块一直在演进:上下文长度是大模型的核心竞争点之一,而位置编码直接决定了「训练时见过 4K,能不能用在 32K 上」。这是一个活跃的研究方向。
把两块拼图装上
一个完整的 Transformer 层现在长这样:
输入 = 词嵌入 + 位置编码
↓
多头自注意力
↓
残差连接 + 层归一化
↓
前馈网络(两层 MLP)
↓
残差连接 + 层归一化
残差连接(第二章 ResNet 那一节讲过)在这里同样关键——没有它,几十层的 Transformer 根本训不动。
练习:如果去掉位置编码,Transformer 处理「猫追狗」和「狗追猫」会有区别吗?为什么?
多头注意力为什么「几乎是免费的」?自注意力为什么必须额外加位置编码?
登录 后可看答案