惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Fortinet All Blogs
B
Blog
T
The Blog of Author Tim Ferriss
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
Y
Y Combinator Blog
Microsoft Azure Blog
Microsoft Azure Blog
L
LangChain Blog
Recent Announcements
Recent Announcements
U
Unit 42
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The Register - Security
The Register - Security
Recorded Future
Recorded Future
C
Check Point Blog
V
V2EX
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
酷 壳 – CoolShell
酷 壳 – CoolShell
F
Full Disclosure
小众软件
小众软件
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
有赞技术团队
有赞技术团队
MongoDB | Blog
MongoDB | Blog
爱范儿
爱范儿
P
Proofpoint News Feed
罗磊的独立博客
量子位
D
Docker
博客园_首页
D
DataBreaches.Net
Project Zero
Project Zero
博客园 - 司徒正美
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - Franky
Security Latest
Security Latest
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
Netflix TechBlog - Medium
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
大猫的无限游戏
大猫的无限游戏

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
微调LLM前你需要了解的一些概念2--多头注意力机制
royalrover · 2026-06-09 · via 博客园_首页

1. 先区分两个概念:多头和多层

Multi-Head Attention 和多层 Transformer Block 不是一回事。

一句话区分:

Multi-Head Attention:同一层里,多个 attention head 并行看上下文。
多层 Transformer Block:很多层 block 串行堆叠,一层处理完再传给下一层。

更短地记:

多头 = 横向多视角
多层 = 纵向深加工

图示如下:

flowchart TD X["输入 hidden states X0"] --> B1["Transformer Block 1"] B1 --> B2["Transformer Block 2"] B2 --> B3["Transformer Block 3"] B3 --> Y["最终 hidden states"] subgraph S1["Block 1 内部:Multi-Head Attention"] H1["Head 1"] H2["Head 2"] H3["Head 3"] HC["合并多个 head"] H1 --> HC H2 --> HC H3 --> HC end

Block 之间是串行的:

X1 = Block1(X0)
X2 = Block2(X1)
X3 = Block3(X2)

因为第 2 层必须等第 1 层输出之后才能计算。

但在一个 Block 内部,多个 head 可以并行计算:

Head 1 ┐
Head 2 ├─ 同时计算 → 合并 → 输出
Head 3 ┘

2. 为什么需要 Multi-Head Attention

Self-Attention 的核心问题是:

当前 token 应该关注上下文里的哪些 token?

如果只有一个 head,它只能产生一套注意力分布。

例如句子:

小明 把 苹果 放进 书包 因为 它 太小 了

模型处理“它”时,需要同时理解很多关系:

1. “它”指代谁?
2. “太小”描述的是哪个物体?
3. “苹果”和“书包”之间是什么动作关系?
4. 句子的主语是谁?
5. 哪些词是局部搭配?

如果只有一个 head,它可能给出一套注意力权重:

书包: 0.70
苹果: 0.15
小明: 0.05
其他: 0.10

这套权重主要解决了“它指代书包”这个问题。

但同一层里,模型还可能需要同时关注动作关系、语法关系、局部搭配等。一个 head 只有一套 softmax 权重,很难同时清晰表达多种关系。

Multi-Head Attention 的目的就是:

让同一个 token 在同一层里,从多个子空间、多个角度同时理解上下文。

可以把多个 head 想成多个小专家:

Head 1:关注指代关系
Head 2:关注动作关系
Head 3:关注局部搭配
Head 4:关注语法结构
Head 5:关注长距离依赖

同一个 token “它”,不同 head 可能关注不同位置:

Head 1,看指代:
书包: 0.80, 苹果: 0.10

Head 2,看动作链:
放进: 0.50, 苹果: 0.20, 书包: 0.20

Head 3,看局部搭配:
太小: 0.70, 了: 0.20

Head 4,看主语结构:
小明: 0.40, 把: 0.30, 放进: 0.20

最后这些 head 的结果合并起来,“它”的表示就会带着更丰富的信息:

它 ≈ 指代书包
   + 和“太小”形成属性关系
   + 处在“苹果放进书包”的动作结构中
   + 受前面“小明把...”句法结构影响

3. 多层 Transformer Block 不能替代多头吗

不能完全替代。它们解决的问题不同。

如果只有单头但有很多层,模型当然也能逐步加工信息:

第 1 层:用一套注意力看上下文
第 2 层:再用一套注意力看上一层结果
第 3 层:继续加工

这像:

一个人反复读文章很多遍。

Multi-Head Attention 像:

一组人同时从语法、语义、指代、位置等角度读同一句话。

两者互补:

多头:同一层内提供多视角并行理解
多层:层与层之间逐步抽象、深化、整合

