1.6 测试和验证
了解模型对新实例的泛化能力的唯一方法是在新实例上进行实际尝试。一种方法是将模型部署到生产环境并监控其性能。这种方法很有效,但如果模型非常糟糕,你的用户就会抱怨,所以这显然不是最好的方法。
更好的选择是将数据分成两组:训练集和测试集。顾名思义,你可以使用训练集训练模型,并使用测试集对其进行测试。新实例的错误率称为泛化误差(或样本外误差),通过在测试集上评估模型,你可以获得误差的估计值。这个值能告诉你模型在处理以前从未见过的实例时的表现。
如果训练误差很低(即模型在训练集上犯的错误很少)但是泛化误差很高,这意味着你的模型过拟合了训练数据。
通常使用80%的数据进行训练,保留20%的数据进行测试。然而,这取决于数据集的大小:如果它包含1000万个实例,那么保留1%意味着你的测试集将包含10万个实例,这可能足以很好地估计泛化误差。
1.6.1 超参数调整和模型选择
评估模型非常简单:只需使用一个测试集。现在假设你在两种类型的模型(比如线性模型和多项式模型)之间犹豫不决,你如何做出判断呢?一种选择是同时训练这两个模型,并使用测试集比较它们的泛化能力。
现在假设线性模型泛化得更好,但你想应用一些正则化来避免过拟合。问题是,你如何选择正则化超参数的值?一种选择是对于这个超参数,使用100个不同的值来训练100个不同的模型。假设你找到了最佳超参数值,它生成的模型泛化误差最小,比如只有5%的误差。你将此模型部署到生产环境,但遗憾的是它的性能并不如预期,产生了15%的误差。到底发生了什么?
问题是你多次测量了测试集上的泛化误差,并且调整了模型和超参数来生成拟合那个测试集的最佳模型。这意味着该模型不太可能在新数据上表现良好。
这个问题的一个常见解决方案称为保持验证(见图1-25):你只需保持训练集的一部分,以评估几个候选模型并选择最佳模型。新的保留集称为验证集(或开发集)。更具体地说,你可以在简化的训练集(即完整训练集减去验证集)上训练具有各种超参数的多个模型,然后选择在验证集上表现最佳的模型。在此保持验证过程之后,你在完整训练集(包括验证集)上训练最佳模型,这就是你的最终模型。最后,你在测试集上评估这个最终模型以获得泛化误差的估计。
图1-25:使用保持验证的模型选择
这个解决方案通常效果很好。但是,如果验证集太小,则模型评估就不精确,你最终可能会错误地选择一个次优模型。相反,如果验证集太大,那么剩余的训练集会比完整的训练集小得多。为什么这样不好?好吧,由于最终模型是在完整的训练集上进行训练,因此在小得多的训练集上训练的候选模型并不理想。这就像选择最快的短跑运动员去参加马拉松比赛。解决这个问题的一种方法是使用许多小的验证集执行重复的交叉验证。每个模型在对其余数据进行训练后,每个验证集都会评估一次。通过对模型的所有评估求平均,可以更准确地衡量其性能。然而,有一个缺点:训练时间是验证集数量的倍数。
1.6.2 数据不匹配
在某些情况下,很容易获得大量数据用于训练,但这些数据可能无法完全代表将在生产环境中使用的数据。例如,假设你想创建一个移动应用程序来拍摄花朵照片并自动确定它们的种类。你可以轻松地在网络上下载数百万张花卉图片,但它们并不能完全代表在移动设备上使用该应用程序实际拍摄的照片。也许你只有1000张有代表性的照片(即实际使用该应用程序拍摄的)。
在这种情况下,要记住的最重要的规则是验证集和测试集都必须尽可能地代表你希望在生产环境中使用的数据,因此它们应该完全由有代表性的图片组成:你可以将它们打乱并将一半放在验证集中,一半放在测试集中(确保两个集中都没有重复或接近重复)。在网络图片上训练了模型后,如果你观察到模型在验证集上的表现令人失望,那么你将不知道这是因为模型对训练集过拟合了,还是仅仅因为网络图片和移动应用程序图片之间的不匹配。
一种解决方案是将一些训练图片(来自网络)放在被吴恩达(Andrew Ng)称为train-dev(训练开发)集(见图1-26)的另一个集合中。模型训练完成后(在训练集上,而不是在train-dev集上),你可以在train-dev集上对其进行评估。如果模型表现不佳,那么它一定是对训练集过拟合了,所以应该尽量简化或正则化该模型、获取更多的训练数据,以及清洗训练数据。但是如果模型在train-dev集上表现良好,那么你可以在开发集上评估模型。如果模型表现不佳,那么问题一定来自数据不匹配。你可以尝试通过预处理网络图片来解决这个问题,使它们看起来更像移动应用程序拍摄的照片,然后重新训练模型。一旦你拥有在train-dev集和开发集上都表现良好的模型,就可以在测试集上最后一次评估它,以了解它在生产环境中的表现。
图1-26:当真实数据稀缺时(右),你可以使用类似丰富的数据(左)进行训练,并在train-dev集中保留一些数据以评估过拟合。然后使用真实数据评估数据不匹配(开发集)和最终模型的性能(测试集)
没有免费的午餐定理
模型是数据的简化表示。简化旨在丢弃不太可能泛化到新实例的多余细节。当你选择特定类型的模型时,你是在隐含地对数据做出假设。例如,如果你选择线性模型,则隐含地假设数据基本上是线性的,并且实例与直线之间的距离只是噪声,可以安全地忽略它。
在1996年的一篇著名论文(https://homl.info/8)[9]中,David Wolpert证明,如果你完全不对数据做出任何假设,那么就没有理由偏爱某个模型。这被称为没有免费的午餐(No Free Lunch,NFL)定理。对于一些数据集,最好的模型是线性模型,而对于其他数据集,最好的模型是神经网络模型。不存在一个先验模型可以保证一定能更好地工作(这是定理名称的由来)。确定哪种模型最好的唯一方法是对所有模型进行评估。由于这是不可能的,因此在实践中你对数据做出了一些合理的假设并仅评估了几个合理的模型。例如,对于简单的任务,你可能只会评估几个具有不同正则化水平的线性模型,而对于复杂的问题,你可能会评估多个神经网络模型。