跳到主要内容

别把训练集背下来 — 0.91/0.71 的基线与三种补救

这一章讲三件事: 「把训练集背下来」长什么样;三种补救各自在哪一步动手; 以及为什么在最朴素的更新下等价的两招,换到 Adam 上就不等价了。

它在全书链条里的位置: 第 04 章给「在目标后面加一项罚参数走极端」起了名字, 第 11 章看到过拟合的现场信号(验证损失由降转升)。 这一章把三种补救各跑一遍,每组都带成绩。

需要的基础: 第 04 章的过拟合;第 12 章的两种更新方式。

1. 先看现象:训练集 0.91,测试集 0.71

先把「背下来」这件事做出来。 书里的配方是:数据故意造得少而杂, 网络故意给得够深1:

过拟合考场
────────────────────────────────────────────────
数据 300 条弯月数据,噪声开到 0.5
200 条训练、100 条测试
网络 三层:2 → 20 → 3 → 1,隐藏层用那道折线激活
训练 最朴素的更新,每步挪 0.2,训 50 000 步

结果:训练集准确率 0.91、测试集 0.712

20 个百分点的差距强烈暗示过拟合——模型把 200 条训练样本逐个记住了, 遇到没见过的就露馅2

书里还画了一张决策边界图作证:边界在两类交界处被切得过于精细, 呈现典型的「记住每个训练点」的特征3这一章后面的每张边界图,都要和这张基线图对比着看。

这种「训练集好、测试集差」的病,统称过拟合;对付它的一类手段统称正则化—— 通过显式约束、加入先验、提前停止等手段,把模型的有效复杂度(模型能拟合多细的模式的能力)压下来4

全章主走查:同一个考场,四种配置
═══════════════════════════════════════════════════════════════
§1 ① 基线(什么都不加) 训练 0.91 / 测试 0.71
§2 ② 损失后面挂罚项(ℓ2) 训练 0.86 / 测试 0.77
§3 ③ 每步更新前先缩小参数 训练 0.845 / 测试 0.75
§4 ④ 训练时随机关闭一部分神经元 训练 0.855 / 测试 0.76
§5 ⑤ 四组并排 + 决策边界图
§6 ⑥ ② 和 ③ 什么时候等价、什么时候不等价
═══════════════════════════════════════════════════════════════

2. 补救一:在损失后面挂一项「罚参数走极端」

第 04 章埋过一个伏笔:学习准则不只看训练误差,还要在目标后面加一项,罚参数走极端。 这一节就是那一项的实物。 带罚项的优化问题长这样5:

目标 = 原来的损失 + λ × 罚项
────────────────────────────────────────────────
λ 是罚项的强度(超参数,人来定)
罚项怎么算,有两种写法:
ℓ1:取所有参数绝对值之和
ℓ2:取所有参数平方之和

两种写法的差别不只是系数。 取绝对值之和,梯度对每个参数施加的拉力是恒定的 ±λ, 小参数会被一路拉到 0、再也不动——等于顺手把没用的输入特征筛掉了; 取平方之和,拉力正比于参数本身的大小,参数越小拉力越弱,所以它只是把所有参数一起往小里拽, 不会把谁压死成 0。 (这段区分书里只点了名、没有展开,这一句是补充,不在书里,来自通用知识。)

书里的实验用的是 ℓ2。代码上只改两处6:

改动一(算损失时) 损失 += λ × (各层权重平方之和) / (2 × 批大小)
改动二(算梯度时) 每层权重的梯度 += λ × 该层权重 / 批大小

改动二那一行值得停下来看:梯度里多了一项「正比于参数自身」的拉力。 这意味着每一步更新,参数除了沿损失方向挪,还同时被往零的方向拽—— 这就是「一起往小里拽」的机制。

主走查第二格:取 λ = 0.7,其他配置完全不变,重训 50 000 步7:

训练 0.86 / 测试 0.77

训练集从 0.91 降到 0.86、测试集却从 0.71 升到 0.77—— 训练精度小幅让步换来泛化精度明显提升8。 决策边界图也明显比基线平滑,不再追着每个训练点跑9

差距从 20 个百分点压到 9 个。

