如何评估 PyTorch 模型的性能

设计深度学习模型有时就像一门艺术。有很多决策点,而且很难说哪种是最好的。一种方法是通过反复试验,并在实际数据上评估结果。因此,拥有一个科学的方法来评估神经网络和深度学习模型的性能非常重要。事实上,这也是比较任何机器学习模型在特定应用上性能的相同方法。

在本帖中,您将发现稳健评估模型性能的常用工作流程。在示例中,我们将使用 PyTorch 来构建模型,但该方法也适用于其他模型。完成本帖后,您将了解:

  • 如何使用验证数据集评估 PyTorch 模型
  • 如何使用 k 折交叉验证评估 PyTorch 模型

通过我的《用PyTorch进行深度学习》一书来启动你的项目。它提供了包含可用代码自学教程


让我们开始吧。

如何评估 PyTorch 模型的性能
图片来自 Kin Shing Lai。部分权利保留。

概述

本章分为四个部分,它们是:

  • 模型的经验评估
  • 数据分割
  • 使用验证训练 PyTorch 模型
  • k 折交叉验证

模型的经验评估

从头开始设计和配置深度学习模型时,需要做出很多决定。这包括设计决策,例如深度学习模型中使用多少层、每层的大小以及使用何种层或激活函数。还可能包括损失函数、优化算法、训练的 epoch 数以及模型输出的解释。幸运的是,有时您可以复制其他人的网络结构。有时,您可以通过一些启发式方法自己做出选择。要判断您的选择是否好,最好的方法是通过实际数据对多个替代方案进行经验评估并进行比较。

深度学习通常用于具有非常大的数据集的问题。即成千上万甚至数十万的数据样本。这提供了充足的测试数据。但是,您需要有一个强大的测试策略来估计模型在未见过的数据上的性能。基于此,您可以有一个指标来比较不同的模型配置。

想开始使用PyTorch进行深度学习吗?

立即参加我的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

数据分割

如果您有成千上万甚至更多样本的数据集,您不必总是将所有数据都用于模型训练。这会不必要地增加复杂性并延长训练时间。越多不一定越好。您可能无法获得最佳结果。

当您拥有大量数据时,您应该从中抽取一部分作为 训练集,输入模型进行训练。另一部分保留为 测试集,从训练中排除,但使用训练或部分训练的模型进行验证评估。此步骤通常称为“训练-测试拆分”。

让我们考虑 Pima 印第安人糖尿病数据集。您可以使用 NumPy 加载数据。

有 768 个数据样本。数量不多,但足以演示拆分。让我们将前 66% 作为训练集,剩余的作为测试集。最简单的方法是切片数组。

选择 66% 是任意的,但您不希望训练集太小。有时您可能使用 70%-30% 的拆分。但如果数据集非常大,您甚至可以使用 30%-70% 的拆分,只要 30% 的训练数据足够大。

如果您以这种方式拆分数据,您就假设数据集已打乱,因此训练集和测试集同样多样化。如果您发现原始数据集已排序,并且只在最后取测试集,您可能会发现您的所有测试数据都属于同一类别,或者在一个输入特征中具有相同的值。这并不理想。

当然,您可以在拆分前调用 np.random.shuffle(data) 来避免这种情况。但许多机器学习工程师通常使用 scikit-learn 来完成此操作。请看这个示例:

但更常见的是,在您分离输入特征和输出标签之后进行。请注意,此 scikit-learn 函数不仅可以处理 NumPy 数组,还可以处理 PyTorch 张量。

使用验证训练 PyTorch 模型

让我们回顾一下构建和训练该数据集上的深度学习模型的代码。

在此代码中,每个迭代都会从训练集中提取一个批次,并在前向传播中输入模型。然后,您在后向传播中计算梯度并更新权重。

虽然在本例中,您在训练循环中使用了二元交叉熵作为损失度量,但您可能更关心预测的准确性。计算准确性很容易。您将输出(在 0 到 1 之间)四舍五入到最近的整数,这样您就可以得到 0 或 1 的二元值。然后,您计算预测与标签匹配的百分比;这就是准确性。

但是您的预测是什么?它是当前模型对 X_batch 的预测 y_pred。将准确性添加到训练循环中会变成这样:

但是,X_batchy_batch 被优化器使用,优化器会微调模型,使其能够从 X_batch 预测 y_batch。而您现在使用准确性来检查 y_pred 是否与 y_batch 匹配。这就像作弊,因为如果您的模型以某种方式记住了解决方案,它可以直接向您报告 y_pred 并获得完美准确性,而无需实际从 X_batch 推断 y_pred

确实,深度学习模型可能非常复杂,以至于您无法知道模型是简单地记住了答案还是正在推断答案。因此,最好的方法是 不要X_batchX_train 中的任何内容计算准确性,而是从其他内容:您的测试集计算。让我们在每个 epoch 之后 使用 X_test 添加一个准确性测量。

在这种情况下,内部 for 循环中的 acc 只是一个显示进度的指标。与显示损失度量相比,差异不大,只是它不参与梯度下降算法。您期望随着损失度量的提高,准确性也会提高。