图示:

flowchart LR A["同一层内"] --> B["多个 head 并行捕捉多种关系"] C["多层之间"] --> D["上一层输出作为下一层输入,逐步深化表示"] B --> E["横向多视角"] D --> F["纵向深加工"] E --> G["共同提升模型表达能力"] F --> G

所以,多头不是单纯为了加速,而是为了增强表达能力。

它让模型在同一层里拥有多套“关注谁”的方案,而不是把所有关系挤进一套注意力权重里。

4. 每一层都有相同的多头吗

通常,标准 LLM 中每一层 Transformer Block 都有 Multi-Head Attention。

例如一个模型配置可能是:

num_layers = 32
hidden_size = 4096
num_attention_heads = 32
head_dim = 128

这意味着:

一共有 32 层 Transformer Block
每层都有 32 个 attention heads
每个 head 的维度是 128

但是要注意:

每层结构通常相同,但参数不共享。

也就是说:

Block 1:
  32 个 heads
  使用 Wq1, Wk1, Wv1, Wo1

Block 2:
  32 个 heads
  使用 Wq2, Wk2, Wv2, Wo2

Block 3:
  32 个 heads
  使用 Wq3, Wk3, Wv3, Wo3

第 1 层的 Head 1 和第 20 层的 Head 1 不是同一个 head。它们只是编号相同,参数不同,输入也不同。

因为不同层处理的表示阶段不同:

第 1 层输入:更接近原始 token embedding
第 10 层输入:已经融合了一些上下文关系
第 30 层输入:更接近高级语义和预测任务

所以不同层需要不同的 Q/K/V 参数来处理不同阶段的信息。

可以粗略理解为:

低层 head:更偏局部位置、相邻 token、标点、短语搭配
中层 head:更偏语法关系、实体关系、指代关系
高层 head:更偏任务意图、长距离依赖、输出预测相关信息

这不是人工规定,而是训练后自然形成的倾向。

5. 一个大矩阵如何一次性算出所有 head 的 Q/K/V

这是多头注意力最容易卡住的地方。

先记住一句话:

大矩阵负责一次性算出所有 head 的 Q/K/V;reshape 负责把“混在一起的 head 维度”重新分组,让程序知道哪一段属于哪个 head。

假设:

seq_len = 3
hidden_size = 8
num_heads = 2
head_dim = 4

因为:

hidden_size = num_heads × head_dim = 2 × 4 = 8

输入 X 的形状是:

X shape = [seq_len, hidden_size] = [3, 8]

可以理解为 3 个 token,每个 token 是 8 维向量:

token1: [8 维]
token2: [8 维]
token3: [8 维]

如果不用大矩阵,你可以想象成分别计算两个 head:

Q_head1 = X Wq_head1  → [3, 4]
Q_head2 = X Wq_head2  → [3, 4]

但工程实现不会一个 head 一个 head 地算,而是把两个 head 的投影矩阵拼成一个大矩阵:

Wq shape = [8, 8]

一次性计算:

Q = X Wq
Q shape = [3, 8]

这个 [3, 8] 的最后一维其实可以理解为:

前 4 维:Head 1 的 Q
后 4 维:Head 2 的 Q

例如:

Q token1 = [h1_1, h1_2, h1_3, h1_4, h2_1, h2_2, h2_3, h2_4]

reshape 就是把它从:

[3, 8]

变成:

[2, 3, 4]

含义变成:

2 个 head
3 个 token
每个 token 在每个 head 里是 4 维

6. reshape 的意义是什么

reshape 不改变数值,只改变数据的组织方式。

reshape 前:

Q shape = [3, 8]

可以看成:

token1: [a1 a2 a3 a4 b1 b2 b3 b4]
token2: [a5 a6 a7 a8 b5 b6 b7 b8]
token3: [a9 a10 a11 a12 b9 b10 b11 b12]

reshape 后:

Q shape = [2, 3, 4]

变成:

Head 1:
token1: [a1 a2 a3 a4]
token2: [a5 a6 a7 a8]
token3: [a9 a10 a11 a12]

Head 2:
token1: [b1 b2 b3 b4]
token2: [b5 b6 b7 b8]
token3: [b9 b10 b11 b12]

所以 reshape 的意义是:

把原来连在一起的 hidden_size 维向量,拆成 num_heads × head_dim,让每个 head 拿到属于自己的那一段 Q/K/V。

K 和 V 也一样:

K = X Wk → [3, 8] → reshape 为 [2, 3, 4]
V = X Wv → [3, 8] → reshape 为 [2, 3, 4]

于是每个 head 都有自己的:

Head 1: Q1, K1, V1,shape 都是 [3, 4]
Head 2: Q2, K2, V2,shape 都是 [3, 4]