3. 补救二:不动损失,每步更新前先把参数缩小一点

第二招换个作用位置:不改损失函数,改更新那一步。

权重衰减的一步
────────────────────────────────────────────────
θ ← (1 − β)·θ − α·g
└ 每次更新前,先把参数整体缩小一点点
────────────────────────────────────────────────
β 是权重衰减系数,典型值 0.0001 ~ 0.001
这种做法就叫权重衰减(Weight Decay)

对比第 2 节那行梯度改动:那里是「损失里多一项,梯度里多一个往回拽的力」; 这里是「更新时直接先把参数缩小」。 做的事听起来一样,但作用的位置不同——这一节的实验暂时看不出差别,第 6 节会看到什么时候有差别。

主走查第三格:取 β = 0.001,关掉第 2 节的罚项,重训10:

训练 0.845 / 测试 0.75

书里的评价是:过拟合显著减弱但仍有空间;单独使用权重衰减效果接近 ℓ2 正则化, 但通常需要稍微小一些的衰减系数搭配更精细的学习率调度11。 决策边界与 ℓ2 版本几乎一致12

4. 补救三:训练时随机关掉一部分神经元

第三招的思路与前两种截然不同13:

暂退法的一步(只在训练时启用)
────────────────────────────────────────────────
① 掷骰子:每个神经元以概率 p 被关掉(输出强制设为 0)
② 照常前向:剩下的神经元接班
③ 把保留下来的激活放大 1/(1−p) 倍
────────────────────────────────────────────────
推断时:全部神经元在线,不放大

第 ① 步为什么有用? 每一步被迫用不同的「半个网络」工作, 网络就无法依赖任何特定子集,只能让同一个特征在多个神经元上都有备份—— 书里的说法是被动学会「分布式表示」13

第 ③ 步是容易漏的一步,书里专门讲了为什么。 训练时平均只有 (1−p) 的神经元在线, 激活的总能量比推断时低;推断时全开,两边对不上。 所以训练阶段把保留下来的激活放大 1/(1−p) 倍,让两边的期望(概率论里的加权平均)幅度对齐14这个「训练时放大、推断时不动」的版本,书里注明与主书公式略有不同, 是 PyTorch、TensorFlow 等框架的默认实现15

反向传播时,被关掉的神经元梯度也是 0,与前向行为完全对齐16

这一招的名字叫暂退法,英文 Dropout——「训练时随机丢弃一部分」的意思; 框架里对应 nn.Dropout,丢弃概率就是构造时的那个参数。

主走查第四格:取 p = 0.3,关掉前两招,在两个隐藏层之后各插一道随机关闭17:

训练 0.855 / 测试 0.76

与权重衰减相近,训练-测试差距同样被大幅压低18

还记得第 03 章那句「少一句切推断模式,同一份输入会给出不一致的输出」吗? 第 13 章第 8 节讲了第一个元凶,这一节就是第二个:训练时随机关、推断时全开, 不切换模式,同一份输入当然给出两个答案。

这个随机关闭的动作在第 16 章还会见到一次——Transformer 编码器的输入层末尾就插了一道。 它在那里的位置,第 16 章第 4 节讲。

5. 四组并排,以及边界图上看到的差别

配置训练测试训练-测试差距
基线0.910.7120 个百分点
ℓ2 罚项(λ = 0.7)0.860.779 个百分点
权重衰减(β = 0.001)0.8450.759.5 个百分点
暂退法(p = 0.3)0.8550.769.5 个百分点

三招的共同点:训练成绩都让了一步,测试成绩都涨了,差距都压回 10 个百分点以内。 这就是正则化的代价结构:它从不让训练集更好看,只让测试集更接近训练集。

边界图上的读法: ℓ2 与权重衰减的边界几乎一致地平滑; 暂退法的边界比基线平滑,但比 ℓ2 略弱—— 书里的解释是这与小数据集和简单网络有关, 在更深、参数更多的网络上,暂退法往往是性价比最高的选项19

书里还留了一个反方向的练习:把三个系数都调到很大(λ = 10、β = 0.1、p = 0.9), 观察两个准确率怎么变化——这是定位「正则化过度」的好练习20罚过头,模型连训练集都学不会,那是另一个方向的病。

