本讲目录

第 04 讲 · 神经网络的兴衰与反向传播

诞生场景:前三讲的模型都在"人给的特征"上找函数。可要是连特征都说不清呢?大脑没人给它设计特征,靠约 860 亿个神经元互联自己搞定了一切。1943 年起,一批研究者开始琢磨:能不能仿照神经元,搭出会学习的机器?这条路线在此后六十年里两起两落——被寄予厚望、被判死刑、复活、再被 SVM 按在地上、再翻盘统治世界。本讲讲透它的原理与恩怨,核心是完整推导那个让多层网络成为可能的算法:反向传播。

学习层:把“反向传播”变成可追踪的消息

具体谜题:一条边变大,损失会怎样?

下面的实验固定一个 2 → 2 → 1 网络和一个样本。先猜:把 \(w_{11}\)(\(x_1\to h_1\))稍微调大,预测 \(\hat y\) 会让平方损失上升还是下降?不要先算完整梯度,只根据这条路径上每个局部导数的符号作答。

先做预测,再看答案

初始样例是 \(x=(0.8,-0.4)\)、目标 \(y=0.6\);默认激活函数为 sigmoid。预测以下三件事:① 哪个隐藏节点的 \(z\) 为负?② \(\partial L/\partial w_{11}\) 的符号是什么?③ 中心差分和解析梯度应不应该接近?然后在实验中切换到 ReLU,观察第二个隐藏节点被“截断”后消息如何改变。

最小模型:只保留四个部件

前向计算是 \(z_1=W_1x+b_1\)、\(a_1=\sigma(z_1)\)、\(z_y=v^\top a_1+b_y\)、\(\hat y=\sigma(z_y)\);损失取 \(L=\tfrac12(\hat y-y)^2\)。实验只让你观察一个样本和一个选中参数,因此它是“显微镜”,不是完整的 XOR 训练器。