7. reshape 后每个 head 如何计算 attention

对 Head 1:

Q1 shape = [3, 4]
K1 shape = [3, 4]
V1 shape = [3, 4]

先计算注意力分数:

scores1 = Q1 K1^T

形状是:

[3, 4] × [4, 3] = [3, 3]

这个 [3, 3] 是一张注意力图:

每个 query token 对每个 key token 的关注分数。

例如:

              key token1  key token2  key token3
query token1      0.8         0.1         0.1
query token2      0.2         0.6         0.2
query token3      0.3         0.2         0.5

然后缩放并做 softmax:

weights1 = softmax(scores1 / sqrt(head_dim))

再用权重加权 V:

out1 = weights1 V1

形状是:

[3, 3] × [3, 4] = [3, 4]

Head 2 同理:

out2 shape = [3, 4]

最后把两个 head 的输出拼回去:

concat(out1, out2) → [3, 8]

再经过输出投影矩阵:

output = concat_heads Wo

最终输出形状仍然是:

[3, 8]

这样它就可以继续进入残差连接、MLP、下一层 Transformer Block。

完整流程如下:

flowchart TD X["X: [seq_len, hidden_size] = [3, 8]"] --> Q["Q = X Wq: [3, 8]"] X --> K["K = X Wk: [3, 8]"] X --> V["V = X Wv: [3, 8]"] Q --> QR["reshape Q: [num_heads, seq_len, head_dim] = [2, 3, 4]"] K --> KR["reshape K: [2, 3, 4]"] V --> VR["reshape V: [2, 3, 4]"] QR --> A1["Head 1 Attention"] KR --> A1 VR --> A1 QR --> A2["Head 2 Attention"] KR --> A2 VR --> A2 A1 --> C["concat heads: [3, 8]"] A2 --> C C --> WO["输出投影 Wo"] WO --> O["Attention 输出: [3, 8]"]

8. 加上 batch 后的真实形状

真实模型中通常有 batch。

输入形状:

X shape = [batch, seq_len, hidden_size]

例如:

batch = 2
seq_len = 3
hidden_size = 8
num_heads = 2
head_dim = 4

那么:

X shape = [2, 3, 8]

一次性计算 Q:

Q = X Wq
Q shape = [2, 3, 8]

reshape:

Q shape = [2, 3, 2, 4]

通常还会 transpose 一下,把 head 维度提前:

Q shape = [2, 2, 3, 4]

含义是:

[batch, num_heads, seq_len, head_dim]

也就是:

2 个样本
2 个 head
3 个 token
每个 head 4 维

K 和 V 同理:

K shape = [2, 2, 3, 4]
V shape = [2, 2, 3, 4]

然后批量计算:

scores = Q @ K.transpose(-2, -1)

形状变化:

[2, 2, 3, 4] @ [2, 2, 4, 3]
= [2, 2, 3, 3]

含义是:

每个 batch、每个 head,都有一张 seq_len × seq_len 的注意力图。

再做:

weights = softmax(scores / sqrt(head_dim))
out = weights @ V

形状:

[2, 2, 3, 3] @ [2, 2, 3, 4]
= [2, 2, 3, 4]

最后转置并 reshape 回:

[2, 2, 3, 4]
→ [2, 3, 2, 4]
→ [2, 3, 8]

这就回到了:

[batch, seq_len, hidden_size]

9. 为什么这样能并行

reshape 后,head 维度变成了张量中的一个独立维度:

[batch, num_heads, seq_len, head_dim]

GPU 可以把:

batch 维度
head 维度
token 维度

一起打包成大规模矩阵运算。

它不是在 Python 里慢慢循环:

for head in heads:
    attention(head)

而是一次性执行:

所有 batch 的所有 head 的 QK^T
所有 batch 的所有 head 的 softmax
所有 batch 的所有 head 的 weights @ V

这就是多头注意力中的“并行”。

图示:

flowchart LR A["Q/K/V: [batch, num_heads, seq_len, head_dim]"] --> B["批量矩阵乘法 QK^T"] B --> C["scores: [batch, num_heads, seq_len, seq_len]"] C --> D["softmax"] D --> E["weights @ V"] E --> F["head outputs: [batch, num_heads, seq_len, head_dim]"] F --> G["合并 heads: [batch, seq_len, hidden_size]"]

10. 为什么不是直接用一个更大的 head

一个常见疑问是:

如果总维度一样,为什么不用一个大 head,而要拆成多个小 head?

例如:

一个 head,维度 12

和:

三个 head,每个维度 4

总维度看起来一样。

关键区别在于:

一个大 head 通常只有一套注意力分布;多个 head 有多套独立的注意力分布。