6. 第 2 节和第 3 节,到底等不等价

现在回答第 3 节挂起来的问题。

书里给出了一条明确的结论: 在标准的最朴素更新下,权重衰减与 ℓ2 正则化等价——可以证明; 但对 Adam 这类自适应优化器,二者并不等价21

为什么最朴素更新下等价? 第 2 节的梯度多了一项 λ·θ, 更新式展开就是 θ ← θ − α·(g + λ·θ) = (1 − αλ)·θ − α·g—— 和第 3 节的式子是同一个形状,(1−β) 对上了 (1−αλ)。

为什么 Adam 下不等价? 回到第 12 章第 6 节: Adam 会把梯度除以一个逐参数的分母。罚项混在损失里,它的那部分梯度也要过这个分母—— 原本「恒定往回拽」的力,被分母随参数的历史扭曲了; 而把衰减直接写在更新那一步,不经过任何分母,每个参数受到的缩小比例才是恒定的。

补充(不在书里,依据我们的 frontier 书架):把衰减从梯度里拿出来、直接写进更新步, 就是「解耦权重衰减」——那个优化器叫 AdamW。 框架的实现里,AdamW 与 Adam 的差别就在这一处:Adam 把罚项算进梯度、过自适应分母; AdamW 在更新时单独执行衰减、不过分母22所以第 16 章训练 Transformer 编码器时,优化器选的是 AdamW 而不是 Adam, 并且只对权重开衰减、对偏置和规范化参数关掉——那一节的设定到那时再读。

书里在这里只点了 AdamW 的名字,调用它做的实验留成了练习23

7. 作者的判断与证据

书里给了证据的:

  • 四组成绩——基线 0.91/0.71,三招 0.86/0.77、0.845/0.75、0.855/0.76, 全部是同一考场同一网络的实际打印281118;
  • 边界图——基线过精细,ℓ2 与权重衰减几乎一致地平滑,暂退法介于中间3919;
  • 最朴素更新下两者等价、Adam 下不等价——书里写明「可以证明」, 但把证明指回了主书方向,正文没有展开21

属于经验判断的:

  • 「暂退法在更深的网络上往往是性价比最高的选项」——书里自己标注了前提 (本节的差别与小数据集和简单网络有关)19;
  • 权重衰减「需要稍微小一些的衰减系数搭配更精细的学习率调度」——经验提示(来自实践的建议,不是书里的实验结论)11

判断(我们的,不是书里的):这一章的四组数不该读成名次表。 三种补救的差距都在一个百分点以内,而它们的作用位置完全不同 (损失里、更新步里、前向过程里)——真正的收获是「过拟合可以从三处下手」这个结构, 不是哪一招赢了。 如果错,会错在: 如果读者的场景只允许加一招,那名次就有意义; 书里的顺序(先罚项、再衰减、再暂退)也确实是工程上常见的尝试顺序。 判据是:三招能不能叠加——书里没做叠加实验,但三处作用位置互不冲突。

8. 边界与局限

这一章没覆盖的:

没讲什么依据 / 为什么值得知道
提前停止怎么做章首只点了名4;第 11 章那个「用验证集最佳快照」的做法就是它的实物
ℓ1 的实验书里只实现了 ℓ2;ℓ1 会把部分参数压到 0 这一句是书外补充
三招叠加的效果全书没有叠加实验
数据层面的一招(造更多数据)全书没有涉及
批大小对泛化的影响第 12 章第 2 节点了一句「小批次的梯度噪声大,泛化不一定更好」24

出门会撞见的名字:

  • L1 / L2 regularization —— 第 2 节那两种罚项写法;
  • weight decay —— 第 3 节那一招;在框架的优化器构造参数里就叫 weight_decay10;
  • dropout(训练时随机关闭一部分神经元的正则化手段) —— 第 4 节那一招,即暂退法;框架里 nn.Dropout;
  • AdamW —— 第 6 节那个解耦版本22;
  • early stopping(提前停止) —— 第 11 章用最佳快照那一招的通用名字。

