15

多头注意力——16 个头各看什么

阅读约 6 分钟第 15/60 课

上一章节完成了单头注意力的计算:一组 Q、K、V,产生一个注意力分布,融合上下文信息。

但一组注意力只能捕捉一种关系。在自然语言中,两个词之间的关系是多层次的:

  • 「她开心地笑了」——「笑」和「她」之间有主谓关系。
  • 同一句话里,「笑」和「开心」之间有状语修饰关系。
  • 「笑」和「了」之间有时态标记关系。

一个注意力头只能学习其中一种关系——它的 Q、K、V 权重矩阵被训练来识别某种特定的匹配模式。要同时捕捉多种关系,需要多个注意力头并行工作。

怎么做到多头

多头注意力(Multi-Head Attention)的思路很直接:把维度分成多份,每份独立做一次注意力,最后把结果拼起来。

Sophia 有 16 个注意力头。隐藏维度是 1,536,分成 16 份,每份 96 维(1,536 ÷ 16 = 96)。

具体步骤:

第一步:生成 Q、K、V(和单头一样)。

Q = X × W_Q     (序列长度 × 1536)
K = X × W_K     (序列长度 × 1536)
V = X × W_V     (序列长度 × 1536)

第二步:拆分成 16 个头。

把每个向量的 1,536 维切成 16 段,每段 96 维:

Q 的第 1 个头: 前 96 维
Q 的第 2 个头: 第 97-192 维
Q 的第 3 个头: 第 193-288 维
...
Q 的第 16 个头: 第 1441-1536 维

K 和 V 也同样拆分。

第三步:每个头独立计算注意力。

16 个头各自在自己的 96 维空间里计算:分数 = Q_i × K_i 的转置 / √96,softmax,然后乘以 V_i。每个头得到一个 序列长度 × 96 的输出。

第四步:把 16 个头的输出拼起来。

把 16 个 96 维的输出沿维度方向拼接,恢复成 1,536 维:

拼接后 = [头1输出 | 头2输出 | ... | 头16输出]     (序列长度 × 1536)

第五步:最后一次矩阵乘法。

通过一个输出投影矩阵 W_O,把拼接后的结果再做一次线性变换:

最终输出 = 拼接后 × W_O     (序列长度 × 1536)

为什么要分成多个头

你可能会问:直接用一个 1,536 维的注意力不行吗?为什么要费力拆成 16 份?

多头让模型能同时学习多种关系。 每个头的 96 维 Q、K、V 权重矩阵是独立训练的,会自然地学到不同的匹配模式。

研究者对训练好的多头注意力做过分析,发现不同的头确实学到了不同的功能:

  • 有的头专注于位置关系:关注固定距离之外的 token(比如总是关注前两个词)。
  • 有的头专注于语法关系:主语关注谓语,修饰语关注被修饰的词。
  • 有的头专注于语义相关性:关注含义相近或相关的词。
  • 有的头似乎在做复制:当需要重复某个词时,这个头会强烈关注那个词的位置。

这种分工不是人为设计的——模型在训练中自己学会了用不同的头做不同的事。

多头的另一个好处是计算效率。 16 个头各自在 96 维空间里计算注意力,总计算量和一个 1,536 维的注意力几乎一样——因为计算量主要取决于维度的平方,而 16 × 96² = 16 × 9,216 = 147,456,和 1,536² = 2,359,296 不同?

等等,这样算不对。实际上,16 个头的计算量确实和单头差不多——关键在于 QK 的矩阵乘法。单头是 (n×1536) × (1536×n) = n² × 1536 次乘法。多头是 16 × (n×96) × (96×n) = 16 × n² × 96 = n² × 1536 次乘法。一样。

所以多头注意力并没有增加计算量,但增加了表达能力——从一种关注模式变成了 16 种。这是一个免费的能力提升。

Sophia 的注意力配置

Sophia 的 28 层采用了一种特殊的排列:每四层为一组,前三层使用 KDA(一种线性注意力变体),第四层使用 MLA(Multi-head Latent Attention)。

这两种注意力都使用多头设计,但内部的计算方式不同——KDA 和 MLA 分别是第 17 和第 22 章节的主题。现在只需要知道:多头注意力是所有这些变体的基础框架,区别只在于每个头内部怎么计算 Q、K、V 以及怎么处理历史信息。

下一章节来看一个实际工程问题:当模型在推理时(已经训练完,正在和你对话),它需要把之前看过的每一个 token 的 K 和 V 向量存起来——这就是 KV cache。它为什么必须存在,以及为什么它会消耗大量显存。