第4章 Transformer Block
本章目标:
理解一个完整的 Transformer Block 的结构,以及 Tensor 的 Shape 是如何在其中变化的。
4.1 一个 Block 的全貌
Transformer 是由多个相同的 Block 堆叠而成的。
原始论文(2017)使用的是 Post-Norm 结构,每个 Block 的结构如下:
#mermaid-svg-V7FvNgZSvg0vSoKX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-V7FvNgZSvg0vSoKX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-V7FvNgZSvg0vSoKX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-V7FvNgZSvg0vSoKX .error-icon{fill:#552222;}#mermaid-svg-V7FvNgZSvg0vSoKX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-V7FvNgZSvg0vSoKX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-V7FvNgZSvg0vSoKX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-V7FvNgZSvg0vSoKX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-V7FvNgZSvg0vSoKX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-V7FvNgZSvg0vSoKX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-V7FvNgZSvg0vSoKX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-V7FvNgZSvg0vSoKX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-V7FvNgZSvg0vSoKX .marker.cross{stroke:#333333;}#mermaid-svg-V7FvNgZSvg0vSoKX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-V7FvNgZSvg0vSoKX p{margin:0;}#mermaid-svg-V7FvNgZSvg0vSoKX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-V7FvNgZSvg0vSoKX .cluster-label text{fill:#333;}#mermaid-svg-V7FvNgZSvg0vSoKX .cluster-label span{color:#333;}#mermaid-svg-V7FvNgZSvg0vSoKX .cluster-label span p{background-color:transparent;}#mermaid-svg-V7FvNgZSvg0vSoKX .label text,#mermaid-svg-V7FvNgZSvg0vSoKX span{fill:#333;color:#333;}#mermaid-svg-V7FvNgZSvg0vSoKX .node rect,#mermaid-svg-V7FvNgZSvg0vSoKX .node circle,#mermaid-svg-V7FvNgZSvg0vSoKX .node ellipse,#mermaid-svg-V7FvNgZSvg0vSoKX .node polygon,#mermaid-svg-V7FvNgZSvg0vSoKX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-V7FvNgZSvg0vSoKX .rough-node .label text,#mermaid-svg-V7FvNgZSvg0vSoKX .node .label text,#mermaid-svg-V7FvNgZSvg0vSoKX .image-shape .label,#mermaid-svg-V7FvNgZSvg0vSoKX .icon-shape .label{text-anchor:middle;}#mermaid-svg-V7FvNgZSvg0vSoKX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-V7FvNgZSvg0vSoKX .rough-node .label,#mermaid-svg-V7FvNgZSvg0vSoKX .node .label,#mermaid-svg-V7FvNgZSvg0vSoKX .image-shape .label,#mermaid-svg-V7FvNgZSvg0vSoKX .icon-shape .label{text-align:center;}#mermaid-svg-V7FvNgZSvg0vSoKX .node.clickable{cursor:pointer;}#mermaid-svg-V7FvNgZSvg0vSoKX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-V7FvNgZSvg0vSoKX .arrowheadPath{fill:#333333;}#mermaid-svg-V7FvNgZSvg0vSoKX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-V7FvNgZSvg0vSoKX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-V7FvNgZSvg0vSoKX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V7FvNgZSvg0vSoKX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-V7FvNgZSvg0vSoKX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V7FvNgZSvg0vSoKX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-V7FvNgZSvg0vSoKX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-V7FvNgZSvg0vSoKX .cluster text{fill:#333;}#mermaid-svg-V7FvNgZSvg0vSoKX .cluster span{color:#333;}#mermaid-svg-V7FvNgZSvg0vSoKX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-V7FvNgZSvg0vSoKX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-V7FvNgZSvg0vSoKX rect.text{fill:none;stroke-width:0;}#mermaid-svg-V7FvNgZSvg0vSoKX .icon-shape,#mermaid-svg-V7FvNgZSvg0vSoKX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V7FvNgZSvg0vSoKX .icon-shape p,#mermaid-svg-V7FvNgZSvg0vSoKX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-V7FvNgZSvg0vSoKX .icon-shape .label rect,#mermaid-svg-V7FvNgZSvg0vSoKX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V7FvNgZSvg0vSoKX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-V7FvNgZSvg0vSoKX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-V7FvNgZSvg0vSoKX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入 x
batch, seq, d_model
Multi-Head Self-Attention
残差连接 +
LayerNorm
Feed Forward Network
残差连接 +
LayerNorm
输出
batch, seq, d_model
⚠️ 注意:上图是原始论文的 Post-Norm 结构。现代 LLM(GPT-2、Llama、Qwen)使用 Pre-Norm 结构,区别见 4.4 节。
注意:输入和输出的 Shape 完全相同。
这是 Transformer 能堆叠多层的关键。
4.2 Block 的四个组件
| 组件 | 作用 | 章节 |
|---|---|---|
| Multi-Head Self-Attention | 让每个 Token 和所有 Token 交互 | 第6、7章 |
| Residual(残差连接) | 防止梯度消失,保留原始信息 | 第10章 |
| LayerNorm | 稳定训练,加速收敛 | 第9章 |
| Feed Forward Network | 对每个 Token 做非线性变换 | 第8章 |
4.3 为什么这样排列?
Block 的排列顺序是:
text
Attention → Add & Norm → FFN → Add & Norm
这个顺序不是随意的:
- Attention 先:让 Token 先收集全局信息
- Add & Norm:稳定 Attention 的输出,防止梯度爆炸
- FFN 后:对每个 Token 的表示做进一步变换(引入非线性)
- Add & Norm:再次稳定
4.3.1 为什么要两次 Residual + 两次 LayerNorm?
很多人看到 Block 结构会疑惑:为什么不是只在最后做一次 Residual + LayerNorm?
答案在于:一个 Block 做了两件本质不同的事情,每件事完成后都需要独立"提交"结果。
| 阶段 | 做什么 | 类比 | 为什么需要独立的 Add & Norm |
|---|---|---|---|
| Attention | 收集其他Token的信息 | 开会听取意见 | 意见可能有错,不能直接覆盖旧认知 |
| FFN | 对已有信息独立加工 | 回家自己思考 | 推理可能跑偏,不能直接覆盖会议结论 |
每个阶段的 Residual 含义:
- 第一次 Residual(Attention后):
旧认知 + 从别人那里收集的新信息 - 第二次 Residual(FFN后):
收集后的认知 + 自己深入思考的结果
如果只在 Block 最后做一次 Residual:
text
❌ H_new = H_old + Attention(H_old) + FFN(...)
那就意味着 FFN 的输入是 Attention 的"裸输出"(未经稳定化),数值可能不稳定,且 Attention 的错误会直接传给 FFN。
两次独立的 Add & Norm 确保:
- FFN 收到的是已经稳定化的中间结果
- 每个阶段的错误都被 Residual "缓冲"------即使那个阶段失败了,原始信息也不会丢失
4.4 Pre-Norm vs Post-Norm
原始论文使用 Post-Norm (LayerNorm 在残差相加之后):
text
Post-Norm: x → Attention(x) → x + Attention(x) → LayerNorm → ...
现代 LLM(GPT-2、Qwen、Llama)使用 Pre-Norm (LayerNorm 在子层之前):
text
Pre-Norm: x → LayerNorm(x) → Attention(LayerNorm(x)) → x + Attention(LayerNorm(x)) → ...
#mermaid-svg-g6HSgOlZLpenTuEn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-g6HSgOlZLpenTuEn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-g6HSgOlZLpenTuEn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-g6HSgOlZLpenTuEn .error-icon{fill:#552222;}#mermaid-svg-g6HSgOlZLpenTuEn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-g6HSgOlZLpenTuEn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-g6HSgOlZLpenTuEn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-g6HSgOlZLpenTuEn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-g6HSgOlZLpenTuEn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-g6HSgOlZLpenTuEn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-g6HSgOlZLpenTuEn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-g6HSgOlZLpenTuEn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-g6HSgOlZLpenTuEn .marker.cross{stroke:#333333;}#mermaid-svg-g6HSgOlZLpenTuEn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-g6HSgOlZLpenTuEn p{margin:0;}#mermaid-svg-g6HSgOlZLpenTuEn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-g6HSgOlZLpenTuEn .cluster-label text{fill:#333;}#mermaid-svg-g6HSgOlZLpenTuEn .cluster-label span{color:#333;}#mermaid-svg-g6HSgOlZLpenTuEn .cluster-label span p{background-color:transparent;}#mermaid-svg-g6HSgOlZLpenTuEn .label text,#mermaid-svg-g6HSgOlZLpenTuEn span{fill:#333;color:#333;}#mermaid-svg-g6HSgOlZLpenTuEn .node rect,#mermaid-svg-g6HSgOlZLpenTuEn .node circle,#mermaid-svg-g6HSgOlZLpenTuEn .node ellipse,#mermaid-svg-g6HSgOlZLpenTuEn .node polygon,#mermaid-svg-g6HSgOlZLpenTuEn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-g6HSgOlZLpenTuEn .rough-node .label text,#mermaid-svg-g6HSgOlZLpenTuEn .node .label text,#mermaid-svg-g6HSgOlZLpenTuEn .image-shape .label,#mermaid-svg-g6HSgOlZLpenTuEn .icon-shape .label{text-anchor:middle;}#mermaid-svg-g6HSgOlZLpenTuEn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-g6HSgOlZLpenTuEn .rough-node .label,#mermaid-svg-g6HSgOlZLpenTuEn .node .label,#mermaid-svg-g6HSgOlZLpenTuEn .image-shape .label,#mermaid-svg-g6HSgOlZLpenTuEn .icon-shape .label{text-align:center;}#mermaid-svg-g6HSgOlZLpenTuEn .node.clickable{cursor:pointer;}#mermaid-svg-g6HSgOlZLpenTuEn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-g6HSgOlZLpenTuEn .arrowheadPath{fill:#333333;}#mermaid-svg-g6HSgOlZLpenTuEn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-g6HSgOlZLpenTuEn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-g6HSgOlZLpenTuEn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-g6HSgOlZLpenTuEn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-g6HSgOlZLpenTuEn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-g6HSgOlZLpenTuEn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-g6HSgOlZLpenTuEn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-g6HSgOlZLpenTuEn .cluster text{fill:#333;}#mermaid-svg-g6HSgOlZLpenTuEn .cluster span{color:#333;}#mermaid-svg-g6HSgOlZLpenTuEn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-g6HSgOlZLpenTuEn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-g6HSgOlZLpenTuEn rect.text{fill:none;stroke-width:0;}#mermaid-svg-g6HSgOlZLpenTuEn .icon-shape,#mermaid-svg-g6HSgOlZLpenTuEn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-g6HSgOlZLpenTuEn .icon-shape p,#mermaid-svg-g6HSgOlZLpenTuEn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-g6HSgOlZLpenTuEn .icon-shape .label rect,#mermaid-svg-g6HSgOlZLpenTuEn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-g6HSgOlZLpenTuEn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-g6HSgOlZLpenTuEn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-g6HSgOlZLpenTuEn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Pre-Norm 现代LLM
x
LayerNorm
Attention
+
输出
Post-Norm 原始论文2017
x
Attention
+
LayerNorm
输出
关键区别:
- Post-Norm:残差加完之后再归一化。梯度必须"穿过" LayerNorm 才能走捷径。
- Pre-Norm :残差连接是"干净的"
x + F(LayerNorm(x)),梯度可以无阻碍地直接回传。
| 方案 | 优点 | 缺点 | 使用模型 |
|---|---|---|---|
| Post-Norm | 原始论文,理论表达能力更优 | 训练不稳定,必须用 warmup | BERT, 原始 Transformer |
| Pre-Norm | 训练稳定,不需要精细的 warmup | 理论上表达能力略弱 | GPT-2, Llama, Qwen |
📌 本书约定:4.1 节展示的是原始论文的 Post-Norm 结构(理解历史)。4.5 节及后续实战代码统一使用 Pre-Norm(对接现代实践)。
💡 Pre-Norm 的一个细节 :由于 Pre-Norm 把 LayerNorm 放在子层之前,最后一个 Block 的输出是未经 Norm 的残差。因此现代 LLM(GPT-2、Llama、Qwen)在所有 Block 结束后、送入 Linear Projection 之前,会额外加一个LayerNorm(代码中通常叫model.norm或ln_f)。这确保最终 Hidden State 的数值范围稳定。
4.5 Tensor Shape 的完整流程(Pre-Norm)
以 batch=2, seq_len=5, d_model=512 为例,这是现代 LLM 使用的 Pre-Norm 结构:
#mermaid-svg-SDa5vLyHkJM7qpJU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SDa5vLyHkJM7qpJU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SDa5vLyHkJM7qpJU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SDa5vLyHkJM7qpJU .error-icon{fill:#552222;}#mermaid-svg-SDa5vLyHkJM7qpJU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SDa5vLyHkJM7qpJU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SDa5vLyHkJM7qpJU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SDa5vLyHkJM7qpJU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SDa5vLyHkJM7qpJU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SDa5vLyHkJM7qpJU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SDa5vLyHkJM7qpJU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SDa5vLyHkJM7qpJU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SDa5vLyHkJM7qpJU .marker.cross{stroke:#333333;}#mermaid-svg-SDa5vLyHkJM7qpJU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SDa5vLyHkJM7qpJU p{margin:0;}#mermaid-svg-SDa5vLyHkJM7qpJU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SDa5vLyHkJM7qpJU .cluster-label text{fill:#333;}#mermaid-svg-SDa5vLyHkJM7qpJU .cluster-label span{color:#333;}#mermaid-svg-SDa5vLyHkJM7qpJU .cluster-label span p{background-color:transparent;}#mermaid-svg-SDa5vLyHkJM7qpJU .label text,#mermaid-svg-SDa5vLyHkJM7qpJU span{fill:#333;color:#333;}#mermaid-svg-SDa5vLyHkJM7qpJU .node rect,#mermaid-svg-SDa5vLyHkJM7qpJU .node circle,#mermaid-svg-SDa5vLyHkJM7qpJU .node ellipse,#mermaid-svg-SDa5vLyHkJM7qpJU .node polygon,#mermaid-svg-SDa5vLyHkJM7qpJU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SDa5vLyHkJM7qpJU .rough-node .label text,#mermaid-svg-SDa5vLyHkJM7qpJU .node .label text,#mermaid-svg-SDa5vLyHkJM7qpJU .image-shape .label,#mermaid-svg-SDa5vLyHkJM7qpJU .icon-shape .label{text-anchor:middle;}#mermaid-svg-SDa5vLyHkJM7qpJU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SDa5vLyHkJM7qpJU .rough-node .label,#mermaid-svg-SDa5vLyHkJM7qpJU .node .label,#mermaid-svg-SDa5vLyHkJM7qpJU .image-shape .label,#mermaid-svg-SDa5vLyHkJM7qpJU .icon-shape .label{text-align:center;}#mermaid-svg-SDa5vLyHkJM7qpJU .node.clickable{cursor:pointer;}#mermaid-svg-SDa5vLyHkJM7qpJU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SDa5vLyHkJM7qpJU .arrowheadPath{fill:#333333;}#mermaid-svg-SDa5vLyHkJM7qpJU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SDa5vLyHkJM7qpJU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SDa5vLyHkJM7qpJU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SDa5vLyHkJM7qpJU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SDa5vLyHkJM7qpJU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SDa5vLyHkJM7qpJU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SDa5vLyHkJM7qpJU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SDa5vLyHkJM7qpJU .cluster text{fill:#333;}#mermaid-svg-SDa5vLyHkJM7qpJU .cluster span{color:#333;}#mermaid-svg-SDa5vLyHkJM7qpJU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SDa5vLyHkJM7qpJU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SDa5vLyHkJM7qpJU rect.text{fill:none;stroke-width:0;}#mermaid-svg-SDa5vLyHkJM7qpJU .icon-shape,#mermaid-svg-SDa5vLyHkJM7qpJU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SDa5vLyHkJM7qpJU .icon-shape p,#mermaid-svg-SDa5vLyHkJM7qpJU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SDa5vLyHkJM7qpJU .icon-shape .label rect,#mermaid-svg-SDa5vLyHkJM7qpJU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SDa5vLyHkJM7qpJU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SDa5vLyHkJM7qpJU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SDa5vLyHkJM7qpJU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入
2, 5, 512
LayerNorm
2, 5, 512
Multi-Head Attention
2, 5, 512
残差 +
2, 5, 512
LayerNorm
2, 5, 512
FFN
内部扩展到 2, 5, 2048
再压缩回 2, 5, 512
残差 +
2, 5, 512
输出
2, 5, 512
关键点:整个 Block 的输入输出 Shape 都是 [batch, seq, d_model]。
4.6 TensorFlow 实现
python
import tensorflow as tf
class TransformerBlock(tf.keras.layers.Layer):
def __init__(self, d_model, num_heads, dff, dropout_rate=0.1):
super().__init__()
self.attention = tf.keras.layers.MultiHeadAttention(
num_heads=num_heads, key_dim=d_model // num_heads
)
self.ffn = tf.keras.Sequential([
tf.keras.layers.Dense(dff, activation='relu'),
tf.keras.layers.Dense(d_model)
])
self.norm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
self.norm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
self.dropout1 = tf.keras.layers.Dropout(dropout_rate)
self.dropout2 = tf.keras.layers.Dropout(dropout_rate)
def call(self, x, training=False, mask=None):
# Pre-Norm + Self-Attention + 残差
attn_output = self.attention(
self.norm1(x), self.norm1(x), attention_mask=mask
)
attn_output = self.dropout1(attn_output, training=training)
x = x + attn_output # 残差
# Pre-Norm + FFN + 残差
ffn_output = self.ffn(self.norm2(x))
ffn_output = self.dropout2(ffn_output, training=training)
x = x + ffn_output # 残差
return x
# 测试
block = TransformerBlock(d_model=512, num_heads=8, dff=2048)
x = tf.random.normal([2, 5, 512])
output = block(x)
print(output.shape) # (2, 5, 512)
4.7 多个 Block 堆叠
python
class TransformerEncoder(tf.keras.layers.Layer):
def __init__(self, num_layers, d_model, num_heads, dff):
super().__init__()
self.blocks = [
TransformerBlock(d_model, num_heads, dff)
for _ in range(num_layers)
]
def call(self, x, training=False):
for block in self.blocks:
x = block(x, training=training)
return x
encoder = TransformerEncoder(num_layers=6, d_model=512, num_heads=8, dff=2048)
x = tf.random.normal([2, 5, 512])
output = encoder(x)
print(output.shape) # (2, 5, 512)
4.7.1 每层的参数是独立的
注意上面的代码:for _ in range(num_layers) 创建了 6 个独立的 Block。
这意味着:
text
Layer 1:Wq₁, Wk₁, Wv₁, FFN₁ ← 一套独立参数
Layer 2:Wq₂, Wk₂, Wv₂, FFN₂ ← 另一套独立参数
Layer 3:Wq₃, Wk₃, Wv₃, FFN₃ ← 又一套独立参数
...
每一层的 WQW_QWQ、WKW_KWK、WVW_VWV 和 FFN 都是独立训练的,互不共享。
这解释了为什么不同层会学到不同层次的特征:
| 层次 | 学到的内容 | 类比 |
|---|---|---|
| 浅层(Layer 1-3) | 词法、局部搭配 | 认识每个字 |
| 中层(Layer 4-8) | 语法、语义关系 | 理解句子结构 |
| 深层(Layer 9-12) | 抽象语义、推理 | 理解言外之意 |
如果所有层共享同一套 WQW_QWQ、WKW_KWK、WVW_VWV,那每一层做的事情都一样------相当于同一层重复 6 次,表达能力大幅下降。
💡 这也是为什么 Transformer 越大(层数越多)越强:更多独立的层 = 更多层次的理解。GPT-3 有 96 层 = 96 套独立的 Attention + FFN 参数。
4.8 一层 Block 有多少参数?
以 d_model=512, num_heads=8, dff=2048 为例:
| 组件 | 参数 | Shape | 参数量 |
|---|---|---|---|
| Multi-Head Attention W_Q | 8个头拼成一个 | 512, 512 | 262,144 |
| Multi-Head Attention W_K | 同上 | 512, 512 | 262,144 |
| Multi-Head Attention W_V | 同上 | 512, 512 | 262,144 |
| Output Projection W_O | 512, 512 | 262,144 | |
| Attention 小计 | 1,048,576 ≈ 105万 | ||
| LayerNorm 1 (γ, β) | 512 + 512 | 1,024 | |
| FFN W_1 | 512, 2048 | 1,048,576 | |
| FFN W_2 | 2048, 512 | 1,048,576 | |
| FFN 小计 | 2,097,152 ≈ 210万 | ||
| LayerNorm 2 (γ, β) | 512 + 512 | 1,024 | |
| 一层 Block 总计 | ≈ 315万 |
整个 Transformer 的参数公式
总参数=vocab_size×dmodel⏟Embedding+M×(Attention+FFN+LayerNorm)⏟M层Block+dmodel×vocab_size⏟输出层LM Head\text{总参数} = \underbrace{\text{vocab\size} \times d{model}}{\text{Embedding}} + \underbrace{M \times (\text{Attention} + \text{FFN} + \text{LayerNorm})}{\text{M层Block}} + \underbrace{d_{model} \times \text{vocab\size}}{\text{输出层LM Head}}总参数=Embedding vocab_size×dmodel+M层Block M×(Attention+FFN+LayerNorm)+输出层LM Head dmodel×vocab_size
以 BERT-Base(vocab=30000, d_model=768, 12层)为例:
text
Embedding: 30000 × 768 ≈ 23M
12层Block: 12 × ~7M ≈ 85M
LM Head: 768 × 30000 ≈ 23M(通常与Embedding共享,不额外计算)
──────────────────────────
总计 ≈ 110M
💡 记忆要点:
- FFN 的参数量约是 Attention 的 2倍(因为 dff = 4 × d_model)
- 一层 Block 中,FFN 占 2/3 参数,Attention 占 1/3
- LayerNorm 参数极少,可忽略
Encoder-Only vs Decoder-Only 参数区别
| 架构 | 一层包含 | 参数量对比 |
|---|---|---|
| Encoder Layer(BERT) | Self-Attention + FFN | 基准 |
| 原始 Decoder Layer(T5) | Self-Attention + Cross-Attention + FFN | 多了一套 Attention(约+33%) |
| GPT/Qwen/Llama Decoder Layer | Masked Self-Attention + FFN(无Cross-Attention) | 和 Encoder 一样 |
📌 现代 GPT/Qwen/Llama 的 Decoder Layer 参数量和 Encoder Layer 基本相同------因为它删掉了 Cross-Attention。它和 Encoder 的唯一区别是 Attention 时有 Causal Mask。
4.9 Hidden State------Block 中真正流动的数据
学完了Block的所有组件后,我们需要回答一个更本质的问题:
Transformer 里面,到底是什么东西在一层一层地流动?
答案不是 Q、K、V,不是 Attention Matrix,甚至不是 Embedding------而是 Hidden State(隐藏状态)。
4.9.1 Embedding 只存在于第一层
text
Token IDs
│
Embedding Layer(只执行一次)
│
▼
H₀ ← 这就是初始 Hidden State
│
Block 1
│
▼
H₁ ← 第1层处理后的 Hidden State
│
Block 2
│
▼
H₂
│
...
│
▼
H₁₂ ← 最终 Hidden State(送去预测/分类)
从 Block 1 开始,再也没有 Embedding 了。每一层的输入都是上一层输出的 Hidden State。
4.9.2 Q/K/V 是临时变量,Hidden State 才是持久数据
text
每一层的生命周期:
H_i ──→ 计算 Q, K, V(临时)
│
▼
Attention(临时)
│
▼
+ Residual + Norm
│
▼
FFN(临时)
│
▼
+ Residual + Norm
│
▼
H_{i+1} ──→ 传递给下一层
| 数据 | 生命周期 | 角色 |
|---|---|---|
| Hidden State | 从第0层一直传到最后一层 | 正式文档(持续更新) |
| Q, K, V | 本层计算完就丢弃 | 草稿纸(用完即扔) |
| Attention Matrix | 本层计算完就丢弃 | 中间结果 |
| Context Vector | 本层计算完就丢弃 | 中间结果 |
精确定义 :Hidden State 在一个 Block 内部经过两次"更新提交"------Attention 后一次、FFN 后一次------但只有 Block 完整结束后的输出才算作正式的 Hi+1H_{i+1}Hi+1:
text
H_i(Block输入)
│
├─ Attention → Add → Norm → 中间状态(Intermediate)
│ ↓
└─────────────────── FFN → Add → Norm → H_{i+1}(Block输出)
中间状态(Attention+Norm后、FFN之前)不算独立的一层 Hidden State------它只是 Block 内部正在加工中的数据。
💡 这也解释了为什么每层的 W_Q/W_K/W_V 必须独立(4.7.1节):因为每层接收的 Hidden State 已经不同了------它已经被上一层加工过,携带了更丰富的语义。基于不同的输入,当然需要不同的投影参数来提取有效的 Q/K/V。
4.9.3 重新理解 Transformer:Hidden State 演化系统
如果只用一句话定义 Transformer:
Transformer 是一个不断迭代 Hidden State 的系统。
| 组件 | 对 Hidden State 做了什么 |
|---|---|
| Embedding | 创建初始 H₀ |
| Attention | 让 H 吸收其他 Token 的信息(全局交互) |
| FFN | 让 H 进行内部加工和抽象(独立思考) |
| Residual | 保留旧 H,叠加新信息(增量更新) |
| LayerNorm | 稳定 H 的数值范围(便于下一层处理) |
text
H₀ ──Attention──→ 吸收上下文 ──FFN──→ 独立思考 ──→ H₁
H₁ ──Attention──→ 更深理解 ──FFN──→ 更深抽象 ──→ H₂
...
H₁₁──Attention──→ 最终理解 ──FFN──→ 最终抽象 ──→ H₁₂
每一层的 Hidden State 都比上一层更接近模型对这句话真正的理解。
📌 后面第11章会展示:不同层的 Hidden State 确实编码了不同层次的特征(浅层=词法,中层=语义,深层=推理)。第14章会讲 Hidden State 还编码了当前语言、角色、任务等信息。
4.9.4 另一种视角:Transformer 在语义空间中移动点
如果把每个 Token 的 Hidden State 想象成高维空间中的一个"点",那么整个 Transformer 可以理解为:
不断把每个 Token 的"语义坐标"移动到越来越准确的位置。
text
bank 的 Embedding → 初始坐标(模糊:可能是银行也可能是河岸)
│
经过多层 Transformer Block
│
bank 的最终 Hidden State → 最终坐标(精确:金融银行区域)
从这个视角看,Block中的四个组件就是四种不同的移动方式:
| 组件 | 移动方式 | 类比 |
|---|---|---|
| Attention | 参考其他Token的位置,决定自己应该往哪个方向移动 | 问路:附近的人告诉我怎么走 |
| FFN | 根据自身当前位置,做一次内部判断和调整 | 看地图:结合自己的目标再调整方向 |
| Residual | 不要一步跳太远,在旧位置基础上平滑移动 | 小步走:每次只移动一小段 |
| LayerNorm | 保持所有维度的数值在合理范围 | 校准:防止某个方向走得过远 |
这个视角解释了为什么:
- 同一个词在不同上下文中有不同含义:同一个初始坐标,因为周围Token不同(Attention方向不同),最终移动到了不同区域
- 最后 Linear Projection 能预测下一个词:最终坐标和词表中哪个 Token 的 Embedding 最近,就输出哪个
- 维度没有固定含义(不是"第1维=语法,第2维=颜色"):是训练自然形成的连续空间,没有人工设计的对应关系
本章总结
一个 Transformer Block = 4 个组件:
#mermaid-svg-Rjtg9bxWlpWfy0OZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .error-icon{fill:#552222;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .marker.cross{stroke:#333333;}#mermaid-svg-Rjtg9bxWlpWfy0OZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Rjtg9bxWlpWfy0OZ p{margin:0;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge{stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section--1 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section--1 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section--1 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section--1 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section--1 text{fill:#ffffff;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth--1{stroke-width:17;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-0 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-0 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-0 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-0 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-0 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-0{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-0{stroke-width:14;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-1 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-1 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-1 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-1 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-1 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-1{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-1{stroke-width:11;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-2 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-2 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-2 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-2 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-2 text{fill:#ffffff;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-2{stroke-width:8;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-3 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-3 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-3 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-3 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-3 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-3{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-3{stroke-width:5;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-4 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-4 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-4 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-4 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-4 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-4{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-4{stroke-width:2;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-5 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-5 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-5 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-5 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-5 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-5{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-5{stroke-width:-1;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-6 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-6 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-6 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-6 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-6 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-6{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-6{stroke-width:-4;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-7 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-7 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-7 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-7 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-7 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-7{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-7{stroke-width:-7;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-8 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-8 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-8 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-8 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-8 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-8{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-8{stroke-width:-10;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-9 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-9 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-9 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-9 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-9 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-9{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-9{stroke-width:-13;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-10 rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-10 path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-10 circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-10 polygon,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-10 text{fill:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .node-icon-10{font-size:40px;color:black;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge-depth-10{stroke-width:-16;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:lightgray;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .disabled text{fill:#efefef;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-root rect,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-root path,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-root circle,#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-root text{fill:#ffffff;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-root span{color:#ffffff;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .section-2 span{color:#ffffff;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .edge{fill:none;}#mermaid-svg-Rjtg9bxWlpWfy0OZ .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-Rjtg9bxWlpWfy0OZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Transformer Block
Multi-Head Attention
让Token互相交流
全局信息聚合
Residual
防止梯度消失
保留原始信息
LayerNorm
稳定训练
加速收敛
Feed Forward
非线性变换
维度扩展再压缩
每个模块的角色区分
| 模块 | 做什么 | Token之间会交换信息吗? | 数学操作类型 |
|---|---|---|---|
| Multi-Head Attention | 根据相关性从其他Token拉取信息 | ✅ 会 | 矩阵乘法(QK^T, ×V) |
| Residual Add | 保留原始表示,叠加新信息 | ❌ | 逐元素加法 |
| LayerNorm | 稳定数值分布,便于训练 | ❌ | 归一化(减均值除标准差) |
| Feed Forward | 对每个Token独立做非线性变换 | ❌ | 矩阵乘法 + 激活函数 |
💡 记忆要诀 :一个 Block 中,只有 Attention 涉及 Token 之间的信息交换。其他三个模块(Residual、LayerNorm、FFN)都是对每个 Token 独立操作的。
Transformer 中三种数学操作的角色
| 操作 | 在 Transformer 中的作用 | 例子 |
|---|---|---|
| 矩阵乘法 | 按可学习的规则重新组合、提取特征 | Q=XW_Q, Attention×V, FFN |
| 逐元素加法 | 保留旧信息,叠加新信息(增量修改) | x + Attention(x), x + FFN(x) |
| 归一化 | 调整数值分布到稳定范围 | LayerNorm |
最重要的一点:Block 的输入输出 Shape 相同,所以可以任意堆叠。
本章思考题
- 为什么 Block 的输入输出 Shape 必须相同?
- Pre-Norm 和 Post-Norm 在训练稳定性上有什么区别?
- 如果去掉残差连接,会发生什么?
- 为什么说 Q/K/V 是"临时变量"而 Hidden State 是"持久数据"?如果把上一层的 Q/K/V 直接传给下一层使用(不重新计算),会有什么问题?
- FFN 内部为什么要先扩展维度再压缩?
下一章预告
下一章我们讲 Attention 的思想。
不用公式,只讲:
- 为什么会想到 Attention?
- Attention 解决了什么问题?
- 为什么叫 Query、Key、Value?