过拟合与学习曲线:在没有数据泄漏的前提下诊断差距
结合训练与验证分数,把预处理放进 pipeline,并让最终测试集独立于参数选择。
本文内容
简明答案
模型在训练数据上的表现远好于未见过的验证数据时,可能存在过拟合。但差距只是诊断线索,不是完整解释:不合适的划分、分布变化、数据泄漏和小样本都值得调查。先选择能够代表未来使用的划分,把需要学习的预处理放入 pipeline,并与适合任务的简单基线比较。学习曲线再展示训练集增大时两类分数如何变化。用开发数据选择复杂度,保留独立测试集进行最终评价,不要反复根据测试结果调整参数。
把过拟合与其他问题区分
对于准确率这类越大越好的指标,训练表现较强而验证表现明显较弱,提示可能有泛化问题。如果两边都弱,也可能是模型或特征不足。不要仅凭一个数字或一次幸运划分就断定过拟合。检查样本规模、标签以及验证例子能否代表部署环境。新群体带来的分布差异,与在原本可比较的数据中记住局部细节,是两种不同问题,需要不同调查。先理解数据,再解释分数。
选择符合未来使用的划分
明确未来预测意味着新独立样本、新客户,还是更晚时间的观察。普通随机划分并不适合所有场景。同一对象的重复测量可能需要按组分离,而预测未来可能需要考虑时间顺序。分层能够保持类别比例,却不能消除组间依赖或时间泄漏。教学代码对合成分类数据使用分层验证折。把这个选择应用到真实数据之前,先确认假设符合目标使用场景,不能因为代码提供了随机种子就认为划分已经正确。
在 pipeline 内拟合预处理
在拟合任何从数据学习参数的转换之前,先划分数据。若在整个数据集上拟合缩放、缺失值填补或特征选择,就可能把验证信息泄漏到训练过程。Pipeline 让交叉验证在每个训练部分拟合 scaler,再将它应用于该折的验证部分。但 pipeline 不会修复本身泄漏答案的特征,也不能让预测时不可获得的字段变得合理。检查特征含义与可用时间,应与检查估计器参数同样认真。
同时阅读两条学习曲线
学习曲线在多个训练集规模上计算训练和验证分数。要同时阅读两条线,不能只看最好的一个点。持续较大差距可能提示高方差;两条接近且都较弱的线,可能提示模型能力或特征不足。更多训练数据有时会有帮助,但曲线不保证具体提升。在示例中,分数数组的每一行对应一个训练规模,每一列对应一个验证折。按行取平均,是对这些折的结果进行概括,而不是证明未来真实效果。
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, learning_curve
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
# Illustrative synthetic classification data.
X, y = make_classification(
n_samples=500, n_features=20,
n_informative=5, n_redundant=5, random_state=42
)
model = make_pipeline(
StandardScaler(), LogisticRegression(max_iter=1000)
)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
sizes, training_scores, validation_scores = learning_curve(
model, X, y, cv=cv,
train_sizes=np.linspace(0.2, 1.0, 5), scoring="accuracy"
)
print(sizes)
print(training_scores.mean(axis=1))
print(validation_scores.mean(axis=1))比较基线并选择合适指标
解释看似优秀的分数之前,先与适合任务的简单基线比较。类别不平衡时,高准确率可能来自始终偏向常见类别,而不是有效识别稀有类别。根据模型支持的决策选择指标,并明确哪个方向表示改善。示例使用 accuracy,只是展示合成数据上的学习曲线 API。它的输出并不能证明准确率适合所有真实分类问题。不同错误带来的业务影响,应独立于绘图便利性和指标名称进行讨论。
有计划地调整复杂度与正则化
预先规划少量复杂度或正则化调整,用相同开发协议评价。对于 LogisticRegression,更小的 C 表示更强的正则化;max_iter 控制优化迭代上限,不控制正则化强度。还要检查特征缩放和收敛。每次改变一个有意义的因素,比较验证表现,而不是只追求训练分数最高。较简单的模型可能泛化更好,但应根据有代表性的验证数据判断,不能因为它让曲线看起来更符合期待就直接接受。
检查各验证折的波动
除了平均值,还应查看各折分数。较大波动可能说明结果对所选样本敏感,或不同验证部分难度不同。这些分数的标准差描述折之间的变化,不会自动成为置信区间。交叉验证的训练部分相互重叠,因此分数不是独立实验的重复。把波动当作重新检查协议、样本与分组的理由,而不是未经额外假设就声称得到未来总体误差的精确边界。清楚说明不确定性的来源比报告过度精确的数字更有用。
让最终评价独立于模型选择
在最终留出评价之前,固定选定特征和参数。若选择设置时反复查看测试集,它就变成选择过程的一部分,独立性随之减弱。记录数据版本、特征定义、划分规则、随机状态、指标和软件版本。代码生成合成数据并打印计算摘要;本文不宣称某个具体分数或基准测试结果。可复现流程有助于理解后续变化,并把真实建模改进与评价方式发生变化这两种情况区分开。
检查清单
- 让验证划分对应未来样本、组或时间范围。
- 只在训练部分拟合预处理,优先放入 pipeline。
- 结合基线和折间波动,同时阅读训练与验证曲线。
- 使用开发数据选择参数,让最终测试保持独立。
适用范围
学习曲线依赖样本质量、划分方式、模型和指标。它们提示可能原因,但不能证明增加数据或加强正则化一定能解决任务。合成示例用于教学,没有作为基准测试执行。