在 PyTorch 中实现梯度下降

梯度下降算法是训练深度神经网络最流行的技术之一。它在计算机视觉、语音识别和自然语言处理等领域有许多应用。虽然梯度下降的概念已经存在了几十年,但直到最近才应用于深度学习相关的应用。

梯度下降是一种迭代优化方法,通过在每一步迭代地更新值来找到目标函数的最小值。每次迭代,它都会朝着所需方向迈出小步,直到收敛或满足停止条件。

在本教程中,您将使用两个可训练参数训练一个简单的线性回归模型,并探索梯度下降的工作原理以及如何在 PyTorch 中实现它。特别是,您将学习到

  • 梯度下降算法及其在 PyTorch 中的实现
  • 批量梯度下降及其在 PyTorch 中的实现
  • 随机梯度下降及其在 PyTorch 中的实现
  • 批量梯度下降和随机梯度下降有何不同
  • 在训练过程中,批量梯度下降和随机梯度下降的损失如何降低

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


那么,让我们开始吧。

在 PyTorch 中实现梯度下降。
图片来自 Michael Behrens。保留部分权利。

概述

本教程分为四个部分;它们是:

  • 准备数据
  • 批量梯度下降
  • 随机梯度下降
  • 绘制图表进行比较

准备数据

为了使模型简单易懂,我们将沿用上一个教程中的线性回归问题。数据是合成的,生成方式如下:

与之前的教程一样,我们初始化了一个变量`X`,其值范围从-5到5,并创建了一个斜率为-5的线性函数。然后,添加高斯噪声以创建变量`Y`。

我们可以使用 matplotlib 绘制数据以可视化模式

回归模型的数据点


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

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

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

批量梯度下降

现在我们已经为模型创建了数据,接下来我们将根据一个简单的线性回归方程构建一个前向函数。我们将训练模型以确定两个参数($w$ 和 $b$)。我们还需要一个损失准则函数。因为它是一个连续值的回归问题,所以 MSE 损失是合适的。

在我们训练模型之前,让我们了解一下**批量梯度下降**。在批量梯度下降中,训练数据中的所有样本都只考虑一个步骤。通过计算所有训练示例的平均梯度来更新参数。换句话说,在一个 epoch 中只有一步梯度下降。

虽然批量梯度下降对于平滑误差流形是最佳选择,但它相对较慢且计算复杂,特别是当您有更大的数据集进行训练时。

使用批量梯度下降进行训练

让我们随机初始化可训练参数 $w$ 和 $b$,并定义一些训练参数,例如学习率或步长、一个用于存储损失的空列表以及训练的 epoch 数。

我们将使用以下代码行训练模型 20 个 epoch。在这里,`forward()`函数生成预测,而`criterion()`函数测量损失并将其存储在`loss`变量中。`backward()`方法执行梯度计算,更新后的参数存储在`w.data`和`b.data`中。

以下是应用批量梯度下降后,每次 epoch 结束时输出和参数的更新方式。

总而言之,以下是完整的代码

上面的 for 循环每 epoch 打印一行,如下所示

随机梯度下降

正如我们所知,当训练数据量巨大时,批量梯度下降并不是一个合适的选择。然而,深度学习算法对数据有很高的要求,通常需要大量数据进行训练。例如,如果使用批量梯度下降,一个拥有数百万训练样本的数据集将要求模型在单个步骤中计算所有数据的梯度。

这似乎不是一种有效的方法,替代方案是**随机梯度下降** (SGD)。随机梯度下降一次只考虑训练数据中的一个样本,计算梯度并迈出一步,然后更新权重。因此,如果训练数据中有 N 个样本,每个 epoch 将有 N 个步骤。

使用随机梯度下降进行训练

为了使用随机梯度下降训练我们的模型,我们将随机初始化可训练参数 $w$ 和 $b$,就像我们为上述批量梯度下降所做的那样。在这里,我们将定义一个空列表来存储随机梯度下降的损失,并训练模型 20 个 epoch。以下是根据先前示例修改后的完整代码。

这会打印出一长串值,如下所示

绘制图表进行比较

现在我们已经使用批量梯度下降和随机梯度下降训练了我们的模型,让我们可视化在模型训练过程中两种方法的损失是如何降低的。因此,批量梯度下降的图表看起来像这样。

批量梯度下降的损失历史

同样,随机梯度下降的图表如下所示。

随机梯度下降的损失历史

如您所见,批量梯度下降的损失平稳下降。另一方面,您会观察到随机梯度下降的图表出现波动。正如前面提到的,原因很简单。在批量梯度下降中,损失是在处理完所有训练样本后才更新的,而随机梯度下降则是在训练数据中的每个训练样本之后更新损失的。

综上所述,以下是完整的代码

总结

在本教程中,您了解了梯度下降,它的一些变体,以及如何在 PyTorch 中实现它们。特别是,您学习了

  • 梯度下降算法及其在 PyTorch 中的实现
  • 批量梯度下降及其在 PyTorch 中的实现
  • 随机梯度下降及其在 PyTorch 中的实现
  • 批量梯度下降和随机梯度下降有何不同
  • 在训练过程中,批量梯度下降和随机梯度下降的损失如何降低

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

Deep Learning with PyTorch

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

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

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

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

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


查看内容

对《在 PyTorch 中实现梯度下降》的 3 条回复

  1. Evgeny 2023 年 4 月 30 日 上午 3:56 #

    感谢您的代码,它对我的学习非常有帮助。不幸的是,SGD 不起作用。
    但我建议进行一些修正
    1) 第 10 行只是为了美化:Y = func + torch.randn(X.size())
    2) 为了让 SGD 工作(这里它不收敛):仅对 SGD 设置 step_size=0.001
    3) 为了让 SGD 符合维基百科的描述,在每个 epoch 之前打乱数据
    在内部循环之前添加

    idx = torch.randperm(Y.shape[0])
    X = X[idx].view(X.size())
    Y = Y[idx].view(Y.size())

  2. Florian 2023 年 12 月 25 日 上午 4:03 #

    对于线性回归问题使用随机梯度下降法有点牵强,因为线性回归问题存在闭式解……为什么不用另一个简单的问题来做呢,比如逻辑回归?

发表回复

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