一个 head:

只有一张 attention map

多个 head:

Head 1 一张 attention map
Head 2 一张 attention map
Head 3 一张 attention map

这意味着,多头不是简单拆维度,而是让模型同时拥有多套“关注谁”的方案。

对同一个 token “它”:

Head 1:关注“书包”,解决指代
Head 2:关注“太小”,解决属性
Head 3:关注“放进”,解决动作关系
Head 4:关注“小明”,解决主语结构

如果只有一个大 head,这些关系要挤在一张注意力图里,表达会更受限。

11. 多头注意力完整流程总结

完整流程可以压缩成:

1. 输入 X: [batch, seq_len, hidden_size]
2. 用大矩阵一次性算 Q/K/V
3. Q/K/V reshape 成 [batch, num_heads, seq_len, head_dim]
4. 每个 head 独立计算 attention map
5. 每个 head 得到自己的输出
6. 把所有 head 的输出 concat 回 hidden_size
7. 经过输出投影 Wo
8. 得到 Multi-Head Attention 输出

图示:

flowchart TD X["X: [B, S, H]"] --> QKV["线性投影得到 Q/K/V: [B, S, H]"] QKV --> R["reshape + transpose: [B, heads, S, head_dim]"] R --> SCORE["QK^T / sqrt(head_dim): [B, heads, S, S]"] SCORE --> MASK["可选 causal mask"] MASK --> SOFT["softmax 得到注意力权重"] SOFT --> VOUT["weights @ V: [B, heads, S, head_dim]"] VOUT --> MERGE["transpose + reshape 合并 heads: [B, S, H]"] MERGE --> WO["输出投影 Wo"] WO --> OUT["Attention 输出: [B, S, H]"]

其中:

B = batch
S = seq_len
H = hidden_size
head_dim = H / num_heads

12. 面试回答模板

Q1:Multi-Head Attention 和多层 Transformer Block 是一回事吗?

不是。Multi-Head Attention 是同一层内部的多个 attention head 并行计算,用于从多个子空间捕捉不同关系;多层 Transformer Block 是多个 block 串行堆叠,后一层依赖前一层输出,用于逐层深化表示。

Q2:为什么需要多头注意力?

一个 attention head 只有一套注意力分布,很难同时表达指代、语法、局部搭配、实体关系等多种关系。多头注意力允许模型在同一层中并行学习多套注意力模式,再合并成更丰富的上下文表示。

Q3:多层 Transformer Block 能替代多头吗?

不能完全替代。多层提供纵向的逐步抽象,多头提供横向的多视角信息交互。单头多层像一个人反复读文章,多头像多人同时从不同角度读文章,两者是互补关系。

Q4:每一层都有相同的多头吗?

多数标准 LLM 中,每一层通常有相同数量的 attention heads,例如每层 32 个 head。但不同层的 Q/K/V/O 参数不共享,因此第 1 层的 Head 1 和第 20 层的 Head 1 不是同一个东西,它们会学习不同层次的关系。

Q5:reshape 的意义是什么?

大矩阵一次性算出的 Q/K/V 形状通常是 [batch, seq_len, hidden_size]。reshape 把最后的 hidden_size 维拆成 num_heads × head_dim,变成 [batch, num_heads, seq_len, head_dim],让每个 head 拿到自己对应的 Q/K/V 子空间并独立计算 attention。

Q6:为什么这种实现可以并行?

reshape 后,head 维度成为张量的批处理维度之一。GPU 可以同时计算所有 batch、所有 head 的矩阵乘法、softmax 和加权求和,而不是一个 head 一个 head 地循环执行。

13. 最短记忆版

Multi-Head Attention:
同一层里多个 head 并行计算多套注意力。

多层 Transformer Block:
多个 block 串行堆叠,逐层深化表示。

为什么需要多头:
一个 head 只有一套注意力分布,多头可以同时关注指代、语法、动作、局部搭配等关系。

每层是否相同:
通常每层 head 数量相同,但参数不共享,学到的功能也不同。

大矩阵算 QKV:
一次性算出所有 head 的 Q/K/V,提高计算效率。

reshape:
把 hidden_size 拆成 num_heads × head_dim,让每个 head 拿到自己的子空间。

并行:
GPU 同时计算所有 batch、所有 head 的 attention。

一句话总结:

Multi-Head Attention 是 Transformer 在同一层里进行多视角上下文理解的机制。它通过大矩阵一次性生成所有 head 的 Q/K/V,再 reshape 成多个 head 独立计算多套注意力图,最后合并输出;多层 Transformer Block 则是在纵向上逐层深化这些表示,二者共同构成 LLM 的强大表达能力。