一
前面几章反复撞见同一个敌人:梯度。感知机学不会 XOR,是表达力问题;但从反向传播开始,几乎所有训练困难都能归到梯度上——梯度消失(第 04 章 RNN)、梯度爆炸、softmax 饱和区梯度小(第 08 章为什么除以根号 d)。原因在第 02 章就埋下了:反向传播是把一长串导数连乘起来,只要这些乘子系统性地偏离 1,连乘的结果就会指数级地趋零或炸开。
所以“让深层网络训得动”这个问题,本质上是“如何让梯度在很多层之间健康地流动”。本章的四项技术——ReLU、BatchNorm、残差连接、Adam——从四个不同角度回答这个问题。它们不改变网络要学的函数,只改变“能不能学到”。把它们理解为深度学习的地基,比理解为调参技巧更准确。
二
第一块地基是激活函数。早期网络用 sigmoid 或 tanh 做非线性,它们有一个致命缺陷藏在导数里。
sigmoid 函数 的导数是 ,它的最大值在 处,只有 0.25;当 偏离 0(输入很大或很小)时,导数迅速趋近 0——这叫“饱和”。回忆第 02 章:误差每反传一层,都要乘一次该层激活函数的导数。如果每层都乘一个 的数,传过 层后梯度量级至多是 ——10 层就只剩约 。深层网络的前几层根本收不到学习信号。
2010 年,Nair 和 Hinton 推广了一个简单到几乎不像“函数”的激活:修正线性单元(Rectified Linear Unit, ReLU)1:
它的导数极其干净: 时导数是 1, 时是 0。正区间导数恒为 1 意味着——误差反传穿过激活时不衰减。把这件事跑出来对比最直观(配套代码 code/09_enablers.py):
展开代码 · 09_enablers.py
"""
第 09 章配套代码:深层可训练性的工程突破
(1) ReLU vs sigmoid 的梯度(为什么 ReLU 缓解梯度消失)
(2) 残差连接如何让梯度直达(ResNet)
(3) Adam 优化器的一步更新
Runnable with: numpy only. python3 09_enablers.py
"""
import numpy as np
def sigmoid(x): return 1 / (1 + np.exp(-x))
print("=== (1) 深层网络里激活函数导数的连乘 ===")
# 10 层,每层乘一次激活导数。sigmoid 导数最大仅 0.25 => 连乘指数衰减
L = 10
# sigmoid'(z) 在 z=0 处最大 = 0.25
sig_grad_chain = 0.25 ** L
# ReLU'(z) = 1 (正区间) => 连乘不衰减
relu_grad_chain = 1.0 ** L
print(f" sigmoid: 10 层导数连乘(每层最多0.25) ~ {sig_grad_chain:.2e} -> 梯度消失")
print(f" ReLU : 10 层导数连乘(正区间每层1.0) ~ {relu_grad_chain:.2e} -> 梯度保持")
print("\n=== (2) 残差连接 y = x + F(x) 的梯度 ===")
# 普通层 dy/dx = F'(x);残差层 dy/dx = 1 + F'(x),那个 '1' 保证梯度有直达通路
for Fp in [0.01, 0.5, 2.0]:
print(f" F'(x)={Fp:>4}: 普通层 dy/dx={Fp:>5} | 残差层 dy/dx=1+{Fp}={1+Fp}"
f" ({'梯度近乎消失' if Fp < 0.1 else '梯度健康'} vs 残差恒有直达项)")
print("\n=== (3) Adam 优化器一步更新(自适应动量)===")
def adam_step(g, m, v, t, lr=0.01, b1=0.9, b2=0.999, eps=1e-8):
m = b1 * m + (1 - b1) * g # 一阶矩(动量)
v = b2 * v + (1 - b2) * g * g # 二阶矩(梯度平方的滑动平均)
m_hat = m / (1 - b1 ** t) # 偏差校正
v_hat = v / (1 - b2 ** t)
update = lr * m_hat / (np.sqrt(v_hat) + eps) # 每个参数自适应步长
return update, m, v
# 模拟一个参数,梯度尺度差异很大
m, v = 0.0, 0.0
for t in range(1, 6):
g = np.array([10.0, 0.01])[t % 2] # 交替大/小梯度
upd, m, v = adam_step(g, m, v, t)
print(f" t={t} 原始梯度={g:>6} Adam 更新量={upd:.5f} (大小梯度被自适应地归一到相近步长)")
sigmoid: 10 层导数连乘(每层最多0.25) ~ 9.54e-07 -> 梯度消失
ReLU : 10 层导数连乘(正区间每层1.0) ~ 1.00e+00 -> 梯度保持
同样 10 层,sigmoid 把梯度压到百万分之一,ReLU 原样保留。ReLU 还有两个附带好处:计算极快(就是一个取大)、且对负输入直接输出 0,带来稀疏激活。代价是“死亡 ReLU”问题——若一个单元长期落在负区间,梯度恒 0、永不更新;后续的 Leaky ReLU、GELU 等变体对此做了改良。但 ReLU 缓解梯度消失这一条,已足以让它成为 AlexNet(第 05 章)及之后几乎所有网络的默认激活。
三
第二块地基是批归一化(Batch Normalization, BatchNorm),2015 年由 Ioffe 和 Szegedy 提出2。
它针对的问题是:训练时,每一层的输入分布会随着前面层参数的更新而不断漂移——作者称之为“内部协变量偏移”(internal covariate shift)。下一层刚适应了某种输入分布,上一层一更新,分布又变了,下一层得重新适应,训练因此变慢、变得对学习率和初始化敏感。
BatchNorm 的做法是:在每一层(通常是激活之前),对一个小批次(mini-batch)内的数据,把每个特征维度归一化到均值 0、方差 1,再用两个可学习参数 做缩放和平移:
其中 是当前批次该特征的均值和方差。先归一化稳住分布,再用 让网络保留“在需要时恢复原始尺度”的自由(如果归一化不利,网络可以学 把它撤销)。
BatchNorm 的效果立竿见影:允许用大得多的学习率、对初始化不再那么敏感、训练显著加快,还附带轻微的正则化效果(因为每个样本的归一化依赖随机的批次统计,引入了噪声)。后来人们对“内部协变量偏移”这个解释本身有争议——有研究认为 BatchNorm 真正的作用是让损失曲面更平滑、优化更容易——但无论机制解释如何,它“稳住数值分布、加速深层训练”的实用价值毋庸置疑。在序列模型和 Transformer 里,因为序列变长、批统计不稳,人们更常用层归一化(LayerNorm,在特征维度而非批次维度归一化,见第 08 章)。
四
第三块、也是最优雅的一块地基,是残差连接(residual connection),2015 年由何恺明等人在 ResNet 里提出3。
它解决一个反直觉的现象:把网络做得更深,效果反而变差——而且不是过拟合(训练误差也更高)。理论上深层网络至少能表达浅层网络能表达的一切(多出来的层学成恒等映射即可),可实践中优化器学不到这个恒等映射,深层网络退化了。
ResNet 的洞察是:与其让每一层去学一个完整的目标映射 ,不如让它去学“目标与输入的差” ,然后把输入直接加回来:
那条把 直接加到输出的线,叫“捷径连接”(shortcut / skip connection)。它带来两个好处。其一,学恒等更容易:要表达恒等映射 ,只需让 (把权重压到 0),这比让一堆非线性层精确拟合出恒等容易得多。其二、也是关键——梯度有了直达通路。看残差层的梯度:
那个 是魔法所在。即便 很小(趋于梯度消失),梯度里永远有一个恒为 1 的直达项,误差可以沿着捷径无衰减地传回浅层。跑出来看(code/09_enablers.py):
F'(x)=0.01: 普通层 dy/dx=0.01 | 残差层 dy/dx=1+0.01=1.01
F'(x)= 0.5: 普通层 dy/dx=0.5 | 残差层 dy/dx=1+0.5=1.5
普通层在 时梯度近乎消失,残差层却稳稳保持在 1 附近。靠这条捷径,ResNet 把网络深度推到了 152 层——比当时的 VGG 深 8 倍——并以 3.57% 的 top-5 错误率赢得 ILSVRC 20153。残差连接的思想此后无处不在:第 08 章的 Transformer 每个子层都包着 ,正是同一个 在让上百层的大模型梯度畅通。
五
第四块地基是优化器。最朴素的梯度下降对所有参数用同一个学习率 ,沿负梯度走 。但不同参数的梯度尺度可能差好几个数量级——有的方向梯度很大、需要小步,有的很小、需要大步,统一学习率顾此失彼。
一系列自适应优化器解决这个问题,集大成者是 2014 年 Kingma 和 Ba 提出的 Adam4。它为每个参数维护两个滑动平均:一阶矩 (梯度的动量,平滑掉噪声、保持方向惯性)和二阶矩 (梯度平方的平均,估计该方向梯度的典型大小):
做偏差校正(修正初期 偏向 0 的问题)后,更新为:
关键是那个 :用动量做分子(稳定方向),用梯度大小做分母(自动缩放步长)。梯度一向很大的参数,分母大、步子被压小;梯度一向很小的参数,分母小、步子被放大。每个参数都得到了适合自己的有效学习率。跑出来看(code/09_enablers.py),交替喂入大梯度(10)和小梯度(0.01),Adam 的实际更新量都被归一到 0.006–0.007 这个相近的量级——尺度被自动拉平。Adam 默认参数()鲁棒、几乎开箱即用,成了深度学习最常用的优化器,从 CNN 到 Transformer 大模型训练的默认选择。
六
把四块地基放在一起看,它们其实是从四个方向围剿同一个敌人——让梯度在深层网络里健康地流动:
敌人: 反向传播是导数连乘 => 系统性偏离 1 就指数消失/爆炸
ReLU : 换掉饱和激活,正区间导数=1 → 激活这一环不衰减
残差连接 +x : 给梯度一条恒等捷径 dy/dx=1+F' → 有一条永不衰减的直达通路
BatchNorm : 稳住每层输入分布(均值0方差1) → 数值不漂移,可用大学习率
Adam : 每参数自适应步长 m̂/√v̂ → 不同尺度的梯度都走合适的步子
└────────────── 合力 ──────────────┘
几层就训不动 ──► 几十上百层稳定收敛
配套的 manim 动画 assets/manim/ch09_enablers.py(含 ReLUGate、Residual、BatchNormScene、AdamTrajectory 四个 Scene)把四块地基各自的几何直觉演出来:ReLU 是一道折线门,正区导数恒为 1、不饱和,梯度不被掐死;残差 的 skip 像一条让梯度直达底层的高速公路;BatchNorm 把漂移的激活分布拉回标准正态;Adam 在被拉长的病态损失曲面上用自适应步长,比朴素 SGD 更直地冲向谷底。四段动画说的是同一件事:这些“工程细节”不是锦上添花,而是深层网络能否被训练出来的生死线。
这一章的技术都不像 Transformer 那样有一个戏剧性的“发明时刻”,它们是一群在 2010–2015 年间陆续到位的拼图。但正是它们的合流,加上第 05 章的数据与算力,才让“把网络堆得很深很大并训练到收敛”从奢望变成日常。地基铺好,就可以盖最高的楼了——把 Transformer 这个骨架,用海量文本做大规模预训练,造出能读会写的语言模型。那是 BERT 与 GPT 的故事,也是大模型时代的开端。
本质
这一章的四项技术看似无关,实则都在对付深层网络的同一个敌人:信号(无论是前向的激活还是反向的梯度)在层与层的反复变换中失控——要么衰减到零,要么膨胀到爆,要么分布漂移到难以优化。ReLU 让梯度有一条不饱和的通路,残差让恒等映射成为默认、给梯度修一条直达底层的近路,归一化把每层的输入分布钉在一个稳定的尺度上,自适应优化器则按每个参数自己的曲率调步长。它们的共同主题是:把深度从一个会放大病态的累赘,变成一个可以安全堆叠的资源。没有任何一项是“提升精度的技巧”,它们合起来回答的是一个更基础的问题——一个几十上百层的网络,凭什么能被训练到收敛。架构决定了模型能表达什么,而这些地基决定了它能不能真的被学出来。
参考文献
-
Nair, V., & Hinton, G. E. (2010). Rectified Linear Units Improve Restricted Boltzmann Machines. ICML 2010. ReLU 缓解梯度消失。综述见 batch/activation 相关文献;ReLU 在 AlexNet 中的角色见 https://en.wikipedia.org/wiki/AlexNet
-
Ioffe, S., & Szegedy, C. (2015). Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. arXiv:https://arxiv.org/abs/1502.03167 ;ar5iv(含公式):https://ar5iv.labs.arxiv.org/html/1502.03167
-
He, K., Zhang, X., Ren, S., & Sun, J. (2015/2016). Deep Residual Learning for Image Recognition. CVPR 2016. 残差连接、152 层、ILSVRC2015 3.57%。arXiv:https://arxiv.org/abs/1512.03385 ;官方代码:https://github.com/KaimingHe/deep-residual-networks
-
Kingma, D. P., & Ba, J. (2014). Adam: A Method for Stochastic Optimization. 一阶/二阶矩、偏差校正、自适应步长。arXiv:https://arxiv.org/abs/1412.6980