第 8 章 性能度量(Measuring performance)
本章一句话:训练误差降到零并不代表模型好;真正要看的是测试误差,而测试误差由噪声 + 偏差 + 方差三部分构成,理解它们如何随“数据量”和“模型容量”变化(包括反直觉的双下降现象),就能用验证集理性地挑选超参数。
读这章的收获:分清训练集 / 验证集 / 测试集的职责;掌握误差的三大来源与偏差-方差权衡;看懂过拟合/欠拟合;理解容量超过数据量后测试误差为何还能再降(双下降与“插值阈值”直觉);学会用验证集选超参数。
本章速览
- 训练好 ≠ 泛化好:容量足够时网络能在训练集上做到完美(误差为零),但在没见过的测试数据上可能错得很离谱。能保持的那部分性能就叫泛化(generalization)。
- 三个数据集,各司其职:训练集学参数、验证集选超参数、测试集估真实性能。三者必须分开。
- 测试误差 = 噪声 + 偏差 + 方差(回归 + 最小二乘损失下严格可加)。噪声是任务本身的不可消除下限;偏差是模型不够灵活;方差是训练数据有限带来的随机抖动。
- 怎么减误差:加数据 → 降方差;加容量(更多隐藏单元/层)→ 降偏差,但对固定数据量会抬高方差——这就是偏差-方差权衡,存在一个最优容量。
- 双下降(double descent):容量越过“参数数 ≈ 数据量”的插值阈值后,测试误差会先冲高再重新下降,甚至比经典最优还低——经典偏差-方差曲线之外的第二段下坡。
- 为什么会双下降:高维空间数据极稀疏(维度灾难),过参数化模型倾向于在数据点之间做更平滑的插值,平滑解通常泛化更好;这种偏好被认为来自初始化/训练算法的隐式正则化。
- 选超参数的方法:用不同超参数训练多个模型,在验证集上比性能、留最好者,最后只在测试集上报一次成绩。超参数空间离散、条件依赖、不可求导,需专门的搜索算法。
8.1 训练一个简单模型
先用一个具体例子建立直觉。书中用 MNIST-1D 数据集:把手写数字 0–9 的一维“模板”随机变换、加噪声后,在 40 个位置采样,得到 40 维输入 \(x\),标签 \(y\in\{0,\dots,9\}\) 共 10 类。训练集 \(I=4000\) 个样本,每类约 400 个。
模型是一个有两个隐藏层(每层 100 个隐藏单元)的网络,40 维输入、10 维输出经 softmax 得到类别概率,用多类交叉熵损失、随机梯度下降训练(批大小 100、学习率 0.1、训练 6000 步,约 150 个 epoch)。
观察训练曲线,会看到一个关键现象:
- 训练误差随训练步数持续下降,约 4000 步后训练数据被完全分类正确,训练损失最终趋近于零。
- 但这不代表模型真的好——它可能只是把训练集“背”了下来,却无法预测新样本。
要估计真实性能,必须另准备一个测试集(这里再生成 1000 个同分布样本)。结果:
- 测试误差也在下降,但只降到 约 40% 就降不动了。比 90% 的瞎猜强,却远差于训练集——模型没有泛化好。
- 测试损失更耐人寻味:前约 1500 步在下降,之后反而回升。此时测试错误率基本不变,模型犯的还是同样的错,只是越来越自信。softmax 为了让训练数据的概率逼近 1,把 pre-softmax 激活推向极端值;对那些本就答错的样本,错误答案的“信心”越来越高,正确答案的概率被压低,负对数似然(损失)于是上升。
直觉小结:训练误差归零是“能力”,测试误差降不下去是“泛化的失败”。损失先降后升,是“越来越自信地犯同样的错”。
8.2 误差来源(噪声、偏差、方差)
为了把“为什么会有误差”讲清楚,书中换到一个能看清真相的玩具问题:一维最小二乘回归。真值是一条类正弦曲线;训练和测试数据都通过在 \([0,1]\) 上采样、过这条曲线、再加固定方差的高斯噪声生成。
用一个简化的浅层网络拟合:输入到隐藏层的权重/偏置被固定,使各隐藏单元的“折点(joint)”在区间上均匀分布。若有 \(D\) 个隐藏单元,折点就在 \(0,1/D,\dots,(D-1)/D\)。于是模型能表示 \([0,1]\) 上含 \(D\) 个等宽区间的任意分段线性函数。这个模型还能闭式求解(不需随机优化),所以一定能找到损失的全局最小,便于把误差来源看清楚。
8.2.1 三种误差来源
测试误差有三个来源,分别叫噪声、偏差、方差:
- 噪声(noise):数据生成本身带随机性——同一个输入 \(x\) 可能对应多个合法的 \(y\)。这是测试性能的根本下限,无法消除。值得注意的是,噪声未必限制训练表现:训练中几乎不会两次见到完全相同的 \(x\),所以仍可能把训练数据拟合得完美。噪声可能来自真正的随机性、标注错误,或存在未观测到的解释变量;极少数情况下噪声也可能缺失(例如网络要逼近的是一个确定、但计算代价很高的函数)。
- 偏差(bias):模型不够灵活,即使参数取到最优也无法精确拟合真值函数。例如只有三段的网络,无论怎么调都画不出那条类正弦曲线,这种系统性偏离就是偏差。
- 方差(variance):训练样本有限且带噪,我们无法区分真值函数的系统性变化与数据噪声。换一批训练数据,拟合出的函数就会略有不同。这种因“恰好抽到这批数据”带来的抖动就是方差(随机训练算法不一定每次收敛到同一解,也会贡献额外方差)。
8.2.2 测试误差的数学分解(直觉版)
设噪声方差为 \(\sigma^2\),真值函数的均值为 \(\mu[x]=\mathbb{E}_y\big[y[x]\big]\)。对单点 \(x\),最小二乘损失的期望可以做如下分解。先对噪声 \(y\) 取期望:
\[ \mathbb{E}_y\big[L[x]\big]=\big(f[x,\phi]-\mu[x]\big)^2+\sigma^2 . \]
也就是“模型与真值均值的偏差平方” + “噪声”。再考虑模型参数 \(\phi\) 依赖于随机抽到的训练集 \(\mathcal{D}\),记所有可能数据集下的平均模型为 \(f_\mu[x]=\mathbb{E}_{\mathcal{D}}\big[f[x,\phi[\mathcal{D}]]\big]\),把第一项继续拆开,最终得到三项相加:
\[ \underbrace{\mathbb{E}_{\mathcal{D}}\Big[\big(f[x,\phi[\mathcal{D}]]-f_\mu[x]\big)^2\Big]}_{\textbf{方差 variance}} +\underbrace{\big(f_\mu[x]-\mu[x]\big)^2}_{\textbf{偏差 bias}} +\underbrace{\sigma^2}_{\textbf{噪声 noise}} . \]
含义:
- 方差——因这一批训练数据不同,拟合模型相对“平均模型”的抖动;
- 偏差——“平均模型”相对真值均值的系统性偏离;
- 噪声——输入到输出映射本身的固有不确定性。
这三项在任何任务中都存在;在“回归 + 最小二乘”下恰好可加,但在分类等其他问题里它们的相互作用会更复杂。
8.3 降低误差
噪声项是不可逾越的下限,无能为力。能动的是另外两项。
8.3.1 降方差 —— 加数据
方差源于“训练数据有限且带噪”。增加训练数据能把噪声平均掉、把输入空间采样得更密,从而降低方差。书中实验:用 6、10、100 个样本分别拟合——
- 只有 6 个点时,三次拟合出的函数差异很大(方差大);
- 增到 100 个点时,三次结果几乎一样(方差小)。
经验法则:加训练数据几乎总能改善测试表现。
8.3.2 降偏差 —— 加容量
偏差源于“模型描述不了真值函数”,办法是让模型更灵活,即增加模型容量(对神经网络就是更多隐藏单元/隐藏层)。在玩具模型里,加容量 = 把 \([0,1]\) 切成更多线性区间。把区间增到 10 个,模型就足够灵活、能贴合真值函数,偏差显著下降。
8.3.3 偏差-方差权衡(bias-variance trade-off)
但加容量有个意外副作用:对固定大小的训练集,容量增大通常会让方差上升。于是加容量不一定降低测试误差。
书中对比很直观:
- 用三区间模型拟合三份各 15 个点的数据,三次结果很接近(方差低)——噪声在每个线性区间里大致被平均掉了。
- 用十区间模型拟合同样三份数据,虽然每次都把训练数据拟合得更好(训练误差更低),但多出来的描述力大量用去拟合噪声,三条曲线彼此差异很大(方差高),且并不更接近真值——这就是过拟合(overfitting)。
由此:随容量增加,偏差下降、方差上升,存在一个最优容量让“偏差 + 方差”之和最小。在书中的玩具模型上,这个最优值是容量为 4(4 个隐藏单元 / 4 个线性区间)。
一句话区分:欠拟合 = 偏差大(模型太简单,连训练数据都拟合不好);过拟合 = 方差大(模型太灵活,把噪声也学了进去)。
8.4 双下降(double descent)
偏差-方差权衡预测:容量过大测试误差会一直上升。但回到 MNIST-1D 做真实实验(1 万训练样本、5 千测试样本、随容量增加观察性能),却出现了经典理论之外的现象。
实验一(原始标签):随隐藏单元增多,训练误差很快趋零;图中有一条竖直虚线标出“参数数 = 训练样本数”的位置(模型在到这条线之前就已经把数据背下来了)。测试误差并没有按偏差-方差权衡那样回升,而是一直在降。
实验二(把 15% 的标签随机打乱):这次噪声更大,模型几乎需要和数据点一样多的参数才能背下数据。测试误差先表现出经典的偏差-方差权衡(先降、在“恰好记住训练数据”附近升高),然后做了件出人意料的事——又开始下降,加足够容量后甚至降到比第一段最低点还低。
这种“降—升—再降”的形状就叫双下降。对某些数据集(如原始 MNIST)原本就有;对另一些(如 MNIST-1D、CIFAR-100)则在给标签加噪后才显现或更明显。曲线被分成三段:
- 第一段:经典 / 欠参数化(under-parameterized)区;
- 中间误差冲高处:临界(critical)区,对应“参数数 ≈ 数据量”的插值阈值(模型刚好能精确记住训练数据);
- 第二段:现代 / 过参数化(over-parameterized)区。
双下降曲线长什么样(文字图):横轴是模型容量(参数数量),纵轴是误差。训练误差单调下滑,到插值阈值附近触零后贴着零走。测试误差先随容量下降(经典下坡)→ 在插值阈值(竖虚线,参数≈数据量)处陡然顶起一个尖峰→ 越过阈值后第二次下坡,最终落到比第一段更低的位置。形状像一条先降、中间鼓起一座尖山、然后再降的曲线。
8.4.1 为什么会有第二段下降
双下降来自两个现象的叠加:
- 临界区变差——模型刚好够把数据记住时测试性能暂时恶化,这正是偏差-方差权衡预测的;
- 过参数化区继续变好——参数多到训练点都约束不住时,测试性能竟还在提升,这才令人困惑。
理解第二段的关键:一旦容量足以把训练损失压到接近零,模型已几乎完美拟合所有训练点,再加容量改变的只能是数据点之间的行为。模型在数据点之间偏好哪种解,叫它的归纳偏置(inductive bias)。
为什么“数据点之间”这么重要?因为高维空间里训练数据极其稀疏——这就是维度灾难(curse of dimensionality)。MNIST-1D 是 40 维、1 万样本,看似很多;但若把每维只粗分成 10 个格子,总共就有 \(10^{40}\) 个格子,却只有 \(10^4\) 个样本,平均每 \(10^{36}\) 个格子才落一个点。
所以真实的高维问题更像:输入空间里只有几小块有数据,点与点之间有巨大空隙。双下降的解释是:随容量增加,模型能在最近的数据点之间越来越平滑地插值——
- 当参数数刚好等于数据量(插值阈值)时,模型被迫“扭曲自己”去精确穿过每个训练点,导致预测剧烈震荡(这解释了尖峰为何如此陡);
- 容量更大时,模型有能力构造更平滑、从而更可能泛化的函数。
在缺乏“数据点之间发生了什么”的信息时,假设平滑是合理的,通常也能较好泛化到新数据。
不过这只说明过参数化模型有能力变平滑,并没解释它为什么真的会选平滑解——同样能让训练损失为零的解里,既有平滑的也有震荡的。书中给出两种可能:① 网络初始化就偏向平滑,训练中没离开平滑函数的子区域;② 训练算法本身倾向于收敛到平滑函数。任何把解“推向某个等价子集”的因素都叫正则化器(regularizer),因此一种说法是:训练算法起到了隐式正则化(implicit regularization)的作用(见第 9 章)。
8.5 选择超参数
前面看到测试性能随容量变化,但实践中我们既拿不到偏差(需要知道真值函数)也拿不到方差(需要多份独立采样的数据集);在现代区里也没法事先知道还该加多少容量。那到底怎么在实践中定容量?
模型容量取决于隐藏层数、每层隐藏单元数等架构因素;学习算法及其参数(学习率、批大小等)也影响测试性能。这些统称超参数(hyperparameters)。寻找最佳超参数的过程叫超参数搜索(hyperparameter search),专门针对网络结构的则叫神经架构搜索(neural architecture search)。
做法 —— 引入第三个数据集“验证集”:
- 不能用测试集来挑超参数——否则挑到的可能只是“恰好在这个测试集上好”,无法泛化。
- 正确流程:对每组超参数,用训练集训练、在验证集上评估;选验证集上最好的模型,最后只在测试集上量一次它的性能。这样得到的才是对真实性能的合理估计。
三件套各司其职:训练集学参数 → 验证集选超参数 → 测试集报成绩。
为什么超参数搜索这么难:超参数空间虽比参数空间小,却仍大到无法穷举;很多超参数是离散的(如层数),还可能相互条件依赖(只有当层数 ≥ 10 时才需要指定“第 10 层的隐藏单元数”)。因此不能像学参数那样用梯度下降。专门的超参数优化算法会根据已有结果智能地采样超参数空间。这个过程很昂贵——每试一组都要完整训练一个模型并测一次验证性能。
本章小结
- 衡量性能要用单独的测试集;性能在测试集上保持的程度叫泛化。
- 测试误差可分解为三项:噪声、偏差、方差——在“回归 + 最小二乘”下严格相加。
- 加训练数据降低方差;当容量小于训练样本数时,加容量降偏差但升方差——这就是偏差-方差权衡,存在一个最优容量。
- 与权衡相抗衡的是另一个倾向:即使参数数超过训练样本,性能仍可能随容量提升。两者叠加形成双下降曲线。一般认为,过参数化的“现代区”里模型在数据点间插值得更平滑,但具体由什么驱动尚不清楚。
- 选容量及其他模型/训练超参数时,训练多个模型,用单独的验证集比性能、选最优。
关键术语对照
| 中文 | English | 一句话含义 |
|---|---|---|
| 泛化 | Generalization | 在没见过的测试数据上保持性能的能力 |
| 训练集 / 验证集 / 测试集 | Training / Validation / Test set | 学参数 / 选超参数 / 估真实性能 |
| 噪声 | Noise | 任务本身的固有不确定性,不可消除的误差下限 |
| 偏差 | Bias | 模型不够灵活,即使最优参数也偏离真值 |
| 方差 | Variance | 训练数据有限带来的拟合抖动 |
| 容量 | Capacity | 模型可表示函数的复杂度(约等于参数/隐藏单元数) |
| 过拟合 / 欠拟合 | Overfitting / Underfitting | 学了噪声(方差大)/ 太简单(偏差大) |
| 偏差-方差权衡 | Bias-variance trade-off | 加容量降偏差却升方差,存在最优容量 |
| 双下降 | Double descent | 越过插值阈值后测试误差先升再降 |
| 插值阈值 | Interpolation threshold | 参数数 ≈ 训练样本数、刚好精确记住数据的临界点 |
| 维度灾难 | Curse of dimensionality | 高维下数据极稀疏,空间体积压倒样本数 |
| 归纳偏置 | Inductive bias | 模型在数据点之间偏好某类解的倾向 |
| 隐式正则化 | Implicit regularization | 初始化/训练算法暗中偏向平滑解 |
| 超参数 | Hyperparameter | 不靠梯度学、需搜索的设定(层数、学习率等) |
| 超参数搜索 | Hyperparameter search | 用验证集挑出最佳超参数组合 |
返回目录 | 上一章:第 7 章 梯度与初始化 | 下一章:第 9 章 正则化