🧠 第八章 神经网络训练
📄 一句话概括

同一个病态目标,跑 100 步:SGD 损失 0.000142、Momentum 0.000013、Adam 0.000010。 但第 10 步时 SGD 只有 0.2210,Adam 还在 3.8714。 学习率扫一遍:SGD 到 0.11 直接炸到 6.9e+16,Adam 五档全稳。

📝 本节和前面几节的关系

上一节讲结构,这一节讲怎么把那些参数定下来。 训练这套流程不复杂,但要跑得动,有几个地方必须知道为什么。

一、训练就是四步循环

  1. 前向:把一批数据喂进去,算出预测。
  2. 算损失:预测和答案差多少,用一个可微的函数量出来。
  3. 反向:把损失对每个参数的导数算出来。
  4. 更新:参数沿着导数的反方向挪一小步,步长就是学习率。 重复这四步,直到损失不再下降。整个深度学习训练,不管模型多大,都是这四步。 区别只在规模:数据多少、模型多大、一步能并行算多少。

二、三种优化器的差别在哪

SGD:直接沿着当前梯度走。 简单,但对曲率敏感——不同方向的陡峭程度差得远时,一个步长没法同时满足两边。 Momentum:给梯度加一个「速度」,累积历史方向。慢方向被推起来,但快方向也容易冲过头。 Adam:按每个维度自己的历史梯度平方缩放步长。 陡的方向自动小步,平的方向自动大步,等于给每个方向单独配了学习率。 Demo 用的目标两个方向曲率差 20 倍(一个是 1,一个是 20),是最典型的病态情形。

三、表里那些数字说明什么

第 100 步三者都收敛了:0.000142、0.000013、0.000010。差得不远。 但看第 10 步:SGD 0.2210,Momentum 3.1610,Adam 3.8714。 这一格是反直觉的——Adam 前期最差。 原因是 Adam 把每个维度的梯度都拉平到 1 的量级,等于不看曲率。 曲率大的方向它照样大步走,于是冲过头。 所以「Adam 一定更快」是错的。它在病态目标上前期反而更慢,只是后期收得干净、且不用调学习率。 另外看终点:SGD 的慢方向还留着 0.0169 没走完,Momentum 是 0.0034,Adam 是 -0.0010。 慢方向收得最干净的是 Adam。

四、学习率不是随便给的数

把学习率扫一遍,结果很干脆:SGD 在 0.004 到 0.09 都收敛,到 0.11 直接炸成 6.9e+16。 这条界线不是玄学。梯度下降的稳定条件是「学习率 × 最大曲率 < 2」。 这个目标最大曲率是 20,所以上限正好是 0.1。 Adam 那边反过来:学习率太小时它走不完。 0.004 那档跑了 100 步,损失还停在 4.175172,因为它每步挪动的幅度大约就是学习率, 跟梯度大小没关系。 两条规律合起来才是真相:SGD 的步长要按曲率配,Adam 的步长要按步数配。 这就是为什么换任务时 SGD 得重调学习率,Adam 基本不动。 对训练师的实际意义:接手别人的训练脚本,看到学习率 1e-4 别急着改——先看优化器是哪个, 再看 batch 多大。这两个变了,学习率的合适区间就变了。

五、动手 Demo:三种优化器加学习率扫描:谁快谁稳,数据说了算

目标函数取 0.5 × (1 × w1² + 20 × w2²),两个方向曲率差 20 倍,起点 (1.0, 1.0)。 分别用 SGD、Momentum、Adam 跑 100 步,记录每 25 步的损失和终点; 再把学习率从 0.004 扫到 0.11,比 SGD 和 Adam 第 100 步的损失。

if kind == u"SGD":
    w = w - lr * g
elif kind == u"Momentum":
    v = 0.9 * v - lr * g
    w = w + v
else:                                    # Adam
    m = 0.9 * m + 0.1 * g
    s = 0.999 * s + 0.001 * g * g
    w = w - lr * (m / (1 - 0.9 ** t)) / (np.sqrt(s / (1 - 0.999 ** t)) + 1e-8)

实跑输出:

