深度学习入门

多头注意力与位置编码

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 把顺序丢掉了,必须显式补回来。

解法:给每个位置加一个「位置向量」

原论文用正弦和余弦函数生成:

为什么用三角函数(两个理由):

  1. 不同频率的组合能唯一编码每个位置,类似二进制用不同位表示数字
  2. 相对位置可以通过线性变换得到—— 能表示成 的线性组合,这让模型更容易学「相对距离」

位置编码直接加到词向量上,然后一起送进网络。


位置编码的演进

方式 特点
正弦位置编码 原论文方案,不用学,理论上可外推到更长序列
可学习位置嵌入 当成参数训练(BERT 用这个),简单但长度写死
相对位置编码 直接建模「词与词的距离」而非绝对位置
旋转位置编码(RoPE) 用旋转矩阵注入位置,外推性好,被很多现代模型采用

为什么这块一直在演进上下文长度是大模型的核心竞争点之一,而位置编码直接决定了「训练时见过 4K,能不能用在 32K 上」。这是一个活跃的研究方向。


把两块拼图装上

一个完整的 Transformer 层现在长这样:

输入 = 词嵌入 + 位置编码
  ↓
多头自注意力
  ↓
残差连接 + 层归一化
  ↓
前馈网络(两层 MLP)
  ↓
残差连接 + 层归一化

残差连接(第二章 ResNet 那一节讲过)在这里同样关键——没有它,几十层的 Transformer 根本训不动。

练习:如果去掉位置编码,Transformer 处理「猫追狗」和「狗追猫」会有区别吗?为什么?

小纸条

多头注意力为什么「几乎是免费的」?自注意力为什么必须额外加位置编码?

登录 后可看答案