all_lessons/数学的逻辑/39第 40 课 / 共 44 课

第十一部分 · 从一个神经元到现代 AI

为什么学得会:泛化、偏差-方差与正则化

上一课的万能逼近定理给了我们一个吓人的承诺:只要神经元够多,网络能拟合任何数据。可这恰恰是最大的隐患——一个能拟合任何东西的模型,完全可以把训练集连同噪声一起死记硬背下来。那它凭什么在从没见过的新数据上还能work?这一课回答机器学习最深的地基问题:为什么"学得会"是可能的。

线性回顾
上一课:万能逼近定理(第 38 课)证明了一件让人振奋的事——一个足够宽的神经网络,可以逼近任意连续函数。表达能力,管够。
留下的问题:可"能拟合任何函数"是把双刃剑。给定 n 个训练点,一个容量足够大的模型总能穿过每一个点、把训练误差压到零——包括那些点上的随机噪声也一起背下来。它在训练集上满分,却可能在新数据上一塌糊涂。拟合训练数据从来不是目的;在没见过的数据上表现好,才是。凭什么它能做到?
本课新增:训练误差 vs 测试误差、过拟合偏差-方差分解容量/VC 维的直觉,以及正则化——而正则化的真面目,是把"参数该简单"这个贝叶斯先验写进优化目标(呼应第 31 课的 MAP)。
本课路线
(1) 背下来 ≠ 学会了:训练误差与测试误差是两回事。(2) 那条 U 形曲线:模型越复杂,训练误差一路降,测试误差却先降后升——甜点在中间。(3) 偏差-方差分解:测试误差 ≈ 偏差² + 方差 + 噪声(打靶的比喻)。(4) 容量与数据量:容量/VC 维越大越容易过拟合,更多数据收紧泛化界。(5) 正则化 = 给复杂度上税 = 高斯先验下的 MAP。

背下来 ≠ 学会了

先把两个词分清楚。你在训练集上算出来的误差,叫训练误差;你真正关心的、模型在从未见过的新数据上的误差,叫测试误差(也叫泛化误差)。学习的目标一直是后者——前者只是我们能直接优化的那个替身。

为什么两者能差这么远?看一个极端例子。给你 10 个数据点,你想拟合一条曲线。用一个 9 次多项式c₀ + c₁x + c₂x² + … + c₉x⁹,10 个可调系数)去拟合——数学上一定能找到一组系数,让这条曲线精确穿过全部 10 个点,训练误差恰好为零。完美!

可这条曲线在点与点之间会疯狂地上下抖动(为了穿过每个点,它不得不剧烈扭曲),在任何一个新的 x 上给出的预测都荒腔走板。它没有学到数据背后的规律,它只是把这 10 个点的坐标(连同其中的噪声)了下来。这就是记忆泛化的根本区别:

记忆:把训练样本逐一记住,训练误差趋近零,但换一批数据就抓瞎。
泛化:抓住数据背后可复用的规律,因此对没见过的数据也能给出靠谱的预测。
一个模型训练误差为零,什么都说明不了——它可能学会了,也可能只是背了答案。

这正是万能逼近定理留下的隐患:表达能力太强,反而给了模型"作弊背答案"的空间。一台好的学习机器,需要的不是"能拟合一切",而是"在拟合数据和保持简单之间恰到好处"。

那条 U 形曲线:过拟合

把"模型复杂度"(比如多项式的次数、网络的宽度)当成横轴,画两条误差曲线,你会看到机器学习里最重要的一张图:

训练误差:随复杂度上升单调下降——模型越复杂,越能贴合训练点,一路降到零。
测试误差:随复杂度上升先降后升,是一条 U 形曲线——先因为模型终于够用而下降,过了某个点,又因为开始背噪声而回升。

两条曲线的分岔把复杂度轴切成三段:

关键的判断信号,是训练误差和测试误差之间那道(泛化间隙)。缝很小、但两个都高 → 欠拟合;缝很大(训练低、测试高)→ 过拟合;两个都低 → 恰好。本课的小实验会让你亲手把这条 U 形曲线拉出来

偏差-方差分解:打靶的两种失手

U 形曲线不是玄学,它背后有一个漂亮的数学分解。假设真实数据是"真规律 + 噪声"生成的,那么模型在一个新点上的期望测试误差可以拆成三块:

期望测试误差 ≈ 偏差² + 方差 + 不可约噪声

(读作"平均而言,你在新数据上犯的错,等于'偏差的平方'加'方差'再加'谁也消不掉的噪声'"。)

三个词各是什么,用打靶的比喻一秒讲清。想象你反复用不同的训练集训练同一种模型,每次得到的预测就是打在靶上的一发子弹:

偏差(Bias)= 瞄偏了。子弹平均落点系统性地偏离靶心。模型太简单,它的形状根本够不着真规律(直线永远拟合不出正弦波的弯),无论给多少数据都偏——这就是欠拟合

方差(Variance)= 手抖。子弹落点散得到处都是。模型太复杂,对训练集里每一点抖动都过分敏感,换一批训练数据,学出来的曲线就面目全非——这就是过拟合

不可约噪声:靶子本身在晃(数据里天生的随机性)。这块是物理下限,任何模型都消不掉。