--------------------------------------------------------------------
三种优化器:同样的目标,收敛路径差多少
--------------------------------------------------------------------
  目标函数                 0.5 × (1 × w1² + 20 × w2²)
  起点                     (1.0, 1.0)
  学习率                   0.04,各跑 100 步
  第几步       SGD   Momentum      Adam
  ------------------------------------
       0   10.5000    10.5000   10.5000
      10    0.2210     3.1610    3.8714
      25    0.0649     0.3361    0.1676
      50    0.0084     0.0251    0.0619
     100    0.0001     0.0000    0.0000

  SGD 终点                 (0.0169, 0.0000),损失 0.000142
  Momentum 终点            (0.0034, 0.0009),损失 0.000013
  Adam 终点                (-0.0010, -0.0010),损失 0.000010

  学习率换一换,同一个 SGD 就完全是另一回事:
  学习率   SGD 第 100 步损失   Adam 第 100 步损失   SGD 表现
  ---------------------------------------------------------
   0.004            0.224305             4.175172   收敛
   0.010            0.066990             0.528948   收敛
   0.040            0.000142             0.000010   收敛
   0.090            0.000000             0.000097   收敛
   0.110             6.9e+16             0.000208   发散

  这个目标两个方向的条件数差 20 倍,是最典型的「病态」情形。纯 SGD 在两个方向上用同一个步长,快方向要小步、慢方向要大步,只能二选一。
  表里看得很清楚:SGD 的学习率一旦越过 0.10 就炸,因为稳定条件是「学习率乘最大曲率小于 2」,这个目标的曲率是 20,上限就是 0.1。
  Adam 那边恰恰反过来:学习率太小时它根本走不完(0.004 那行还停在 4.17),因为它每步挪动的幅度大致等于学习率,跟梯度大小没关系。
  两条规律加在一起才是真相:SGD 的步长要按曲率配,Adam 的步长要按步数配。这就是为什么换了任务,SGD 得重调学习率,Adam 基本不用动。
  另一件事看表一的第 10 步:Adam 是 3.8714,比 SGD 的 0.2210 差得多。因为它把每个维度的梯度都拉平到 1 的量级,等于不看曲率,前期冲得太猛。
  所以「哪个优化器更好」这个问法本身不对。Adam 真正的价值是「不用为每个任务重调学习率」,而不是「收敛得多快」;数据量小、目标简单的时候,调好的 SGD 一样好用,甚至还更准。

起点损失 10.5(0.5 × 1 × 1 + 0.5 × 20 × 1)。 100 步之后三者都到了 1e-4 量级,说明这个目标只要学习率对,三种优化器都能解。 第 10 步那一行是这一节最该记的:Adam 3.8714 比 SGD 0.2210 差了十几倍。 如果只跑 10 步就下结论,会得出「Adam 最差」的错误印象。 学习率扫描里 SGD 在 0.11 炸到 6.9e+16,这个数字大到没有意义,但它的信息很清楚: 越过了稳定上限。 Adam 在 0.004 那一格是 4.175172,比 0.01 的 0.528948 差得多。 0.004 × 100 步 = 0.4,从 1.0 挪 0.4 就到 0.6,确实走不完。 这个 Demo 的目标是我构造的,好处是解析上干净、结论清楚;坏处是真实网络的损失面复杂得多。 真实场景下这几个数会抖,但「SGD 对学习率敏感、Adam 对步数敏感」这条规律不变。

30 秒实验

  1. 把 Momentum 的系数 0.9 改成 0.5 和 0.99,看曲线怎么变。
  2. 把目标里的 20 改成 200,看 SGD 的学习率上限掉到多少。
  3. 想一想:为什么 Adam 在小学习率下反而比 SGD 更慢?

常见误区

  1. 「Adam 是最强优化器」——前期在病态目标上它最差,只是后期收得干净。
  2. 「学习率越小越稳」——太小就是走不完,训练预算用光了还在半路。
  3. 「换个优化器就能解决训练不收敛」——多数时候该查的是数据和学习率,不是优化器。
自测三问(点开对答案) 1. 训练循环的四步是什么? —— 前向算预测、算损失、反向算梯度、沿梯度反方向更新参数。 2. Adam 和 SGD 的核心区别是什么? —— Adam 按每个维度自己的历史梯度平方缩放步长,SGD 所有维度共用一个步长。 3. SGD 的学习率上限由什么决定? —— 由损失面的最大曲率决定,稳定条件是学习率乘最大曲率小于 2。

概念、结构、训练方法都过了。下面六节换个角度:六种具体的网络架构,各解决一类问题。

相关笔记