9. 可带走的

  1. 训练 0.91、测试 0.71 就是「背下来了」——20 个百分点的差距是过拟合的实物;
  2. 正则化的代价结构:训练成绩让一步,换测试成绩涨一截——它从不让训练集更好看;
  3. 罚项有两种写法:取绝对值之和会把小参数压死成 0(顺手筛特征), 取平方和只是把所有参数一起往小里拽;
  4. ℓ2 在代码上只改两处:损失加一项、梯度加一项;
  5. 权重衰减不改损失,改更新那一步:先把参数缩小 (1−β) 倍再更新;
  6. 暂退法训练时随机关、放大 1/(1−p),推断时全开不动——它是推断模式要切换的第二个元凶;
  7. 被关掉的神经元梯度也是 0,前向反向严格对齐;
  8. 三招都把差距压回 10 个百分点以内,作用位置完全不同,不是名次关系;
  9. 罚过头是另一个方向的病——λ = 10、β = 0.1、p = 0.9 是「正则化过度」的考场;
  10. 最朴素更新下 ℓ2 ≡ 权重衰减;Adam 下不等价,所以有了 AdamW

10. 原文地图

主题原书章原文位置
过拟合考场第7章 网络优化与正则化text/08-ch07.txt:1909(搜「刻意设计成易过拟合」)
基线 0.91/0.71第7章 网络优化与正则化text/08-ch07.txt:2107(搜「0.91」)
ℓ1 与 ℓ2第7章 网络优化与正则化text/08-ch07.txt:2143(搜「最经典的正则化手段」)
ℓ2 的两处改动第7章 网络优化与正则化text/08-ch07.txt:2152(搜「前向时损失多加」)
0.86/0.77第7章 网络优化与正则化text/08-ch07.txt:2198(搜「0.86」)
权重衰减第7章 网络优化与正则化text/08-ch07.txt:2218(搜「不再修改损失函数」)
0.845/0.75第7章 网络优化与正则化text/08-ch07.txt:2265(搜「0.845」)
等价与不等价第7章 网络优化与正则化text/08-ch07.txt:2224(搜「并不等价」)
暂退法与放大 1/(1−p)第7章 网络优化与正则化text/09-ch08.txt:11(搜「随机屏蔽一部分神经元」) · text/09-ch08.txt:16(搜「总能量」)
0.855/0.76第7章 网络优化与正则化text/09-ch08.txt:98(搜「0.855」)
边界图对比第7章 网络优化与正则化text/09-ch08.txt:107(搜「相比 ℓ2 正则化的效果略弱」)
AdamW第7章 网络优化与正则化text/08-ch07.txt:1095(搜「AdamW」)

