Reference
https://developers.google.com/machine-learning/crash-course/generalization/peril-of-overfitting
https://developers.google.com/machine-learning/crash-course/training-and-test-sets/splitting-data
https://developers.google.com/machine-learning/crash-course/validation/another-partition
Training and Test Sets
机器学习模型旨在根据以前未见过的新数据做出良好预测。但是,如果你要根据数据集构建模型,如何获得以前未见过的数据呢?一种方法是将你的数据集分成两个子集:
- 训练集 - 用于训练模型的子集。
- 测试集 - 用于测试模型的子集。
一般来说,在测试集上表现是否良好是衡量能否在新数据上表现良好的有用指标,前提是:
- 测试集足够大。
- 你不会反复使用相同的测试集来作假。
你可以想象按如下方式拆分单个数据集:
将单个数据集拆分为一个训练集和一个测试集
确保你的测试集满足以下两个条件:
- 规模足够大,可产生具有统计意义的结果。
- 能代表整个数据集。换言之,挑选的测试集的特征应该与训练集的特征相同。
假设你的测试集满足上述两个条件,你的目标是创建一个能够很好地泛化到新数据的模型。我们的测试集充当新数据的代理。以下图为例。请注意,从训练数据中学习的模型非常简单。该模型的表现并不完美,出现了一些错误的预测。不过,该模型在测试数据上的表现与在训练数据上的表现一致。也就是说,这个简单的模型没有过拟合训练数据。
对照测试数据验证训练后的模型
请勿对测试数据进行训练。 如果你的评估指标取得了意外的好结果,则可能表明你不小心对测试集进行了训练。例如,高准确率可能表明测试数据泄露到了训练集。
例如,假设一个模型要预测某封电子邮件是否是垃圾邮件,它使用主题行、邮件正文和发件人的电子邮件地址作为特征。我们按照 80-20 的拆分比例将数据拆分为训练集和测试集。在训练之后,该模型在训练集和测试集上均达到了 99% 的精确率。我们原本预计测试集上的精确率会低于此结果,因此再次查看数据后发现,测试集中的很多样本与训练集中的样本是重复的(由于疏忽,我们在拆分数据之前,没有将输入数据库中的相同垃圾邮件重复条目清理掉)。我们无意中对一些测试数据进行了训练,因此无法再准确衡量该模型泛化到新数据的效果。
Validation Set
将数据集划分为训练集和测试集。借助这种划分,你可以对一个样本集进行训练,然后使用不同的样本集测试模型。采用两种分类之后,工作流程可能如下所示:
可能的工作流程
在图中,“调整模型”指的是调整你可以想到的关于模型的任何方面,从更改学习速率、添加或移除特征,到从头开始设计全新模型。该工作流程结束时,你可以选择在测试集上获得最佳效果的模型。
将数据集划分为两个子集是个不错的想法,但不是万能良方。通过将数据集划分为三个子集(如下图所示),你可以大幅降低过拟合的发生几率:
将单个数据集划分为三个子集
使用验证集评估训练集的效果。然后,在模型“通过”验证集之后,使用测试集再次检查评估结果。下图展示了这一新工作流程:
更好的工作流程
在这一经过改进的工作流程中:
- 选择在验证集上获得最佳效果的模型。
- 使用测试集再次检查该模型。
该工作流程之所以更好,原因在于它暴露给测试集的信息更少。
Note:
- 不断使用测试集和验证集会使其逐渐失去效果。也就是说,你使用相同数据来决定超参数设置或其他模型改进的次数越多,你对于这些结果能够真正泛化到未见过的新数据的信心就越低。请注意,验证集的失效速度通常比测试集缓慢。
- 如果可能的话,建议你收集更多数据来“刷新”测试集和验证集。重新开始是一种很好的重置方式。