本课问题在 1.4.2 课中,我们把训练描述为最小化损失函数。但训练误差很小,是否就证明模型真正学会了解决任务?不一定。模型过于简单时可能无法捕捉规律;模型过于灵活时则可能记住某个样本中的细节。本课将介绍如何诊断这两类问题。
已掌握的知识你已经了解模型参数、损失函数,以及将数据划分为训练集、验证集和测试集的原因。本课将利用这些知识,不仅评价拟合程度,也评价模型处理新样本的能力。

学习目标

1. 不只看一种误差

训练集反映模型对用于估计参数的样本拟合得如何。验证集帮助判断学到的规律能否迁移到没有参与参数更新的数据。比较时应使用相同的指标或损失,并确保测量条件具有可比性。

训练误差低并不足够。我们需要同时观察训练集和验证集的表现。测试集应留给最终的独立评估,不应反复用于选择模型。

训练集损失J_train(θ) = (1 / n_train) Σ ℓ(yᵢ, f(xᵢ; θ))
训练样本模型过于简单, 拟合适当, 过度贴合噪声训练样本模型过于简单拟合适当过度贴合噪声
模型过于简单 · 拟合适当 · 过度贴合噪声

2. 欠拟合:模型没有捕捉到规律

欠拟合(underfitting)是指模型对于任务过于简单、特征不足、约束过强,或优化尚未找到合适参数。此时模型在训练样本上已经存在较大误差,验证集表现通常也不会明显更好。

典型信号是训练损失和验证损失都较高。可以检查特征和任务定义,选择表达能力更强的模型,减弱过度正则化,或确认优化是否收敛。单纯延长训练并不总能解决问题,应先找出真正的限制。

验证集损失J_val(θ) = (1 / n_val) Σ ℓ(yⱼ, f(xⱼ; θ))

3. 适当拟合:规律能够迁移

具有良好泛化能力时,训练误差较低,验证误差与其接近且没有明显恶化。两者存在小幅差异是正常的,因为样本不同且存在抽样波动。关键在于结果是否稳定,以及指标是否满足任务要求。

验证损失不一定低于训练损失。正则化、dropout 等方法可能有意增加训练难度,因此训练损失有时更高。应结合具体算法和指标理解数值。

4. 过拟合:模型过度贴合样本

过拟合(overfitting)是指模型过于精确地拟合训练样本,包括噪声和样本特有的细节。训练误差持续下降,但验证误差停止改善或开始上升。模型能很好描述熟悉的样本,却难以稳定迁移到新数据。

原因可能同时存在:模型容量过大、数据缺少多样性、标签噪声、信息泄漏、调参次数过多,或反复依赖同一个验证集。较大的训练与验证损失差距是有用信号,但并非单独的证明;还应检查数据划分、分布和测量方式。

训练损失 / 验证损失最佳轮次训练轮次训练损失验证损失最佳轮次
训练损失 and 验证损失 can move in different directions as training continues.

5. 学习曲线与提前停止

训练过程中,训练损失通常持续下降。验证损失可能先下降,随后停止改善并开始上升,这是过拟合的一种典型表现。提前停止(early stopping)会选择验证指标最佳的时刻,并恢复该时刻对应的模型参数。

不要使用测试集选择训练轮次。提前停止应使用验证集或内部验证机制。实际中可以设置 patience,即在停止前允许若干轮没有改善,以免对单次波动过度反应。应观察趋势,而不是单个噪声点。

泛化差距Δ = J_val − J_train

6. 模型容量:权衡而不是竞赛

提高模型容量通常会改善对训练数据的拟合,因此训练误差往往下降。但验证误差可能先下降、随后上升,因为模型开始描述样本特有的噪声。这体现了偏差—方差权衡,但并不是适用于每个模型和数据集的普遍定律。

高偏差意味着模型家族无法充分表达相关关系;高方差意味着训练样本变化时,拟合结果也会显著变化。这些概念有助于诊断,但实际决策仍需实验、正确的数据划分和数据分析。

模型容量误差模型容量训练验证
训练 error may keep falling while 验证 error rises after the useful complexity range.

7. 先诊断,再选择方法

