第 10 章 · 学习是怎么发生的
正则化与泛化
训练能跑稳了,新问题来了:模型在训练集上考了满分,一到没见过的数据就露馅。 这叫过拟合——它把训练题“背下来”了,却没真正“学会”。这一章讲清楚什么是泛化、什么是过拟合, 以及一整套对付它的常用招:weight decay、Dropout、early stopping、数据增强。
读完这一章,你会明白
- 泛化才是目标:训练集好不算好,没见过的数据上好才算好;
- 怎么从训练/验证曲线一眼看出过拟合、欠拟合;
- 偏差与方差为什么此消彼长,泛化的“甜区”在哪;
- L2 / L1 / weight decay 为什么能让模型“更平滑、别太自信”;
- Dropout 怎么靠“随机罢工”逼网络别依赖个别神经元,以及测试时为什么要关掉它;
- early stopping 和数据增强这两招,以及“更多数据”为什么是最强正则。
1. 泛化:考的是“没见过的题”
我们训练模型,真正想要的不是它在训练数据上表现好,而是它在将来没见过的新数据上也表现好—— 这个能力叫泛化(generalization)。就像考试:你要的是“真会做题”, 而不是“把练习册答案背下来”。练习册全对但一考新题就崩,那是白学。
为了诚实地衡量泛化,数据会被分成训练集(用来学)和测试集(用来考,训练时绝不能碰)。 通常还留一份验证集用来边训边监控。怎么分、怎么用,是下一章(第 11 章)的主题; 这一章先聚焦“怎么让模型别把训练集背下来”。
2. 过拟合 vs 欠拟合
训练中会遇到两种“没学好”:
- 欠拟合 underfitting训练集都学不好:模型太弱、或训练不够。表现是训练误差、测试误差都高。
- 过拟合 overfitting训练集很好、测试集拉垮:模型把训练数据的噪声和细节都背了下来。表现是训练误差很低,但测试误差高——两者裂开一道大口子。
典型过拟合信号:训练损失(绿)一路下降,但验证损失(黄)降到某点后反而回升——模型开始背训练集了。
正则化(regularization)就是一类专治过拟合的手段。它们的共同思路只有一句话: 给模型加点“约束”或“干扰”,逼它别把训练集硬背下来,而去学更通用的规律。 在动手之前,先看一眼过拟合和欠拟合背后那对更本质的概念。
3. 偏差与方差:欠拟合和过拟合的“根”
欠拟合和过拟合,其实是同一枚硬币的两面,背后是一对此消彼长的量: 偏差(bias)和方差(variance)。
- 偏差:模型假设太死板,连训练数据的真实规律都抓不住,产生系统性的偏。高偏差 → 欠拟合。
- 方差:模型太敏感,把训练集里的噪声也当成规律学了进去,换一批数据结果就大变。高方差 → 过拟合。
把预测想成打靶:高偏差是每一箭都稳稳地偏向同一边(准星歪了,再稳也脱靶); 高方差是箭散得到处都是(准星没歪,但手一直在抖)。 我们真正想要的,是又准又稳——但现实里,压低一个往往会抬高另一个。
模型在新数据上的总误差,可以粗略拆成三块:
关键在于:模型越复杂(层更深、参数更多、训练更久),偏差越小,但方差越大; 越简单则反过来。所以总误差通常是一条 U 形曲线——两头都差,最优点在中间那个“不太死板、也不太敏感”的甜区。
复杂度越高,偏差(蓝)越小、方差(黄)越大;总误差(绿)是 U 形,谷底就是泛化最好的“甜区”。
想明白这一点,正则化的本质就清楚了:它是主动往模型上加约束,牺牲一点点偏差,换来方差的大幅下降, 从而把总误差推到更靠近谷底的位置。下面第 4–7 节的四招——weight decay、Dropout、early stopping、数据增强—— 全都在做这同一件事,只是切入点不同。
4. L2 正则 / weight decay:别让权重太“嚣张”
过拟合的模型常有一个特征:某些权重变得非常大,对个别特征反应过激(“一朝被蛇咬”式的死记)。 L2 正则的办法是:在损失里加一项“所有权重的平方和”,让“权重太大”本身也成为一种“错”:
效果是把权重往 0 拉一把,模型变得更“平滑、克制”,不会为了迁就某几个训练样本而走极端,泛化通常更好。 在代码里,它就是第 8 章优化器接口的一个开关:
void set_weight_decay(double wd); // 只对 weight 生效, bias 不衰减 1
- 给优化器设一个
weight_decay,训练时每步就会顺带把权重往 0 收一点。注意只惩罚权重、不惩罚 bias;Adam 与 AdamW 对它的耦合方式不同(第 8 章)。
如果把惩罚项从“权重平方和”换成“权重绝对值之和”(λ·Σ|权重|),就是 L1 正则。 两者都压小权重,但性格不同:L2 把权重均匀地往 0 挤,得到一堆“都挺小但都不为 0”的权重,更平滑; L1 则倾向于把一部分权重直接压成 0,相当于自动做“特征筛选”,得到稀疏的模型。 想让模型自己挑出少数关键特征,用 L1;只想让它整体收敛、别走极端,用 L2(也是深度学习里的默认选择)。
5. Dropout:让神经元“随机罢工”
Dropout是个又简单又神奇的招:训练时,每一步随机“关掉”一部分神经元 (比如随机让 20% 的神经元输出 0),每步关掉的还不一样。测试时再把它们全打开。
如果训练时随时有队员被随机叫去罢工,整支队就不敢过度依赖某个明星球员,每个人都得练出真本事、 学会互相配合。网络也一样:Dropout 逼它不把宝押在个别神经元上,而是学出更鲁棒、更分散的表示, 于是更不容易过拟合。相当于同时训练了无数个“缺人版”的小网络,再取平均。
这里有个容易被忽略的细节:训练时关掉了一部分神经元,测试时又全开,两边的输出规模就对不上了。 比如训练时随机丢掉一半,那一层的输出总量平均只有平时的一半;测试时全开,总量却翻倍,后面的层就“懵”了。 解法是做一次缩放:常见做法叫 inverted dropout——训练时把没被丢掉的神经元输出除以保留比例 (丢一半就乘 2),把总量补回来;这样测试时啥都不用改,直接全开即可。记住一句话:Dropout 只在训练时开,测试/推理时关。
6. Early stopping:见好就收
回看上面那张曲线图:验证损失降到最低点后开始回升,那个拐点就是“学得刚刚好、还没开始背书”的时刻。 early stopping(早停)的做法直白得可爱:一边训一边盯验证集,一旦它连续几轮不再改善,就停, 并回退到验证表现最好的那个存档。既省算力,又正好卡在过拟合之前。
7. 数据增强,以及“更多数据”这剂猛药
还有一类正则化是在数据上做文章:
- 数据增强 data augmentation对训练样本做不改变含义的小变换,凭空造出更多样本。图像里常见:随机裁剪、翻转、旋转、调亮度——一张猫图转个角度还是猫,但模型见的“花样”更多了,自然更难死记。
- 更多真实数据最有效的正则化,往往就是喂更多数据。数据越多越杂,模型越没法靠背,只能去学真正通用的规律。这也是第 20 章“大力出奇迹”的伏笔:大模型能那么强,海量数据本身就是最强的抗过拟合手段。
这些招看着五花八门,内核是同一个:故意给学习过程“添点乱”或“加点约束”,不让模型舒舒服服把训练集背下来。 weight decay 约束权重、Dropout 随机罢工、early stop 见好就收、增强/更多数据摊薄记忆——目标都只有一个:泛化。
小结
- 泛化才是目标:要的是没见过的数据上也好,而不是把训练集背下来。
- 过拟合 = 训练好、测试差(背题);欠拟合 = 都差(没学会)。看训练/验证曲线的“裂口”即可判断。
- 偏差 vs 方差:欠拟合是高偏差、过拟合是高方差;总误差是 U 形,正则化用一点偏差换方差,逼近谷底“甜区”。
- weight decay(L2):惩罚大权重,让模型更平滑克制;L1 则会把部分权重压成 0,得到稀疏模型。
- Dropout:训练时随机关神经元(并做缩放),测试时全开;逼网络别依赖个别单元。
- early stopping:验证损失回升前收手;数据增强/更多数据是最本质的正则。
我们一直在说“训练集、验证集、测试集”“看验证损失”——可这些到底该怎么分、怎么读指标? 下一章我们就把评估与数据这件事讲透:数据集划分、准确率/精确率/召回、混淆矩阵、预处理与调试。