Transformer 的多头注意力如何工作:从分头计算到拼接投影
围绕多头注意力内容,解释模型如何把 d_model 分到多个注意力头中,再将不同头的结果拼接回统一表示。
相关工具
为什么一个注意力视角还不够
句子中的关系不止一种。一个词可能需要关注主语,也可能需要关注修饰它的形容词、前面出现的指代对象或句尾的补充信息。如果所有关系都压在同一个注意力空间里,模型需要用同一套特征同时处理很多不同问题。
多头注意力的思路是让模型拥有多个并行的注意力头。每个头都对输入做自己的 Query、Key、Value 投影,在自己的子空间中计算关系,最后把各头结果合并。文中把它描述为同时关注来自不同表示子空间的信息。

同一序列被送入多个注意力头,不同头可以学习不同类型的位置关系。
多头是怎样把模型宽度分开的
假设输入表示宽度是 d_model,注意力头数是 h。模型会为每个头准备自己的投影矩阵,把输入映射到较小的头内维度。常见设置是头内维度约等于 d_model 除以 h,这样所有头的结果拼接后仍然可以回到 d_model。
分头并不是把序列切成几段。每个头通常都能看到完整序列,变化的是每个头使用的特征子空间和投影参数。八个头并不意味着第一个头只处理前八分之一的词,而是八个头都处理所有位置,只用不同的表示方式判断位置之间的关系。

模型宽度被分配到多个头中,每个头完成独立的注意力计算。
每个头为什么可以学到不同关系
不同注意力头拥有不同的 Query、Key、Value 投影矩阵,因此同一个输入词向量进入不同头后,会形成不同的特征表示。一个头可能更容易捕捉相邻词关系,另一个头可能更关注长距离指代,还有的头可能对句法边界或特定语义联系更敏感。
这些功能不是人为固定分配的标签,而是训练过程中逐渐形成的倾向。模型会根据损失函数调整每个头的参数,哪些关系有助于预测目标词,哪些关系就更可能被保留下来。实际分析某个头时,也不能只凭一张注意力图就断言它永远只负责一种关系。

各头拥有独立投影参数,能够在不同子空间中学习不同的注意力模式。
各头算完以后为什么还要拼接
每个头的输出只包含自己子空间中的信息,不能直接作为完整的模型表示。模型会把所有头的输出沿特征维拼接起来,恢复出更宽的组合表示,再通过一个输出投影矩阵混合不同头的信息。
拼接保留了不同头的独立结果,输出投影则让它们可以互相组合。这样,模型既不会在计算一开始就把所有视角混成一份,也不会让各头最后完全彼此隔离。多头的价值就在于先分开观察,再综合使用。
多头注意力和多个独立模型有什么区别
多个独立模型各自处理完整输入,最后再把结果放在一起,参数和计算成本都可能大幅增加。多头注意力则共享同一个输入和主干层,在统一的 d_model 里分配多个较小的子空间,最后再回到同一个残差路径。
它不是把完整 Transformer 复制 h 次,而是在一次注意力子层内使用多组投影矩阵。这样可以在增加关系视角的同时控制计算规模,并让后续 FFN、LayerNorm 和残差连接继续使用统一模型宽度。
头数越多是不是一定越好
头数增加后,每个头的维度通常会变小。如果头数过多,单个头能够表达的特征空间可能不足,多个头之间也可能学到相似关系,增加计算和参数却没有带来相应收益。
头数需要和 d_model 配合选择,通常还要保证模型宽度可以被头数合理分配。模型质量不只取决于头数,还受到层数、FFN 宽度、训练数据和优化配置影响。更多头意味着更多可能的视角,不等于自动获得更好的理解。
编码器和解码器中的多头注意力
编码器自注意力的多个头都可以查看源序列,但各自使用不同投影来建模源内部关系。解码器自注意力的多个头还要共同遵守因果掩码,不能通过某个头绕过未来屏蔽。交叉注意力中,多个头则分别用解码器 Query 查询编码器的 Key 和 Value。
无论是哪种注意力,分头、独立计算、拼接和输出投影的主线基本不变。变化的是输入来源和可见范围,而不是多头机制本身。
用一条流程记住多头注意力
输入表示先经过多组投影,形成每个头自己的 Q、K、V;每个头独立计算分数、掩码、Softmax 和 Value 汇总;所有头的输出沿特征维拼接;拼接结果再经过输出投影,回到 d_model 并进入残差路径。
因此,多头注意力可以概括为“分开看、独立算、合起来用”。它让 Transformer 不必依赖单一的注意力视角,而是同时保留多个子空间中的关系,再把这些关系交给后续层继续加工。
常见问题
多头注意力是把句子分成几段吗?
不是。每个头通常都能看到完整序列,分开的是特征表示空间和投影参数,而不是词元位置。
每个头是不是固定负责一种关系?
不是固定指定的。不同头可能在训练中形成不同关注倾向,但具体作用取决于数据、参数和任务,不能只凭头数预先决定。
为什么多头结果还要经过一次输出投影?
拼接只是把不同头的结果放在一起,输出投影负责混合这些子空间信息,并把结果整理回 d_model 以接入后续残差路径。