状态:草稿 (2026-10-13),部分实测。 第 4 节的实验是在笔记本电脑 CPU(Python 3.9,PyTorch 2.8)上直接运行测得的值(
code/02_residual.py, 约 7 分钟)。论文中的数值已连同条件一起从原文引用。 编写规则:以实测数据为基础,无法测量的标注为“未实测”。
目录
1. 深度悖论
第 1 篇中的 AlexNet 有 8 层。理论上,堆叠更多层可以学习更复杂的模式,因此效果应该更好。然而,He 等人在 2015 年报告了相反的现象。在单纯堆叠卷积的网络(plain)中,ImageNet 验证集 top-1 误差(10 个切片的平均值)表现如下。
| 网络 | 18 层 | 34 层 |
|---|---|---|
| 单纯堆叠网络 | 27.94% | 28.54%(更差) |
| ResNet(残差连接) | 27.88% | 25.03% |
(论文表 2.)重要的一点是,34 层的 plain 网络的 训练误差也 比 18 层更高。如果只是考试表现差,那是过拟合(死记硬背);但如果连训练数据上的表现也很差,就说明是“优化失败”。
这很奇怪。34 层网络本可以模仿 18 层网络——只需完整复制 18 层的权重,然后让其余 16 层变为“将输入原封不动输出的层(恒等函数)”即可。因此,深层网络至少应该和浅层网络表现一样好。然而,梯度下降法却没能找到这个解。要让多层非线性变换精确成为恒等函数,调整权重比想象中要困难得多。
2. 残差连接:只学习差值
ResNet 的核心思想只有一句话:不要让模块去学习输出 H(x) 的全部,而是只去学习 需要加到输入上的差值 F(x) = H(x) − x 。
그냥 쌓은 블록: y = F(x)
잔차 블록: y = x + F(x) (F = 합성곱 두세 층)
这样做使得恒等函数变得容易实现。只要将 F 的权重设在 0 附近,就会变成 y = x 。即使堆叠得很深,也可以从“不需要的模块什么也不做”的状态开始。由于跳跃连接(skip connection)的计算只是单纯的加法,因此几乎不增加任何参数和计算时间。
梯度流
观察反向传播过程中发生了什么,就能更清楚地理解这种设计为什么行之有效。在单纯堆叠的网络中,前面层的梯度是通过将后面各层的导数 相乘 得到的。如果相乘的值略小于 1,梯度就会消失为 0(梯度消失);如果略大于 1,梯度就会爆炸。
正如同一作者的后续论文(Identity Mappings, 2016)所证明的那样,如果堆叠 L 个残差模块,结果将是:
x_L = x_l + Σ_{i=l..L-1} F(x_i)
∂E/∂x_l = ∂E/∂x_L · ( 1 + ∂/∂x_l Σ F(x_i) )
括号内的 1 是核心。损失的梯度 ∂E/∂x_L 不经过任何权重,直接完整地传递到了前面层。由于第二项在整个小批量(mini-batch)中恰好等于 −1 的可能性很低,论文解释称,无论权重多么小,梯度都不会消失。乘法链条变成了加法链条。
该论文采用了一种在加法之后不放置激活函数的“预激活”顺序(归一化 → ReLU → 卷积),使捷径保持完全干净,从而在 CIFAR-10 上成功训练了 1001 层 的网络,达到了 4.62% 的错误率(小批量为 64,5 次运行的中位数。若小批量为 128 则为 4.92%)。相同深度的原顺序 ResNet 的错误率为 7.61%。
3. 批归一化
ResNet 模块中的每个卷积层都附带了 批归一化(Batch Normalization, BN)。它在一个小批量内减去每个通道的均值并除以标准差,然后通过两个可学习的参数(γ, β)进行重新缩放和平移。
x̂ = (x − 배치평균) / √(배치분산 + ε)
y = γ · x̂ + β
在推理时,不使用批次统计量,而是使用在训练过程中收集的滑动平均值。
原论文的解释(2015)。 Ioffe 和 Szegedy 认为,如果在训练过程中前面层的权重发生变化,后面层接收到的输入分布就会不断变化(“内部协变量偏移”),因此必须使用较小的学习率。如果通过归一化固定分布,就可以使用较大的学习率。效果非常显著:Inception 达到相同准确率(验证集 72.2%)需要 3100 万步,而加入 BN 的版本只需要 210 万步(论文中的“减少 14 倍步数”)。6 个 BN 网络的集成(ensemble)在 ImageNet 验证集上的 top-5 错误率为 4.9%,测试集为 4.82%。
后续研究的解释(2018)。 Santurkar 等人反驳称,BN 的效果与分布稳定性并没有太大关系。即使在 BN 层后面故意加入随时间变化的噪声来扰乱分布,性能也几乎保持不变,并且他们还通过测量指出 BN 可能并未减少内部协变量偏移。相反,他们通过理论和实验证明,BN 能够 使损失地形变得平滑 (改善损失和梯度的 Lipschitz 性质),从而使梯度指向更可靠的方向。
这是一个关于“为什么有效”的解释后来发生改变的好例子。实操中的结论是一样的:BN 使大进阶学习率和深层网络的训练变得容易。不过,正如接下来的实验所示, 仅靠 BN 并不能解决深度问题。
4. 动手尝试:直接堆叠 vs 残差,有无归一化
这是一个将卷积替换为宽度为 32 的全连接层的玩具实验(Toy Experiment)。使用 SGD + 动量训练了 500 步,任务是将二维点分为两个螺旋的分类任务(512 个点)。每个网络在 0.01、0.03、0.1 的学习率中选择最好的一个(如果固定一个学习率,选择对哪个网络有利的值会决定结论),结果为 3 个随机种子(seed)的中位数。残差模块将第二层权重初始化为 0,使之在最初成为恒等函数。
| 网络 | 深度 | 起始时刻第一层梯度 | 最终损失 | 训练准确率 |
|---|---|---|---|---|
| 单纯堆叠 | 4 | 3.1×10⁻² | 0.000 | 1.000 |
| 单纯堆叠 | 16 | 1.2×10⁻² | 0.028 | 0.996 |
| 单纯堆叠 | 64 | 9.5×10⁻³ | 0.692 | 0.520 |
| 残差 | 4 | 3.2×10⁻² | 0.000 | 1.000 |
| 残差 | 16 | 4.1×10⁻² | 0.577 | 0.855 |
| 残差 | 64 | 3.5×10⁻² | 0.692 | 0.520 |
| 单纯堆叠 + BN | 4 | 3.4×10⁻¹ | 0.000 | 1.000 |
| 单纯堆叠 + BN | 16 | 1.4 | 0.000 | 1.000 |
| 单纯堆叠 + BN | 64 | 1.1×10⁴ | 0.489 | 0.588 |
| 残差 + BN | 4 | 3.2×10⁻² | 0.000 | 1.000 |
| 残差 + BN | 16 | 4.1×10⁻² | 0.000 | 1.000 |
| 残差 + BN | 64 | 3.5×10⁻² | 0.000 | 1.000 |
(实测 2026-10-13,笔记本 CPU。准确率 0.5 相当于抛硬币水平。损失 0.692 ≈ ln 2 相当于“什么都没学到”。)
阅读方法。
- 单纯堆叠的 64 层网络未能训练。 在此实验中,由于 He 初始化,梯度并没有变得极小(第一层梯度约为 4 层的 1/3),但损失依然没有下降。这是一种无法仅用“梯度消失”来解释的优化困难,也就是第 1 节中的悖论。
- 即使加上 BN,单纯堆叠的 64 层网络也失败了,且第一层梯度放大了 1 万倍。 深层 plain 网络中 BN 反而放大了梯度的现象,与后续理论研究所指出的方向一致(本文中未单独验证该研究)。
- 残差 + BN 在 4、16、64 层上的准确率全部达到了 1.000 ,并且起始时刻的梯度也与深度无关,保持相似。捷径将梯度的大小与深度解耦了。
- 没有归一化的残差网络从 16 层开始变得不稳定。 观察学习曲线可以发现,损失下降后有时会突然弹起并停留在 0.69(seed 0,学习率 0.03)。这似乎是因为通过捷径累加的值在各层叠加,导致激活值变大。这一结果展示了实际 ResNet 与 BN 一起使用的原因。
由于是玩具实验,无法直接推广到实际的 ImageNet 规模。不过,“深度 + 捷径 + 归一化”的职责分工与论文方向一致。
5. 论文数值
| 项目 | 值(论文) | 条件 |
|---|---|---|
| ILSVRC 2015 分类第一名 | top-5 误差 3.57% | ImageNet 测试服务器,不同深度的 6 个模型集成 |
| ResNet-152 单个模型 | top-5 4.49% | 验证集 |
| 计算量 | ResNet-152 113 亿 FLOPs,VGG-19 196 亿 | 以乘加运算为基准 |
| CIFAR-10 | 110 层 6.43%(5 次中最佳,平均 6.61),1202 层 7.93% | 1202 层训练误差低于 0.1% — 过拟合 |
| COCO 检测 | mAP@[.5,.95] 21.2 → 27.2(相对 28%) | 将 Faster R-CNN 的主干从 VGG-16 换为 ResNet-101,COCO 验证集 |
152 层计算量小于 VGG-19(19 层)的原因在于 瓶颈模块(Bottleneck Block) 。通过 1×1 卷积减少通道数,通过 3×3 进行计算,再通过 1×1 放大。开销较大的 3×3 只在较少的通道上运行。ResNet-50/101/152 都使用了这个模块。
最后一行具有超出本文范围的意义。仅将为分类训练的主干网络(backbone)插入检测器中,检测性能就得到了大幅提升。此后,几乎所有的检测与分割模型(第 5、6、8 篇)都从 ResNet 系列主干网络起步。
6. 局限性
- 单纯靠深度并不能无限变好。 CIFAR-10 上的 1202 层网络比 110 层更差。虽然训练成功了(训练误差低于 0.1%),但相对于小数据集而言,网络实在太大了。
- BN 依赖于批次。 由于使用批次均值和方差,如果批次较小,统计量就会不稳定。这在使用大图像导致单张 GPU 只能放下几张图的检测和分割任务中会成为问题,因此会使用群组归一化(Group Normalization)或层归一化(Layer Normalization)等替代方案。第 7 篇的 Transformer 使用的是层归一化。
- 推理与训练的行为不同。 训练时使用批次统计量,推理时使用滑动平均值。如果忘记切换模式,同一张图会输出不同的答案(实操中常见的失误)。
7. 与我们项目的联系
- 捷径现在无处不在。TT Score 找球的 HRNet 系列主干也是通过堆叠残差模块构建的,第 9–11 篇 SAM 使用的 Transformer 模块也是“x + Attention(x)”、“x + MLP(x)”形式的残差连接。
- 对小型模型同样有意义。正如第 4 节的实验所示,捷径使训练与深度无关地变得稳定,因此参数量仅约 150 万的找球模型也能堆叠足够的层数。
下一篇文章将介绍保持分辨率的结构——U-Net 和 HRNet。我们将探讨当需要以像素级精度识别球这样的小型物体位置时,第 1 篇的池化(pooling)为什么会成为问题,以及如何避免它。
TT 的总结。 不要对深层网络说“全部重新画”,而是告诉它“只说要改哪里”,于是它连 64 层也学会了。这就是一次加法的作用。
参考文献
- He, K., Zhang, X., Ren, S., Sun, J. (2016). Deep Residual Learning for Image Recognition. CVPR 2016. https://arxiv.org/abs/1512.03385
- He, K., Zhang, X., Ren, S., Sun, J. (2016). Identity Mappings in Deep Residual Networks. ECCV 2016. https://arxiv.org/abs/1603.05027
- Ioffe, S., Szegedy, C. (2015). Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. ICML 2015. https://arxiv.org/abs/1502.03167
- Santurkar, S., Tsipras, D., Ilyas, A., Madry, A. (2018). How Does Batch Normalization Help Optimization? NeurIPS 2018. https://arxiv.org/abs/1805.11604
- 示例代码与输出:此文件夹中的
code/02_residual.py,code/02_residual.out.txt