Footnotes

  1. 出处:「第7章 网络优化与正则化」第 1909 段(text/08-ch07.txt:1909,搜「刻意设计成易过拟合」)与第 1915 段(text/08-ch07.txt:1915,搜「前 200 条作训练集」)。原文:为了在同一组实验里横向对照各类正则化的效果,本节先用一个刻意设计成易过拟合的小数据集 + 深层 MLP 把过拟合现象「做出来」;数据取 300 条弯月样本(噪声 0.5),前 200 条作训练集、剩余 100 条作测试集;样本量小、噪声大,正适合让深层网络「过拟合」。

  2. 出处:「第7章 网络优化与正则化」第 2107 段(text/08-ch07.txt:2107,搜「0.91」)与第 2110 段(text/08-ch07.txt:2110,搜「20 个百分点」)。打印输出:train accuracy: 0.91、test accuracy: 0.71;原文:训练集准确率 91%、测试集准确率仅 71%——20 个百分点的差距强烈暗示过拟合。训练设定:三层网络(2 → 20 → 3 → 1),BatchGD 学习率 0.2,训 50 000 步,见第 2094–2104 段。 2 3

  3. 出处:「第7章 网络优化与正则化」第 2132 段(text/08-ch07.txt:2132,搜「切得过于精细」)。原文:散点是真实样本,背景色块是模型学到的两个决策区域;可以看到边界在两类交界处被切得过于精细,呈现典型的「记住每个训练点」的过拟合特征。 2

  4. 出处:「第7章 网络优化与正则化」第 1906 段(text/08-ch07.txt:1906,搜「跌跌不休」)。原文:深网络容量大、表达力强,很容易在训练集上一路降损失却在测试集上跌跌不休——这就是过拟合;要让模型在未见样本上同样可用,需要正则化(Regularization):通过显式约束、加入先验、提前停止等手段,把模型的有效复杂度压下来。 2

  5. 出处:「第7章 网络优化与正则化」第 2143 段(text/08-ch07.txt:2143,搜「最经典的正则化手段」)。原文:ℓ1 和 ℓ2 正则化是最经典的正则化手段——通过约束参数本身的 ℓ1 或 ℓ2 范数,限制模型容量,缓解过拟合;带正则项的优化问题为「最小化 损失 + λ·罚项」,其中 p 通常取 1 或 2 分别对应 ℓ1、ℓ2,λ 是正则化强度。

  6. 出处:「第7章 网络优化与正则化」第 2152 段(text/08-ch07.txt:2152,搜「前向时损失多加」)。原文:把 ℓ2 正则化加到上面的过拟合实验里——前向时损失多加 λ/(2B)·‖θ‖²,反向时每个参数梯度多加 λ/B·θ;代码上前向累加各线性层权重平方和,反向把 λ·W/B 加进各层权重梯度。

  7. 出处:「第7章 网络优化与正则化」第 2189 段(text/08-ch07.txt:2189,搜「其他配置完全不变重新训练」)。原文:取 λ = 0.7,其他配置完全不变重新训练 50 000 步。

  8. 出处:「第7章 网络优化与正则化」第 2198 段(text/08-ch07.txt:2198,搜「0.86」)与第 2201 段(text/08-ch07.txt:2201,搜「小幅让步」)。打印输出:train accuracy: 0.86、test accuracy: 0.77;原文:训练集准确率从 91% 降到 86%、测试集却从 71% 升到 77%——训练精度小幅让步换来泛化精度的明显提升,正是 ℓ2 正则化的预期效果。 2

  9. 出处:「第7章 网络优化与正则化」第 2206 段(text/08-ch07.txt:2206,搜「明显比基线更平滑」)。原文:决策边界明显比基线更平滑,不再追着每个训练点跑——过拟合得到缓解,与准确率数字一致。 2

  10. 出处:「第7章 网络优化与正则化」第 2218 段(text/08-ch07.txt:2218,搜「不再修改损失函数」)与第 2256 段(text/08-ch07.txt:2256,搜「取权重衰减系数」)。原文:权重衰减(Weight Decay)是另一条常用思路——不再修改损失函数,而是在每次更新参数时让权重自身按比例缩小:θ ← (1−β)·θ − α·g,β 典型值 0.0001 ∼ 0.001;实验取 β = 0.001,关掉 ℓ2 正则化(λ = 0),其他配置不变重新训练。 2

  11. 出处:「第7章 网络优化与正则化」第 2265 段(text/08-ch07.txt:2265,搜「0.845」)与第 2269 段(text/08-ch07.txt:2269,搜「稍微小一些的衰减系数」)。打印输出:train accuracy: 0.845、test accuracy: 0.75;原文:过拟合显著减弱,但仍有空间;可见单独使用权重衰减效果接近 ℓ2 正则化,但通常需要稍微小一些的衰减系数搭配更精细的学习率调度。 2 3

  12. 出处:「第7章 网络优化与正则化」第 2274 段(text/08-ch07.txt:2274,搜「几乎一致」)。原文:边界依旧平滑,与 ℓ2 正则化版本几乎一致。

  13. 出处:「第7章 网络优化与正则化」第 11 段(text/09-ch08.txt:11,搜「随机屏蔽一部分神经元」)。原文:暂退法(Dropout)的思路与前两种正则化截然不同——训练时在每一步随机屏蔽一部分神经元(输出强制设为 0),让网络无法依赖任何特定子集,被动学会「分布式表示」,从而缓解过拟合;最常见的做法是给每个神经元独立设定一个固定的丢弃概率 p。注意这一段正文因转码时的章节边界错位,落在了 text/09-ch08.txt 的开头。 2

  14. 出处:「第7章 网络优化与正则化」第 16 段(text/09-ch08.txt:16,搜「总能量」)。原文:仅这一步还有副作用——训练时部分神经元被屏蔽,激活值的总能量比推断时低;而推断阶段保留全部神经元,激活值的期望幅度(方差)与训练阶段不一致;常见的修补办法是 inverted dropout——训练阶段把保留下来的激活放大 1/(1−p) 倍,让训练和推断的输出方差大致对齐。

  15. 出处:「第7章 网络优化与正则化」第 26 段(text/09-ch08.txt:26,搜「略有不同」)。这是书里的提醒框:公式与主书略有不同——主书是「训练阶段保留、推断阶段缩放」,本书采用「训练阶段缩放、推断阶段保留」的 inverted dropout 版本,这也是 PyTorch、TensorFlow 等框架的默认实现。

  16. 出处:「第7章 网络优化与正则化」第 34 段(text/09-ch08.txt:34,搜「梯度也是 0」)。原文:注意——被屏蔽神经元的梯度也是 0,与前向行为完全对齐。

  17. 出处:「第7章 网络优化与正则化」第 56 段(text/09-ch08.txt:56,搜「各插一个」)与第 90 段(text/09-ch08.txt:90,搜「单独看 Dropout 的效果」)。原文:在两层 ReLU 激活之后各插一个 Dropout 层,前向时按模式决定是否启用;取丢弃概率 p = 0.3,关掉 ℓ2 正则化与权重衰减,单独看 Dropout 的效果。

  18. 出处:「第7章 网络优化与正则化」第 98 段(text/09-ch08.txt:98,搜「0.855」)与第 101 段(text/09-ch08.txt:101,搜「与权重衰减相近」)。打印输出:train accuracy: 0.855、test accuracy: 0.76;原文:与权重衰减相近,暂退法同样把训练-测试差距大幅压低,过拟合显著缓解。 2

  19. 出处:「第7章 网络优化与正则化」第 107 段(text/09-ch08.txt:107,搜「相比 ℓ2 正则化的效果略弱」)。原文:决策边界比基线更平滑,过拟合得到缓解;不过相比 ℓ2 正则化的效果略弱,这与本节使用的小数据集和简单 MLP 有关——在更深、参数更多的网络上,Dropout 往往是性价比最高的选项。 2 3

  20. 出处:「第7章 网络优化与正则化」第 121 段(text/09-ch08.txt:121,搜「正则化过度」)。这是动手练习 7.11:分别把正则化系数 λ、权重衰减系数 β 和暂退率 p 调到很大(如 λ = 10、β = 0.1、p = 0.9),观察训练集准确率和测试集准确率会如何变化——这是定位「正则化过度」的好练习。

  21. 出处:「第7章 网络优化与正则化」第 2224 段(text/08-ch07.txt:2224,搜「并不等价」)。原文:可以证明——在标准 SGD 下,权重衰减与 ℓ2 正则化等价;但对 Adam 这类自适应优化器,二者并不等价,这正是 AdamW 被提出的原因。 2

  22. 补充(不在书里,依据我们的 frontier 书架):AdamW 把权重衰减从梯度中解耦出来、在更新步单独执行,不再经过自适应分母。依据: shelf=ai-frontier-reference/pytorch@src:torch/optim/adamw.py:95 @c187ef3271d5555d2d79a7c599263be58e036d62 事实=该文件的文档字符串在此处把算法指向 Decoupled Weight Decay Regularization 那篇论文,与 Adam 的文档字符串并列两份引用。 2

  23. 出处:「第7章 网络优化与正则化」第 1095 段(text/08-ch07.txt:1095,搜「AdamW」)。这是动手练习 7.6:学习 AdamW 算法,使用 torch.optim.AdamW 作为优化器训练网络,进行简单的拟合实验。

  24. 出处:「第7章 网络优化与正则化」第 303 段(text/08-ch07.txt:303,搜「批大小越小、学习率同步缩小」)。原文:而且小批次的梯度噪声大,泛化不一定更好。