形式化步骤:局部导数如何接力

  1. 输出端先传回 \(\partial L/\partial \hat y=\hat y-y\),再乘输出激活的局部导数,得到 \(\delta_y=\partial L/\partial z_y\)。
  2. 沿输出边回传:\(\partial L/\partial a_{1,i}=\delta_yv_i\);经过隐藏激活后,\(\delta_i=\delta_yv_i\sigma'(z_i)\)。
  3. 到达输入边时,消息与“上游激活”相乘:\(\partial L/\partial w_{ij}=\delta_i x_j\),偏置梯度则是 \(\partial L/\partial b_i=\delta_i\)。
  4. 中心差分把同一个参数改成 \(w+\varepsilon\) 与 \(w-\varepsilon\),用 \([L(w+\varepsilon)-L(w-\varepsilon)]/(2\varepsilon)\) 做独立校验;真正训练仍使用解析梯度的负方向。

边界与反例:什么时候直觉会失效?

  • ReLU 在 \(z=0\) 处不可微;若差分步长跨过这个拐点,数值梯度和选定的次梯度不一致是预期的边界现象。
  • 梯度为零不等于参数“没有作用”:可能是上游误差为零,也可能是 ReLU 把局部导数置零;要同时看节点的 \(z,a\) 与回传消息。
  • 数值差分不是训练方法:参数越多,所需前向次数越多;它适合在小模型上抓转置、符号或索引错误。

迁移题:把消息传给另一层

如果输出层改成两个 logit 并接 softmax + 交叉熵,哪一步要改写,哪一步(“误差 × 上层激活”)仍然不变?再想象一个 batch:哪些量可以沿样本维并行,哪些参数梯度需要累加?把答案写成四行伪代码。

无 JavaScript 时的静态版本:固定样例给出 \(z_1=0.86\)、\(z_2=-0.95\)。sigmoid 下先逐层算出 \(a_1,a_2,\hat y\),再用 \(\partial L/\partial w_{11}=(\hat y-y)\sigma'(z_y)v_1\sigma'(z_1)x_1\);中心差分应在合适的 \(\varepsilon\) 下接近同一个数。页面脚本加载后可选择 sigmoid/ReLU、任意一条边或偏置、查看 SVG 计算图,并只对选中参数执行一步梯度下降。

1. 从神经元到感知机(1943–1969)

1943 年 McCulloch 和 Pitts 提出神经元的数学漫画:输入加权求和,超过阈值就"放电":

\[ a = \sigma\Big(\sum_j w_j x_j + b\Big) \]

\(\sigma\) 是激活函数——最初是阶跃函数,后来换成光滑版本,如 sigmoid \(\sigma(z) = \frac{1}{1 + e^{-z}}\)。单个神经元就是第 02 讲的线性分类器套一个非线性外壳;Rosenblatt 1958 年的感知机给它配上了学习算法(第 02 讲已证其收敛性),媒体狂热了十年。

1969 年,Minsky 和 Papert 的著作《Perceptrons》给出了那个著名的判决:单层感知机连 XOR 都表示不了(第 01 讲已证:\(\mathbb{R}^2\) 线性分类器 VC 维为 3,打散不了 XOR 那 4 个点;一行代数也能证:若 \(f(0,0)<0, f(1,1)<0, f(0,1)>0, f(1,0)>0\),四式相加得 \(0 < 0\),矛盾)。书里同时指出多层网络或许能行,但"没有有效的训练算法"。经费应声枯竭,第一次 AI 寒冬降临,神经网络研究冻结了近十五年。

2. 多层网络的表达力:万能逼近

激活函数

图 4.1激活函数给网络注入非线性:没有它,多层网络会塌回一个线性映射——sigmoid/tanh/ReLU/GELU 是最常见的几种。

把神经元层层堆叠:第 \(l\) 层把上一层输出 \(a^{(l-1)}\) 变换为

\[ z^{(l)} = W^{(l)} a^{(l-1)} + b^{(l)}, \qquad a^{(l)} = \sigma(z^{(l)}) \]

这就是多层感知机(MLP)。XOR 在表示上可以被解决:两个隐藏神经元分别实现"或"和"与",输出层算"或减与"。但“存在一个能表示 XOR 的参数点”和“训练算法能找到它”是两件事;下方 lab 固定一个小网络来观察梯度,而不是完整的 XOR 训练器。更一般地:

定理(万能逼近,Cybenko 1989 / Hornik 1991):设 \(\sigma\) 是任意非常数、有界、连续的"挤压型"函数。则形如 \(g(x) = \sum_{i=1}^{N} c_i\, \sigma(w_i^\top x + b_i)\) 的单隐层网络全体,在紧集上对连续函数一致稠密——即对任意连续 \(f\) 与 \(\epsilon > 0\),存在足够宽的单隐层网络 \(g\) 使 \(\sup_x |f(x) - g(x)| < \epsilon\)。

证明思路(Cybenko 的泛函分析论证):反证。设逼近不到的连续函数存在,则网络全体张成的子空间在 \(C(K)\) 中不稠密;由 Hahn–Banach 定理,存在非零有界线性泛函在该子空间上恒零;由 Riesz 表示定理,该泛函对应一个非零符号测度 \(\mu\),满足 \(\int \sigma(w^\top x + b)\, d\mu(x) = 0\) 对一切 \(w, b\) 成立。最后证明挤压函数族"足够丰富"(取 \(w\) 方向的极限可逼出半空间指示函数,进而由傅里叶论证)迫使 \(\mu = 0\),矛盾。\(\blacksquare\)

两点必须泼的冷水,也是这条定理最常被误读的地方:

3. 训练:梯度下降与反向传播

反向传播:前向计算图 + 反向梯度沿链式法则回流。

图 4.3反向传播:前向计算图 + 反向梯度沿链式法则回流。

梯度下降与学习率

图 4.2梯度下降沿负梯度更新参数:学习率太大则来回震荡甚至发散、太小则慢——调好它是训练的第一件事。

表达力有了,Minsky 的第二个问题还在:怎么训练?参数 \(\theta = \{W^{(l)}, b^{(l)}\}\) 几千上万个,损失 \(L(\theta)\) 非凸(不像 SVM),解析解无望。答案是最朴素的迭代:往下坡走。

3.1 梯度下降与 SGD

\[ \theta_{t+1} = \theta_t - \eta \nabla_\theta L(\theta_t) \]

\(\eta\) 是学习率。全量梯度要过一遍所有样本,太贵;随机梯度下降(SGD)每步只用一个小批量(mini-batch)估计梯度——无偏但带噪声。噪声不全是坏事:它帮助逃离鞍点和尖锐极小值。非凸优化没有全局最优保证,但深度学习的经验事实是:足够大的网络里,SGD 找到的局部极小值几乎都"够好"——这个现象至今没有完整的理论解释(与第 01 讲"VC 界失效"并列为深度学习理论的未解之谜)。

现在只剩一个问题,也是 1969–1986 年间卡住一切的问题:\(\nabla_\theta L\) 怎么算?参数在层层复合函数的深处,一个 \(W^{(1)}\) 的分量要经过后面所有层才影响损失。

3.2 反向传播:完整推导

设网络共 \(L\) 层,单个样本损失 \(\ell(a^{(L)}, y)\)(推导对任意可微损失/激活成立)。目标:所有 \(\dfrac{\partial \ell}{\partial W^{(l)}}, \dfrac{\partial \ell}{\partial b^{(l)}}\)。

核心记号:定义第 \(l\) 层的误差信号

\[ \delta^{(l)} \equiv \frac{\partial \ell}{\partial z^{(l)}} \in \mathbb{R}^{n_l} \]

即损失对该层"激活前值"的敏感度。整个算法就是四个方程。

方程一(输出层的 \(\delta\)):直接链式法则,逐分量

\[ \delta^{(L)}_i = \frac{\partial \ell}{\partial z^{(L)}_i} = \sum_j \frac{\partial \ell}{\partial a^{(L)}_j}\frac{\partial a^{(L)}_j}{\partial z^{(L)}_i} = \frac{\partial \ell}{\partial a^{(L)}_i}\,\sigma'(z^{(L)}_i) \]

(激活逐元素作用,故 \(j \neq i\) 的项为零。)向量形式:\(\delta^{(L)} = \nabla_{a^{(L)}} \ell \odot \sigma'(z^{(L)})\),\(\odot\) 为逐元素乘。

常用组合有惊喜:平方损失 \(\ell = \frac12\|a - y\|^2\) 给出 \(\nabla_a \ell = a - y\);而 softmax + 交叉熵的组合,\(\delta^{(L)}\) 恰好也化简为 \(a^{(L)} - y\)(one-hot 的 \(y\);推导留作练习,展开 \(\ell = -\log \frac{e^{z_y}}{\sum_k e^{z_k}}\) 对 \(z_i\) 求导即可)——"预测减真相",形式干净得不像巧合。

方程二(\(\delta\) 的逐层回传)——算法的心脏。已知 \(\delta^{(l+1)}\),求 \(\delta^{(l)}\)。链条是 \(z^{(l)} \to a^{(l)} \to z^{(l+1)} \to \ell\),其中 \(z^{(l+1)} = W^{(l+1)} a^{(l)} + b^{(l+1)}\):

\[ \delta^{(l)}_i = \sum_j \frac{\partial \ell}{\partial z^{(l+1)}_j} \frac{\partial z^{(l+1)}_j}{\partial a^{(l)}_i} \frac{\partial a^{(l)}_i}{\partial z^{(l)}_i} = \sum_j \delta^{(l+1)}_j W^{(l+1)}_{ji}\, \sigma'(z^{(l)}_i) \]

向量形式:

\[ \boxed{\;\delta^{(l)} = \big(W^{(l+1)\top} \delta^{(l+1)}\big) \odot \sigma'(z^{(l)})\;} \]

读出它的含义:误差沿着权重矩阵的转置逆流而上(前向乘 \(W\),反向乘 \(W^\top\)),途中被本层激活函数的导数逐元素调制。

方程三、四(参数梯度):\(z^{(l)} = W^{(l)}a^{(l-1)} + b^{(l)}\) 中 \(W^{(l)}_{ij}\) 只出现在 \(z^{(l)}_i\) 里,且 \(\partial z^{(l)}_i / \partial W^{(l)}_{ij} = a^{(l-1)}_j\):

\[ \frac{\partial \ell}{\partial W^{(l)}_{ij}} = \delta^{(l)}_i\, a^{(l-1)}_j \;\;\Longleftrightarrow\;\; \frac{\partial \ell}{\partial W^{(l)}} = \delta^{(l)}\, a^{(l-1)\top}, \qquad \frac{\partial \ell}{\partial b^{(l)}} = \delta^{(l)} \]

每层梯度 = 本层误差 × 上层激活的外积。完整算法:

  1. 前向:从 \(x\) 逐层算出所有 \(z^{(l)}, a^{(l)}\)(缓存下来);
  2. 反向:方程一起手,方程二逐层回传 \(\delta^{(L)} \to \delta^{(L-1)} \to \cdots\);
  3. 沿途用方程三、四收集所有梯度;
  4. SGD 更新。

复杂度:反向传播的乘加次数与前向同阶(每层一次矩阵-向量乘),算全部梯度只需前向的常数倍,而不是按参数个数重复前向。对比一下就知道这有多惊人:数值差分要对每个参数扰动一次、做 \(O(\text{参数数})\) 次前向;一个百万参数的网络,反向传播与数值差分之间可有百万量级的成本差异。没有这个效率,深度学习不存在。本质上它是多元链式法则 + 动态规划(\(\delta^{(l)}\) 是被复用的子问题答案),也是今天所有深度学习框架里"自动微分"(反向模式)的数学内核——PyTorch 的 loss.backward() 做的就是上面四个方程在计算图上的一般化。

1986 年 Rumelhart、Hinton、Williams 在 Nature 发表这套算法(思想此前多次被独立发现:Werbos 1974 的博士论文、更早的控制论文献,但 1986 年这篇让它出圈),Minsky 的判决被推翻,神经网络第一次复兴开始:1989 年 LeCun 用它训练卷积网络识别手写邮编(第 05 讲主角的前身),Hornik 证明万能逼近,一切看起来欣欣向荣。

4. 第二次寒冬(1995–2006):为什么又不行了

复兴只维持了不到十年。90 年代中期起,神经网络在学术界再次失宠,这次的对手正是第 02 讲的 SVM。原因值得逐条看清,因为后来深度学习的爆发恰好是这些原因被逐条消除:

1. 梯度消失——深不下去的数学根源。盯住方程二连乘的结构,从输出层回传到第 \(l\) 层:

\[ \delta^{(l)} = \Big[\prod_{k=l+1}^{L} \mathrm{diag}\big(\sigma'(z^{(k-1)})\big)\, W^{(k)\top}\Big]\, \delta^{(L)} \cdot (\text{按序整理}) \]

粗略地按范数估计,每回传一层,\(\|\delta\|\) 被乘上一个约为 \(\|W\| \cdot \max\sigma'\) 的因子。而 sigmoid 的导数 \(\sigma'(z) = \sigma(z)(1 - \sigma(z)) \leq \frac14\)(在 \(z=0\) 处取最大;两侧饱和区几乎为 0)。如果权重的谱范数没有抵消这个缩放,连续层的梯度就会快速衰减;在一个简化的单位尺度估计中,10 层可出现 \(4^{-10} \approx 10^{-6}\) 的量级——底层梯度几乎收不到信号。反过来若 \(\|W\|\) 大,连乘就可能爆炸。梯度消失/爆炸是深度的原罪,1991 年 Hochreiter 的硕士论文就把它说透了(此人后来发明 LSTM,第 06 讲再见)。

2. 数据太少、算力太弱。几千个样本训不动大网络(第 01 讲:复杂模型需要大 \(n\));CPU 训练以周计。

3. 理论气质完败。SVM:凸优化全局最优、VC 理论保泛化、调参少且行为可解释。神经网络:非凸、局部极小、初始化玄学、"炼丹"。审稿人的风向直接反映生态:当年论文里出现"neural network"就难中,SVM 成为默认基线。

5. Hinton 的坚守(2006–2012)

大多数人转向了。Geoffrey Hinton 没有——从 70 年代读博起他就认定"大脑显然是靠某种梯度式学习工作的,这条路不可能错"。加拿大 CIFAR 研究所在神经网络最不受待见的年代给了他和 Bengio、LeCun 一小笔长期经费(后来被戏称为"加拿大黑手党"的三人组,2018 年共享图灵奖)。

2006 年,Hinton 在 Science 发表深度信念网络(DBN):逐层无监督预训练——先让每一层单独学习重构输入(受限玻尔兹曼机,RBM),学完一层再堆下一层,最后用反向传播整体微调。这绕开了梯度消失(每层的起点已在不错的位置),首次证明训练深层网络是可行的。同一篇论文里,他刻意启用了一个新名字:deep learning——部分原因是"neural network"这个词在审稿人那里名声太差,换个说法才发得出去。

有趣的注脚:随着 ReLU、良好初始化和 GPU 的到来,逐层预训练这个具体技术几年内就被淘汰了——DBN 的历史作用不是技术本身,而是把"深度可训练"这个信念重新注入了整个领域,并聚拢了一批人才等待引爆点。引爆点在 2012 年到来,需要的三样东西恰好同时凑齐:大数据(ImageNet)、大算力(GPU)、以及消除梯度消失的架构技巧。那就是下一讲的故事。

本讲小结

概念 一句话
感知机之死 单层线性,XOR 不可表示(1969),第一次寒冬
MLP 层层复合 \(\sigma(Wx+b)\);深度 = 复合 = 层级表示
万能逼近 单隐层已稠密,但只保证存在性;深度的价值在表示效率
SGD 小批量噪声梯度下坡;非凸但经验上够好
反向传播 \(\delta^{(l)} = (W^{(l+1)\top}\delta^{(l+1)}) \odot \sigma'\);链式法则 + 动态规划;代价 ≈ 2 次前向
梯度消失 sigmoid 导数 \(\leq 1/4\) 连乘指数衰减;深网络底层训不动
第二次寒冬 输给 SVM:凸性、理论、小数据时代的气质之争
Hinton 坚守 2006 逐层预训练证明"深度可训",deep learning 得名

动手:在本页的 backprop lab 中固定一个 2→2→1 网络,切换 sigmoid/ReLU,选一条边或一个偏置,读出前向节点值与链式法则消息;再用中心差分做梯度检查。默认状态下相对误差应很小,但靠近 ReLU 的 \(z=0\) 拐点时要把差异解释为不可微边界,而不是盲目追求一个阈值。

延伸阅读:Nielsen《Neural Networks and Deep Learning》第 2 章(反向传播讲得最细的免费教材,neuralnetworksanddeeplearning.com);Rumelhart, Hinton & Williams (1986)。


下一讲:2012 年 9 月 30 日,ImageNet 竞赛结果公布,一个名叫 AlexNet 的模型把错误率从 26% 砍到 15%,全场哗然。深度学习的热潮由此点燃——而它用的网络结构 CNN,把"归纳偏置"这个概念演绎到了极致。