第 7 章 · 泛化

过拟合:背答案的学生

模型在练习卷上考了满分,换套卷子却一塌糊涂——「学得太好」为什么反而是病?这一章我们亲手把过拟合制造出来,再亲手把它治回去。

7.1 背答案的学生

先讲个故事。小明要备考数学,他的策略是「背」:把练习册上每道题的答案硬背下来——第三题选 C,第五题答案是 42,甚至把某页的印刷错误都原样背了进去。练习卷发下来,他考了满分;正式考试换了一套题,他直接崩盘。

机器学习里的模型会犯一模一样的病。用上一章的梯度下降把训练误差一路压到接近零,听起来是大获全胜——但如果它只是「背下了训练数据」,换一批没见过的新数据,误差立刻打回原形。这种病叫过拟合(overfitting):训练集上表现满分,新数据上一塌糊涂。

反过来,如果模型简单到连训练集都学不好(比如用一条直线去拟合波浪),那叫欠拟合(underfitting)——连背答案都没背会。

这里有两个关键数字,务必分清楚:

我们真正关心的从来只有后者。训练误差只是手段,测试误差才是目的——模型存在的意义,是处理好没见过的数据。

💡 一句话直觉

学习的目标是「举一反三」,不是「过目不忘」。把练习册背到满分却做不出新题的学生,并没有真的学会。

⚠ 常见坑

测试集只能用来「阅卷」,绝不能用来「备考」。如果你看着测试误差调模型、挑模型,相当于偷看了考卷再复习——成绩从此作废,它再也测不出真实水平。需要边调边看?单独留一份验证集(7.5 节的「提前停止」就靠它)。

7.2 偏差–方差权衡

为什么模型会去背答案?因为它「太聪明了」——准确说,是它的灵活度相对于数据量太高了。想象用不同阶数的多项式去拟合一段波浪形的数据:

「方差」这个名字很形象:过拟合的模型对数据极度敏感,换一批训练数据,学出来的曲线面目全非——预测忽左忽右,方差自然大。统计学里有一个著名的分解,把泛化误差拆成三块:

泛化误差 ≈ 偏差2 + 方差 + 不可约噪声

最后一项是数据本身携带的噪声,神仙也消不掉。我们能做的,是在偏差与方差之间走钢丝,找到总和最小的那个甜点。

∑ 想深一层

偏差大 = 模型「天生笨」,换多少数据都学不对;方差大 = 模型「神经质」,数据稍有风吹草动就反应过度。好学生要「稳」也要「准」,可惜二者通常此消彼长——这就是「权衡」(trade-off)一词的分量。

7.3 多项式实验台

空说不如动手。假设上帝视角下的真实规律是一条正弦波 f(x) = sin(2πx),x ∈ [0, 1]——你看不到它,你只能拿到 14 个带噪声的观测点(噪声 σ ≈ 0.15)。你的武器是一族多项式:

f(x) = w0 + w1x + w2x2 + ⋯ + wdxd

阶数 d 就是你手里的「灵活度旋钮」:d = 1 是直线,d 越大曲线越能扭。下面的实验台用最小二乘法求出当前数据下误差最小的那组系数——整个求解(正规方程 + 高斯消元)都是这一页用原生 JS 现场算的。

演示 1 · 多项式拟合实验台

拖滑块 + 重采样

深色实心点是训练数据(模型只能看到这些),淡灰空心点是测试点——只负责阅卷,绝不参与拟合;灰色虚线是上帝视角的真实规律。把阶数拉到 12 以上,看曲线为了穿过每个点扭成麻花。

训练 MSE 测试 MSE 最大 |w|

把阶数从 1 慢慢拉到 15,你会看完一整出三幕剧:d = 1 时直线根本拐不过两个弯,训练、测试误差双高——欠拟合;d = 3 ~ 5 时曲线既贴合训练点又接近真实波形,两个误差都低——甜点;d ≥ 12 时曲线精确地穿过每一个训练点,训练误差几乎归零,但点与点之间疯狂扭动,测试误差一飞冲天——教科书级的过拟合。