现在 U 形曲线就说得通了。简单模型:高偏差、低方差(稳定地瞄偏)。复杂模型:低偏差、高方差(平均瞄得准,但每次都手抖到不知飞哪去)。复杂度从低往高走,偏差一路降、方差一路升,两者之和——测试误差——自然先降后升,谷底就在偏差和方差的拉锯达到平衡的地方。这就是著名的偏差-方差权衡:你没法同时把两者都压到最小,只能找那个最佳折中。

容量与数据量:模型能背下多少

"复杂度"能不能量化?能。一个模型的容量(capacity),粗略地说就是"它能完美拟合多少种不同的数据集"。刻画容量的经典指标叫 VC 维,直觉版定义是:模型能"打散"(shatter)的最多点数——所谓打散,就是不管你把这些点的标签怎么摆(正正负、正负正、……任意组合),模型都能找到一组参数把它们完全分对。能打散的点越多,容量越大,模型越"油滑"。

容量直接决定过拟合的风险。有一个(简化版的)泛化界把这件事说得很干脆:

测试误差 ≲ 训练误差 + O( √( 容量 / n ) )

(读作"测试误差,大致不超过训练误差,再加上一项正比于'根号下(容量除以样本数 n)'的间隙"。 读作"大致不超过",n 是训练样本数。)

这个不等式一次讲清了三件事:

还记得第 24 课的维度灾难吗?维度越高,把空间填满所需的样本数指数爆炸,等价于说:在高维里,同样的 n 显得格外稀疏,那道缝格外难收窄——所以高维时更容易过拟合。泛化界里的 √(容量/n) 和维度灾难,讲的是同一堵墙的两面。

正则化 = 给复杂度上税 = 先验

既然过拟合来自容量太大,最直接的对策就是压制容量——但不是粗暴地砍掉参数,而是在优化目标里给"复杂"上一道税。这就是正则化:不再单纯地最小化训练损失,而是最小化"训练损失 + 复杂度惩罚"。

新目标 = 训练损失 + λ · 复杂度惩罚

(读作"要最小化的,是原来的训练损失,加上一个'惩罚项'乘以旋钮 λ"。λ 读作"拉姆达",是控制惩罚力度的超参数:λ=0 就是不管复杂度、放任过拟合;λ 越大,越逼模型选简单解。)

常见的几种"税":

但正则化最深刻的一层意义,不是这些工程技巧,而是它和第 31 课的MAP严丝合缝地对上了。回忆一下:MAP(最大后验)在 MLE(最大似然)的基础上,乘进了一个关于参数的先验。现在做一件事——给权重假设一个均值为 0 的高斯先验("我事先就相信权重应该小、应该接近 0"),然后照第 31 课的套路做 MAP、取对数:

−log 后验 = −log 似然 + (1/(2σ²)) ∑wᵢ² + 常数

(读作"负的对数后验,等于负的对数似然(也就是训练损失),加上一项正比于权重平方和的项"。)

看清楚了吗?那个凭空冒出来的 L2 惩罚项 ∑wᵢ²,正是高斯先验取对数后的产物——而惩罚力度 λ = 1/(2σ²) 由先验的"宽窄" σ 决定:你越确信权重该小(先验越窄、σ 越小),λ 就越大,税就越重。于是:

一次合体 · 正则化 = MAP
L2 正则化 = 给权重加一个高斯先验后的最大后验(MAP)估计。正则化不是拍脑袋的 hack,它是把"参数应该小、应该简单"这个先验信念,用数学写进了优化目标。第 31 课的贝叶斯推断和这一课的正则化,是同一件事的两种说法。(顺带一提:L1 惩罚对应的则是拉普拉斯先验。)

本课的小实验会把这一切演成一场戏:把多项式次数 d 拉到 9、λ 归零,你会看到训练误差冲向零、测试误差却爆炸(过拟合);再把 λ 拧上去,曲线立刻平滑下来、测试误差回落——正则化救场,U 形曲线活生生地在你眼前展开。

过拟合 U 形曲线:多项式拟合
一组固定的训练点(实心圆,带噪声)来自一条真曲线 y = sin(πx)(浅色);另有一组测试点(空心圆)来自同一条真曲线。我们用岭回归拟合一个 d 次多项式。玩法:先把 λ=0,拉高次数 d → 训练误差奔向 0,但曲线开始疯狂抖动、测试误差飙升(过拟合);再拧大 λ → 曲线被抹平、测试误差回落(正则化救场)。这就是 U 形曲线,活的。
训练误差 (MSE)
测试误差 (MSE)
状态

常见误解

一句话带走
能拟合一切的模型,也能背下一切——所以训练误差为零毫无意义,测试误差才算数。它随复杂度走出一条 U 形曲线(偏差² + 方差 + 噪声:太简单则高偏差/欠拟合,太复杂则高方差/过拟合),甜点在中间。控制容量的通用旋钮是正则化——而 L2 正则化就是高斯先验下的 MAP(第 31 课),把"参数该简单"这条先验写进了优化目标。更多数据 + 匹配的容量,才是泛化的正道。
下一步
正则化是一把通用的容量旋钮——它对任何模型、任何数据都一视同仁地"给复杂度上税"。可对图像、序列这种自带结构的数据,我们其实有一招更聪明的:与其事后惩罚复杂度,不如干脆把数据的结构("图像有局部性、有平移不变性")直接刻进网络的架构里,当成一种最强硬的先验。这种"把结构变成先验"的思想,就叫归纳偏置,而卷积正是它最漂亮的一次落地。→ 第 40 课《归纳偏置:卷积如何把结构变成先验》。