如果训练损失和验证损失都高,应检查模型表达能力、特征、正则化和优化收敛。如果训练损失低而验证损失明显更高或持续上升,应检查信息泄漏、噪声和分布差异,再考虑简化模型、正则化、增加多样化数据、数据增强或提前停止。

不要同时应用所有方法。一次改变一个因素,固定验证流程并比较结果。更多数据只有在相关且能代表未来条件时才有帮助。正则化过强也可能让模型重新陷入欠拟合。

正则化训练目标J_total(θ) = J_train(θ) + λ Ω(θ)
检查数据划分检查数据划分 → 比较训练与验证 → 寻找原因 → 一次改变一个因素检查数据划分比较训练与验证寻找原因一次改变一个因素
检查数据划分 → 比较训练与验证 → 寻找原因 → 一次改变一个因素

8. 一个多项式模型小实验

在同一个合成任务上比较不同复杂度的模型。线性模型可能过于简单,无法表达波动关系;中等阶数的多项式可能拟合得更好;高阶多项式则可能对噪声和个别点过度敏感。具体数值取决于随机划分,因此应比较训练和验证结果,而不是宣称某个阶数永远最好。

本例使用验证集选择复杂度。选择方案后,应在没有参与调参的独立测试集上进行最终评估。在实际工作中,如果数据量允许,也可以使用多次划分或交叉验证。

示例:比较不同复杂度的多项式模型

Python · NumPy · scikit-learn
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

rng = np.random.default_rng(7)
X = np.sort(rng.uniform(0, 1, 36)).reshape(-1, 1)
y = np.sin(2 * np.pi * X[:, 0]) + rng.normal(0, 0.18, len(X))

X_train, X_val, y_train, y_val = train_test_split(
    X, y, test_size=0.25, random_state=7
)

for degree in (1, 4, 12):
    model = make_pipeline(
        PolynomialFeatures(degree=degree, include_bias=False),
        LinearRegression()
    )
    model.fit(X_train, y_train)
    train_mse = mean_squared_error(y_train, model.predict(X_train))
    val_mse = mean_squared_error(y_val, model.predict(X_val))
    print(degree, round(train_mse, 3), round(val_mse, 3))

输出列依次为多项式阶数、训练 MSE 和验证 MSE。阶数增加时,训练误差可能下降,但验证误差不一定同步下降。可以更换 random_state 再运行,观察结果是否稳定。不要把验证集当作最终测试集。

实践任务

比较两个实验:第一个 train loss = 0.42、validation loss = 0.45;第二个 train loss = 0.08、validation loss = 0.91。在指标相同且数据集可比时,第二种情况值得检查是否过拟合。但在修改模型结构之前,应先确认划分正确、没有信息泄漏,并且验证集能代表预期使用条件。

参考资料与延伸阅读

课程术语表

01欠拟合Underfitting

模型即使在训练数据上也无法捕捉重要规律。

02过拟合Overfitting

模型过度贴合训练样本中的细节和噪声,损害对新数据的表现。

03泛化Generalization

模型在目标应用领域的新样本上保持有效表现的能力。

04训练损失Training loss

在用于估计模型参数的数据上计算的损失。

05验证损失Validation loss

在独立数据集上计算、用于模型选择和调参的损失。

06泛化差距Generalization gap

在可比测量条件下,验证误差与训练误差之间的差值。

07模型容量Model capacity

模型家族表达不同关系的能力。

08偏差Bias

由模型假设或限制导致的系统性误差。

09方差Variance

模型拟合结果对训练样本变化的敏感程度。

10提前停止Early stopping

根据验证表现停止训练,并恢复最佳检查点。

自我检测

问题 1

如果训练损失和验证损失都很高,首先应检查什么?

问题 2

哪种现象通常提示过拟合?

问题 3

验证集的主要用途是什么?

问题 4

为什么不应反复使用测试集调参?

问题 5

哪些方法可能缓解过拟合?

问题 6

较大的泛化差距意味着什么?

问题 7

哪种做法可能帮助解决欠拟合?

问题 8

训练损失很低,是否能证明模型在新数据上表现良好?