把注意力和 FFN 一层层直接叠起来,叠深了会怎样?
本课一问:把注意力和 FFN 一层层直接叠起来,叠深了会怎样?
这一课先不碰:把残差流拉回稳定尺度的归一化(L3)、Post-LN 为什么离不开 warmup(C8)、把一条残差流加宽成 4 条的新做法(C15)。
② 从已有出发
「小明把苹果给了小王」的 5 个 token,在 Qwen3.8 里是一个 [5 × 5120] 的矩阵。一个块里有两种子层:注意力([T × d] → [T × d])和 FFN([T × d] → [T × d]),形状进出一样,所以可以一层接一层地叠——Qwen3.8 叠了 64 层,这 5 行要连续穿过 128 个子层。最直接的叠法是:上一个子层的输出,就是下一个子层的输入。
下面的模拟器不用这 5 个 token,而用随机向量和随机初始化的网络,原因是:这一课要看的是「堆叠方式」本身的性质(梯度、token 会不会趋同),和具体内容无关;随机初始化正是训练开始那一刻网络的真实状态。
③ 先自己设计:直接堆叠行不行?
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
这个实验不在 Transformer 上,而在图像分类网络上——但它第一次把「深了反而更差」量化了出来(ImageNet 验证集 top-1 错误率,10-crop):
| 18 层 | 34 层 | |
|---|---|---|
| 直接堆叠(plain) | 27.94% | 28.54% |
这两个网络都带 BatchNorm,作者专门检查过:前向信号和反向梯度都没有消失 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条He et al. 2015 §4.1 与 Table 2;作者写明 plain 网络训练时梯度范数正常,34 层的训练误差在整个训练过程中都高于 18 层。只在 ImageNet 与他们的 CNN 上测过。 出处He et al. 2015 Table 2 ↗需联网 。深度本身成了障碍。
同一篇论文,只把每两层包成 x + F(x),参数一个不多:
| 18 层 | 34 层 | |
|---|---|---|
| 直接堆叠 | 27.94% | 28.54% |
| 残差 | 27.88% | 25.03% |
加了残差,34 层反过来比 18 层好 2.85 个百分点。多出来的层现在「什么都不做」只需要让 F(x) ≈ 0,这比让一叠非线性层恰好拼出恒等映射容易得多。
Transformer 里有两个同样的问题,可以在浏览器里亲手复现(下面的网络都是随机初始化、没有训练,用来看结构本身的性质):
- 梯度能不能传到底层:直接堆 32 个子层,把初始化尺度 gain 从 0.5 拖到 2.0,第 1 层收到的梯度与顶层之比从 1.4 × 10⁻²⁰ 一路变到 2.9 × 10³——23 个数量级,只有很窄的一段既不消失也不爆炸。
- token 会不会变成一样:只用注意力、直接堆叠时,每一层都在对前面的 token 取加权平均。6 个 token 离「全部相同」的相对距离从 0.924 起步,8 层后剩 5.8 × 10⁻³,32 层后只剩 3.2 × 10⁻¹⁰——每个位置都成了同一个向量,后面再多的层也分不出谁是谁 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条Dong et al. 2021 证明:没有残差、也没有 MLP 时,自注意力的输出会以双指数速度收敛到秩 1(所有行相同)。下面组件的设置与论文不同(随机 Q/K/V、因果掩码),只演示同一方向的现象。 出处Dong et al. 2021 ↗需联网 。
口径:浏览器实时计算。权重由固定种子生成(随机初始化,没有训练),所以每次打开结果相同;换 N 或 gain 会重新生成整套权重。
试三件事:① 先只看红色(朴素堆叠)那一排,把 gain 从 0.5 拖到 2.0,看右边梯度柱从「底层几乎没有」变成「底层大得离谱」,再看最下面那条红线的形状——它就是「刀刃」;② 绿色那一排只开「残差」,再拖一遍 gain:绿线始终在 1 以上,梯度不会消失,但会越传越大,左边的残差流 RMS 也从 1 涨到 6 以上;③ 切到「token 会不会变成一样」:N = 32 时红线一路掉到 3.2 × 10⁻¹⁰(把 N 拖到 8,是 5.8 × 10⁻³);只开残差时绿线掉得慢得多,但 32 层后仍到 0.026;再把「写回乘 1/√N」和「子层输入先 RMSNorm」都勾上,是 0.828,6 个 token 基本保持不同。
④ 改进到现代做法
第 1 步:残差,x + F(x)
极小真数字:两层、标量。 设每个子层都是 F(x) = 0.5·x,输入 x₀ = 1。
- 直接堆叠:x₁ = 0.5,x₂ = 0.25;dx₂/dx₀ = 0.5 × 0.5 = 0.25。层数翻到 32,就是 0.5³² ≈ 2.3 × 10⁻¹⁰。
- 残差:x₁ = 1 + 0.5 = 1.5,x₂ = 1.5 + 0.75 = 2.25;dx₂/dx₀ = (1 + 0.5)(1 + 0.5) = 2.25 = 1 + 0.5 + 0.5 + 0.25。
右边四项正好是梯度的四条路:两层都跳过(1)、只经过第 1 层(0.5)、只经过第 2 层(0.5)、两层都经过(0.25)。直接堆叠只剩最后一条;残差把「都跳过」那条留住了,所以梯度不会消失 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条(1 + J₂)(1 + J₁) = 1 + J₁ + J₂ + J₂J₁;L 层时展开成 2^L 条路径,恒有长度为 0 的那一条。 出处本页推导 ↗ 。
「高速公路」这个说法怎么用才不出错。
- 精确映射:主路 = x 这一项(不经过任何参数);匝道 = 每个子层 F;汇入 = 加法;「车流直达」= 展开式里的 I·I·…·I 那一项,梯度可以不经过任何子层到达底层。
- 失效点:① 高速公路上的车不会越走越多,残差流会——每个子层都往里加东西,前向时它的尺度随深度增长(下面第 3 步);② 直通不等于梯度大小刚好——组件里只开残差时,底层梯度反而是顶层的 20 倍(gain = 1、N = 32);③ He 2015 专门检查过,他们的 plain 网络梯度并没有消失,残差的好处首先是让优化器容易找到「每层只改一点」的解,而不只是「防梯度消失」。
第 2 步:新的失败——残差流越加越大
x_L = x₀ + Σ F_l 这个展开式也说明了代价:每个子层都在往同一条流里加东西。如果 128 次写入各自方差为 1、彼此独立,方差会相加:最后的标准差是 √(1 + 128) = √129 = 11.36,比输入大一个数量级 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条独立随机变量之和的方差等于方差之和:Var(x₀ + ΣF) = 1 + 128 × 1 = 129。「独立、方差为 1」是为了算清量级的假设,真实写入之间并不独立。 出处待补 。组件里只开残差时也是这样:32 个子层之后残差流 RMS 从 1 变成 6.3,梯度也被放大到 20 倍。
后果:越往上的层,看到的输入尺度越大;同一个 F 在不同层面对的是完全不同量级的数。两种补救一起用:
- 写得小一点:GPT-2 把残差支路输出投影的初始化乘以 1/√N(N 为残差层数) 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条GPT-2 报告 §2.3:A modified initialization which accounts for the accumulation on the residual path——按 1/√N 缩放,让 N 次写入累加后的方差不随深度增长。这是设计动机,报告没有给消融。 出处GPT-2 报告 §2.3 ↗ 。我们的项目也这样做:
model.py里带is_residual_out的投影按 0.02/√(2 × 4) = 0.00707 初始化(4 层 × 每层 2 个子层)。在上面的组件里(「梯度传到哪」,N = 32、gain = 1)把「子层输入先 RMSNorm」和「写回乘 1/√N」都勾上,底层与顶层的梯度之比回到 0.97,残差流 RMS 停在 1.1。 - 读之前先归一化:每个子层读残差流之前先把尺度拉回来——这是下一课。
第 3 步:回到 token 趋同
切到组件的「token 会不会变成一样」:只开残差,32 层后相对距离是 0.026(两两余弦平均 0.999),比直接堆叠的 10⁻¹⁰ 好得多,但仍在收敛;三个开关全开(残差 + 先 RMSNorm + 写回乘 1/√N)时是 0.828,余弦平均 0.162,6 个 token 基本保持各自的样子。Dong 等还证明 MLP 也能阻止这种退化——FFN 和残差在这里是互相配合的 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条Dong et al. 2021:skip connection 与 MLP 都能阻止纯注意力的秩坍缩(在其假设下的分析 + 在标准 Transformer 变体上的实验)。 出处Dong et al. 2021 ↗需联网 。
残差在一个块里的样子
演进图:本课在第几代
Qwen3.8-27B 仍然用普通残差;把残差加宽是 2026 年正在形成的共识苗头,具体怎么加宽各家分歧很大 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条R3 §3.5:mHC(DeepSeek V4 / V4.1、GLM-5.3-Flash)、iHC(Hy4)、Gated Residual(Qwen3.8-Flash-Next,4 条流)、AttnRes(Kimi K3);各家的收益都是自报。Qwen3.8-Flash-Next 报告的消融:pre-norm 50.91 → mHC 动态 54.47 → Gated Residual 54.66(25B-A3B,560B token)。 出处mHC(DeepSeek 2025) ↗需联网 ,放到 C15 讲。
⑤ 项目实测
项目基线是 4 层、每层 2 个子层;对照组只把两处 x + 去掉,其余(Pre-Norm、最终 norm、数据、种子、步数)全部相同。另有 12 层的一对,看深度加大后差距怎么变。
读图(2026-09-26 导出的数据,以组件显示为准):
- 去掉残差,4 层和 12 层的 val loss 都停在 6.627,几乎贴着图里的虚线——虚线 6.625 是「完全不看上下文、只按训练集字频猜」的交叉熵。四条卡住的曲线连训练 loss 的尾巴都逐位相同:这些模型只学会了字频。
- 训练结束时,4 层无残差模型最底层块收到的梯度只有最顶层的 3.7 × 10⁻⁷,12 层是 1.5 × 10⁻⁸;有残差的基线是 2.2 倍(底层反而略大)。12 层无残差模型前 100 步 grad_norm 的最大值是 183,基线是 3.2。
- 残差流确实越加越大:基线训练后从 embedding 之后的 0.057 涨到最后一次写入之后的 1.46;12 层有残差是 0.052 → 4.17。这正是下一课要处理的。
- 12 层有残差(1,001.7 万参数)val loss 4.732,比 4 层基线还高;它的训练 loss 也更高(4.06 对 3.56),两条曲线在第 400 步都还在降——更深的模型在按 4 层基线定的 400 步里还没训到位,不是残差的问题。
⑥ ⚠ 常见误解
「残差只是为了防梯度消失」✗ —— He 2015 的 plain 网络带 BatchNorm,梯度范数正常,34 层仍然比 18 层差。残差首先改变的是「默认解」:F = 0 就是恒等,每层只需要学一个增量;梯度直通路是它的另一个好处,而且只开残差时梯度还可能被放大。
「残差是把输入复制一份拼在后面」✗ —— 是逐元素相加,不是拼接(拼接是 DenseNet 的做法)。所以每个子层的输出必须和输入一样宽:Qwen3.8 的注意力先升到 6,144 维、FFN 先升到 17,408 维,最后都要投影回 5,120 维才能加回去。
「有了残差,层数越多越好」✗ —— 残差流越加越大,靠后的层写入的增量在总和里占比越来越小;Pre-Norm 结构下深层的贡献会被稀释,这是 C8 和 C15 的话题。
⑦ 证据三问
- 它解决什么问题? 深网络比浅网络更难训(ResNet 的退化实验),纯注意力堆叠会让所有 token 趋同。
- 数学上为什么可能有效? 展开式 x_L = x₀ + Σ F 与雅可比矩阵里的 I 都是可证明的:梯度总有一条不经过任何子层的路 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条∂x_(l+1)/∂x_l = I + ∂F_l/∂x_l,连乘后恒含 I。 出处待补 ;「学增量比学恒等容易」是 He 等的理论动机,不是定理 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条ResNet §3.1 的假设:if an identity mapping were optimal, it would be easier to push the residual to zero。 出处He et al. 2015 §3.1 ↗需联网 。
- 实验上为什么最后选了它? ResNet 的 ImageNet 对照(34 层:28.54% → 25.03%) 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条ImageNet 验证集 top-1,10-crop;参数量相同。 出处He et al. 2015 Table 2 ↗需联网 ,以及此后几乎所有深层 Transformer;我们项目里去掉残差,4 层就只学会了字频(6.627 对 4.626) 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条04-实践项目 c4_nores 与基线只差 model.residual 一项;单种子,差值 2.0 远超噪声底线(C14 实测同配置 5 次重跑极差 0.016);只在 3.7M 参数、0.5M token 规模上成立。 出处本章实验课 ↗ 。
⑧ 一句话
残差让每层只学一个增量:输出 = 输入 + 改动,梯度因此总有一条不经过任何子层的直通路。
⑨ 下一个缺口
残差留住了直通路,却让残差流越加越大:128 次写入之后标准差可以到 11.36,越往上的层看到的输入越大。能不能让每个子层在读残差流之前,先把它的尺度拉回同一个范围?下一课:归一化在做什么。
⑩ 你可能会问
- 「为什么 GPT-2 的缩放是 1/√N,我们项目里是 1/√(2 × 层数)?」 —— 报告说 N 是「残差层数」;每个块里有注意力、FFN 两个残差支路,所以 4 层就是 8 个残差层,0.02/√8 = 0.00707。
- 「现代模型还在用这种最普通的残差吗?」 —— Qwen3.8-27B、Qwen3 系列都是;加宽成多条流、跨层注意力是 2025–2026 年的新方向,见演进地图与 C15。
- 「Post-LN 和 Pre-Norm 对残差有什么不同?」 —— 下一课会给你看两种摆法;「为什么 Pre-Norm 更稳」要等 C8 讲完初始化和 warmup 才能讲透。
🔍 先透露一点
Post-LN 把 LayerNorm 放在加法之后、主路之上,于是从第 1 层到最后一层之间没有一条只做加法的直通路——本课的展开式 x_L = x₀ + Σ F 在 Post-LN 里不成立。Xiong 等 2020 从这一点出发分析了为什么它需要 warmup。