在 PyTorch 中构建二分类模型

PyTorch 库是用于深度学习的。深度学习模型的一些应用包括解决回归或分类问题。
在本文中,您将了解如何使用 PyTorch 为二元分类问题开发和评估神经网络模型。

完成这篇文章后,您将了解:

  • 如何加载训练数据并使其可供 PyTorch 使用
  • 如何设计和训练神经网络
  • 如何使用 k 折交叉验证评估神经网络模型的性能
  • 如何在推理模式下运行模型
  • 如何为二元分类模型创建接收器工作特性曲线 (ROC 曲线)

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


让我们开始吧。

在 PyTorch 中构建二分类模型
图片来自 David Tang。部分权利保留。

数据集描述

在本教程中,您将使用 Sonar 数据集

该数据集描述了从不同服务反弹的声纳啁啾回波。60 个输入变量是不同角度的回波强度。这是一个二元分类问题,需要模型来区分岩石和金属圆柱体。

您可以在 UCI 机器学习库上了解有关此数据集的更多信息。您可以免费 下载数据集,并将其以 sonar.csv 的文件名放在您的工作目录中。

这是一个广为人知的数据集。所有变量都是连续的,通常在 0 到 1 的范围内。输出变量是字符串“M”代表矿石(Mine)和“R”代表岩石(Rock),需要转换为整数 1 和 0。

使用此数据集的一个好处是它是一个标准基准问题。这意味着我们对优秀模型的预期技能有一些了解。使用交叉验证,神经网络 应该能够达到 84% 到 88% 的准确率

加载数据集

如果您已将数据集下载为 CSV 格式并将其保存为本地目录中的 sonar.csv,您可以使用 pandas 加载数据集。有 60 个输入变量 (X) 和一个输出变量 (y)。由于文件包含字符串和数字的混合数据,因此使用 pandas 比使用 NumPy 等其他工具更容易读取它们。

数据可以按如下方式读取:

这是一个二元分类数据集。您会更喜欢数值标签而不是字符串标签。您可以使用 scikit-learn 中的 LabelEncoder 进行此类转换。LabelEncoder 用于将每个标签映射到一个整数。在这种情况下,只有两个标签,它们将变为 0 和 1。

使用它,您需要先调用 fit() 函数使其学习可用的标签。然后调用 transform() 进行实际转换。以下是如何使用 LabelEncodery 从字符串转换为 0 和 1:

您可以使用以下命令查看标签:

这将输出:

如果您运行 print(y),您会看到以下内容:

您可以看到标签已转换为 0 和 1。从 encoder.classes_ 中,您知道 0 表示“M”,1 表示“R”。在二元分类的上下文中,它们也分别称为负类和正类。

之后,您应该将它们转换为 PyTorch 张量,因为这是 PyTorch 模型喜欢的工作格式。

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

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

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

创建模型

现在您已经准备好构建神经网络模型了。

正如您在之前的一些帖子中看到的,最简单的神经网络模型是 3 层模型,它只有一个隐藏层。深度学习模型通常指的是具有多个隐藏层的模型。所有神经网络模型都具有称为权重的参数。我们通常认为模型的参数越多,它就越强大。您应该使用每层参数更多的模型,还是层数更多但每层参数更少的模型?让我们一探究竟。

每层参数更多的模型称为宽模型。在此示例中,输入数据有 60 个特征来预测一个二元变量。您可以假设构建一个具有一个隐藏层、180 个神经元的宽模型(输入特征的三倍)。这样的模型可以使用 PyTorch 构建:

因为这是一个二元分类问题,输出必须是一个长度为 1 的向量。然后您希望输出在 0 和 1 之间,这样您可以将其视为概率或模型预测输入对应于“正类”的置信度。

层数更多的模型称为深模型。考虑到之前的模型有一个包含 180 个神经元的层,您可以尝试用每个包含 60 个神经元的三个层来代替。这样的模型可以使用 PyTorch 构建:

您可以确认这两个模型具有相似数量的参数,如下所示:

model1.parameters() 将返回模型的所有参数,每个参数都是一个 PyTorch 张量。然后,您可以使用 x.reshape(-1).shape[0] 将每个张量重新格式化为向量并计算其长度。因此,上面的代码总结了每个模型的总参数数量。

通过交叉验证比较模型

您应该使用宽模型还是深模型?一种方法是使用交叉验证来比较它们。

这是一种技术,它使用“训练集”数据来训练模型,然后使用“测试集”数据来查看模型预测的准确性。测试集的结果是您应该关注的。但您不希望只测试一次模型,因为如果您看到极好或极差的结果,那可能是偶然的。您希望进行 $k$ 次此过程,使用不同的训练集和测试集,这样您就可以确信您正在比较的是 **模型设计**,而不是特定训练的结果。