盯住读出里的「最大 |w|」:过拟合时它会飙到成千上万。剧烈的扭动只能靠巨大的正负系数互相抵消才拼得出来——权重爆炸就是过拟合的指纹。下一节的药,就开在这一点上。

再点点「重采一批数据」:高阶拟合的形状会完全变样(它对噪声太敏感,正是方差大),而低阶拟合几乎纹丝不动。另外那 40 个淡灰空心测试点,是模型从没见过的「正式考卷」——拟合时它们被严格隔离。

7.4 正则化:给「太自由」的模型上镣铐

过拟合的症结是「太自由」:14 个点,它有 16 个系数,背下来绰绰有余。正则化(regularization)的思路简单粗暴——既然过拟合的指纹是权重爆炸,那就给权重上镣铐,谁也不许太大。最常用的 L2 正则化,在损失函数里加一项「权重平方和」:

L = (1/n)· Σi ( yi − f(xi) )2 + λ · Σj wj2

前半项还是老目标「拟合训练数据」,后半项是新加的惩罚:权重越大,代价越高。λ(读作 lambda)这只旋钮控制镣铐的松紧:

为什么压住权重就能治过拟合?多项式想扭出剧烈的急弯,必须靠巨大的高阶系数互相抵消;系数一被压小,曲线自然变平滑。L2 正则化因此也叫权重衰减(weight decay)——训练时权重每走一步都被往 0 拽一点。

∑ 想深一层

加上 L2 惩罚后,最小二乘仍有闭式解,只需在正规方程的对角线上加 λ:

( XTX + λ·I ) · w = XT · y

所以它得了个外号叫「岭回归」(ridge regression),本章实验台就是这么算的。工程上还有个细节:先把 x 归一化到 [−1, 1] 再取幂,否则 15 次幂会让正规方程病态到无法求解。

演示 2 · 双 U 曲线:误差的分岔口

随 λ 实时重算

这张图针对演示 1 的当前数据和 λ,把每个阶数都重新拟合了一遍。把演示 1 的阶数拉到 12 以上:训练误差贴地、测试误差飞天;保持高阶不动,再拉大 λ,看测试曲线被整条「救回」。

甜点阶数 最低测试 MSE

读这张图:横轴是灵活度,纵轴是误差(对数刻度)。λ = 0 时,训练误差一路贴地,测试误差先降后升,谷底就是「甜点」;把 λ 拉到 10−3 再看,测试曲线被整条救回,连 d = 15 都不再飞天——代价是甜点变浅了一点。λ 继续加大,两条曲线会一起抬头:镣铐太紧,连真实规律也学不动了。

7.5 更多武器

L2 只是武器库里的一件。实战中对付过拟合,常用的还有这三件:

武器一:更多数据

最朴素也最有效的一件。14 个点背得下来,1400 个点就背不动了——噪声之间互相矛盾,唯有真实规律能同时讨好所有数据。只要条件允许,先问「能不能搞到更多数据」,再谈别的技巧。(图像领域的数据增强,本质上也是人工变出更多数据。)

武器二:提前停止(Early Stopping)

训练神经网络时,训练误差一路下降,验证误差却往往先降后升——在回升的那个瞬间果断叫停,把当时的权重留下来。相当于在学生「开始背答案」之前收走练习册。成本几乎为零,是深度学习训练的标配。

武器三:Dropout(随机失活)

训练时每走一步都随机关掉一部分神经元(比如一半),下一步再换一批关。网络从此不敢把宝押在任何单个神经元上——就像公司强制轮岗,防止核心业务只有一个人会。结果是网络被迫学出多套「冗余备份」,同一个特征有多条通路可以表达,整体鲁棒得多。测试时全员到岗,效果反而更好。

✓ 本章小结

过拟合就是「背答案」:训练满分,换卷就崩。泛化误差 ≈ 偏差² + 方差 + 噪声——太简单欠拟合、太灵活过拟合,甜点在中间。武器库:L2 正则化给权重上镣铐、更多数据、提前停止、Dropout。铁律只有一条:测试集只能阅卷,不能备考。