在外部 for 循环中,每个 epoch 结束时,您会根据 X_test 计算准确性。工作流程类似:您将测试集输入模型并请求其预测,然后计算与测试集标签匹配的结果数量。但是,这个准确性是您应该关心的。它应该随着训练的进行而提高,但如果您没有看到它提高(即准确性增加)甚至下降,您就必须中断训练,因为它似乎开始过拟合。过拟合是指模型开始记住训练集而不是学习从中推断预测。其迹象是训练集的准确性不断提高,而测试集的准确性却在下降。

以下是实现上述所有内容的完整代码,从数据拆分到使用测试集进行验证:

上面的代码将打印以下内容:

k 折交叉验证

在上面的示例中,您从测试集中计算了准确性。随着训练的进行,它被用作模型的 分数。您希望在分数达到最大值时停止。事实上,仅通过比较此测试集的分数,您就可以知道您的模型在 epoch 21 之后效果最好,之后开始过拟合。对吗?

如果您构建了两个不同设计的模型,您是否应该仅仅在同一个测试集上比较这些模型的准确性,并声称一个比另一个更好?

实际上,您可以辩称,即使您在提取测试集之前对数据集进行了混洗,测试集也不够有代表性。您还可以争辩说,碰巧一个模型更适合这个特定的测试集,但不总是更好。为了更有力地证明哪个模型更好,并且独立于测试集的选择,您可以尝试 多个测试集 并计算平均准确性。

这就是 k 折交叉验证的作用。它是一个决定哪个 设计 效果更好的过程。它的工作方式是,从头开始重复训练过程 $k$ 次,每次使用不同的训练集和测试集组合。因此,您将有 $k$ 个模型和 $k$ 个各自测试集的准确性分数。您不仅对平均准确性感兴趣,还对标准差感兴趣。标准差说明准确性分数是否一致,或者某个测试集是否对某个模型特别好或不好。

由于 k 折交叉验证会从头开始多次训练模型,因此最好将训练循环包装在一个函数中。

上面的代码故意不打印任何内容(在 tqdm 中设置了 disable=True),以保持屏幕整洁。

同样,在 scikit-learn 中,有一个用于 k 折交叉验证的函数。您可以利用它来对模型的准确率进行稳健的估计。

运行此代码会打印出:

在 scikit-learn 中,有多种 k 折交叉验证函数,这里使用的是分层 k 折。它假定 y 是类别标签,并考虑了其值,以便在划分中提供平衡的类别表示。

上面的代码使用了 $k=5$ 或 5 个划分。这意味着将数据集分成五个相等的部分,选择其中一个作为测试集,其余部分组合成训练集。有五种方法可以做到这一点,因此上面的 for 循环将有五次迭代。在每次迭代中,您调用 model_train() 函数并返回准确率得分。然后将其保存在一个列表中,该列表将在最后用于计算均值和标准差。

kfold 对象将返回 索引。因此,您无需提前运行训练-测试拆分,而是在调用 model_train() 函数时,使用提供的索引即时提取训练集和测试集。

上面的结果显示该模型表现中等,平均准确率为 64%。并且由于标准差为 3%,因此该分数是稳定的。这意味着在大多数情况下,您期望模型的准确率为 61% 到 67%。您可以尝试更改上述模型,例如添加或删除一个层,并观察均值和标准差的变化。您还可以尝试增加训练中使用的 epoch 数并观察结果。

k 折交叉验证得到的均值和标准差是您应该用来为模型设计设定基准的指标。

总而言之,以下是 k 折交叉验证的完整代码。

总结

在这篇文章中,您了解了对深度学习模型在未见过的数据上进行性能估计的稳健方法的重要性,并学会了如何做到这一点。您看到了:

  • 如何使用 scikit-learn 将数据拆分为训练集和测试集
  • 如何借助 scikit-learn 进行 k 折交叉验证
  • 如何修改 PyTorch 模型中的训练循环以包含测试集验证和交叉验证

开始使用PyTorch进行深度学习!

Deep Learning with PyTorch

学习如何构建深度学习模型

...使用新发布的PyTorch 2.0库

在我的新电子书中探索如何实现
使用 PyTorch进行深度学习

它提供了包含数百个可用代码自学教程,让你从新手变成专家。它将使你掌握:
张量操作训练评估超参数优化等等...

通过动手练习开启你的深度学习之旅


查看内容

“如何评估 PyTorch 模型性能” 的 6 条回复

  1. Oladimeji 2023 年 2 月 10 日 下午 5:54 #

    非常感谢您的努力,非常赞赏!

    • James Carmichael 2023 年 2 月 11 日 上午 7:38 #

      Oladimeji,不客气!我们感谢您的支持和反馈!

  2. Jahangir Khan 2023 年 7 月 25 日 上午 12:40 #

    做得好!谢谢 James!

    • James Carmichael 2023 年 7 月 25 日 上午 8:31 #

      Jahangir,不客气!我们非常感谢您的支持和反馈!

  3. shadow 2024 年 2 月 2 日 下午 5:08 #

    谢谢 James!

    • James Carmichael 2024 年 2 月 3 日 上午 9:44 #

      不客气!我们感谢您的支持!

留下回复

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。