您可以在这里使用的技术称为 k 折交叉验证。它会将一个较大的数据集分成 $k$ 部分,然后取其中一部分作为测试集,而将 $k-1$ 部分合并为训练集。有 $k$ 种不同的组合。因此,您可以重复实验 $k$ 次并取平均结果。

在 scikit-learn 中,有一个用于分层 k 折的函数。分层意味着当数据被分成 $k$ 部分时,算法会查看标签(即二元分类问题中的正类和负类),以确保分割方式使得每个部分都包含相同数量的类别。

运行 k 折交叉验证非常简单,例如:

简单来说,您使用 scikit-learn 中的 StratifiedKFold() 来分割数据集。此函数返回索引。因此,您可以使用 X[train]X[test] 创建分割后的数据集,并将其命名为训练集和验证集(以便与稍后用于选择模型设计的“测试集”区分开)。您假设有一个函数可以运行模型上的训练循环,并为您提供验证集上的准确率。然后,您可以找到此分数作为此类模型设计的性能指标的平均值和标准差。请注意,您需要在上面的 for 循环中为每次创建新模型,因为在 k 折交叉验证中不应重新训练已训练过的模型。

训练循环可以定义如下:

上面的训练循环包含了常规元素:前向传播、反向传播和梯度下降权重更新。但它扩展了每个 epoch 后的评估步骤:您在评估模式下运行模型,并检查模型如何预测 **验证集**。验证集上的准确率与模型权重一起被保存。在训练结束时,最佳权重会被恢复到模型,并返回最佳准确率。这个返回值是您在多次 epoch 训练中遇到的最佳值,并且是基于验证集的。

请注意,您将 tqdm 中的 disable 设置为 True。您可以将其设置为 False,以便在训练过程中查看训练集的损失和准确率。

请记住,目标是选择最佳设计并重新训练模型,在训练过程中,您希望获得评估分数,以便了解在生产环境中可以期待什么。因此,您应该将获得的整个数据集分成训练集和测试集。然后,您将训练集进一步分为 k 折交叉验证。

有了这些,您可以这样比较两个模型设计:对每个模型运行 k 折交叉验证并比较准确率。

You may see the output of above as follows

So you found that the deeper model is better than the wider model, in the sense that the mean accuracy is higher and its standard deviation is lower.

Retrain the Final Model

Now you know which design to pick, you want to rebuild the model and retrain it. Usually in k-fold cross validation, you will use a smaller dataset to make the training faster. The final accuracy is not an issue because the gold of k-fold cross validation to to tell which design is better. In the final model, you want to provide more data and produce a better model, since this is what you will use in production.

As you already split the data into training and test set, these are what you will use. In Python code,

You can reuse the model_train() function as it is doing all the required training and validation. This is because the training procedure doesn’t change for the final model or during k-fold cross validation.

This model is what you can use in production. Usually it is unlike training, prediction is one data sample at a time in production. The following is how we demonstate using the model for inference by running five samples from the test set

Its output should look like the following

You run the code under torch.no_grad() context because you sure there’s no need to run the optimizer on the result. Hence you want to relieve the tensors involved from remembering how the values are computed.

The output of a binary classification neural network is between 0 and 1 (because of the sigmoid function at the end). From encoder.classes_, you can see that 0 means “M” and 1 means “R”. For a value between 0 and 1, you can simply round it to the nearest integer and interpret the 0-1 result, i.e.,

or use any other threshold to quantize the value into 0 or 1, i.e.,

Indeed, round to the nearest integer is equivalent to using 0.5 as the threshold. A good model should be robust to the choice of threshold. It is when the model output exactly 0 or 1. Otherwise you would prefer a model that seldom report values in the middle but often return values close to 0 or close to 1. To see if your model is good, you can use receiver operating characteristic curve (ROC), which is to plot the true positive rate against the false positive rate of the model under various threshold. You can make use of scikit-learn and matplotlib to plot the ROC

You may see the following. The curve is always start from the lower left corner and ends at upper right corner. The closer the curve to the upper left corner, the better your model is.

Complete Code

Putting everything together, the following is the complete code of the above

总结

In this post, you discovered the use of PyTorch to build a binary classification model.

You learned how you can work through a binary classification problem step-by-step with PyTorch, specifically

  • How to load and prepare data for use in PyTorch
  • How to create neural network models and use k-fold cross validation to compare them
  • How to train a binary classification model and obtain the receiver operating characteristics curve for it

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

Deep Learning with PyTorch

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

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

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

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

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


查看内容

One Response to Building a Binary Classification Model in PyTorch

  1. shadow February 5, 2024 at 5:26 pm #

    Hello, there is a problem I don’t understand. In the two loops of fold.split, there is model=Wide() or Deep() at the beginning of each loop. Is this a reset of the model? If each loop continues to train the best model in the previous cycle, Whether model=Wide() or Deep() should be placed outside the loop to avoid reassignment of the model

Leave a Reply

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