微信登录

优化器 - 梯度下降 - 基本梯度下降算法

PyTorch 优化器 - 梯度下降 - 基本梯度下降算法

一、引言

在深度学习的世界里,训练模型就像是在一个复杂的地形中寻找山谷的最低点,这个最低点代表着模型损失函数的最小值,意味着模型的最优状态。而梯度下降算法就是帮助我们在这片“地形”中找到最低点的重要工具。PyTorch 作为深度学习领域中广受欢迎的框架,为我们提供了丰富的优化器来实现各种梯度下降算法。接下来,我们将深入探讨基本梯度下降算法在 PyTorch 中的应用。

二、梯度下降算法的基本原理

2.1 直观理解

想象你站在一座山上,你的目标是到达山的最低点。你不知道最低点的确切位置,但你可以感受到脚下地面的倾斜程度(梯度)。梯度下降算法的思想就是根据当前位置的梯度方向,朝着坡度下降的方向迈出一步,然后不断重复这个过程,直到你感觉自己已经到达了最低点。

2.2 数学原理

假设我们有一个损失函数 $J(\theta)$,其中 $\theta$ 是模型的参数。梯度下降算法的更新公式为:
$\theta = \theta - \alpha \nabla J(\theta)$
其中,$\alpha$ 是学习率,它控制着每一步迈出的大小;$\nabla J(\theta)$ 是损失函数 $J(\theta)$ 关于参数 $\theta$ 的梯度,它表示损失函数在当前点的变化率和方向。梯度的方向总是指向损失函数增加最快的方向,所以我们取负号来朝着损失函数减小的方向更新参数。

三、基本梯度下降算法的类型

3.3.1 批量梯度下降(Batch Gradient Descent, BGD)

  • 原理:在每一次迭代中,使用整个训练数据集来计算损失函数的梯度,并更新参数。
  • 优点:收敛稳定,最终可以收敛到全局最优解(对于凸函数)。
  • 缺点:计算成本高,尤其是当训练数据集非常大时,每次迭代都需要处理整个数据集,训练速度慢。

3.3.2 随机梯度下降(Stochastic Gradient Descent, SGD)

  • 原理:在每一次迭代中,随机选择一个样本点来计算损失函数的梯度,并更新参数。
  • 优点:计算速度快,每次只处理一个样本,能够更快地更新参数,适用于大规模数据集。
  • 缺点:收敛过程不稳定,容易陷入局部最优解,且梯度的方差较大,导致参数更新的方向波动较大。

3.3.3 小批量梯度下降(Mini - Batch Gradient Descent, MBGD)

  • 原理:在每一次迭代中,随机选择一小批样本(通常是 16、32、64 等)来计算损失函数的梯度,并更新参数。
  • 优点:结合了批量梯度下降和随机梯度下降的优点,既具有较快的计算速度,又能使收敛过程相对稳定。
  • 缺点:需要手动调整小批量的大小,不同的小批量大小可能会影响模型的性能。

下面是三种梯度下降算法的对比表格:
| 算法类型 | 每次迭代使用的数据量 | 计算速度 | 收敛稳定性 |
| —— | —— | —— | —— |
| 批量梯度下降(BGD) | 整个训练数据集 | 慢 | 高 |
| 随机梯度下降(SGD) | 一个样本 | 快 | 低 |
| 小批量梯度下降(MBGD) | 一小批样本 | 较快 | 较高 |

四、PyTorch 中实现基本梯度下降算法

4.1 准备工作

首先,我们需要导入必要的库,并生成一些示例数据。

  1. import torch
  2. import torch.nn as nn
  3. import torch.optim as optim
  4. # 生成示例数据
  5. x = torch.randn(100, 1)
  6. y = 2 * x + 1 + 0.1 * torch.randn(100, 1)

4.2 定义模型和损失函数

我们定义一个简单的线性回归模型,并使用均方误差损失函数。

  1. # 定义线性回归模型
  2. model = nn.Linear(1, 1)
  3. # 定义损失函数
  4. criterion = nn.MSELoss()

4.3 使用不同的优化器实现梯度下降算法

4.3.1 批量梯度下降(BGD)

  1. # 定义优化器,使用随机梯度下降,这里 batch_size 为整个数据集大小
  2. optimizer = optim.SGD(model.parameters(), lr=0.01)
  3. # 训练模型
  4. num_epochs = 100
  5. for epoch in range(num_epochs):
  6. # 前向传播
  7. outputs = model(x)
  8. loss = criterion(outputs, y)
  9. # 反向传播和优化
  10. optimizer.zero_grad()
  11. loss.backward()
  12. optimizer.step()
  13. if (epoch + 1) % 10 == 0:
  14. print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')

4.3.2 随机梯度下降(SGD)

  1. # 定义优化器,使用随机梯度下降
  2. optimizer = optim.SGD(model.parameters(), lr=0.01)
  3. # 训练模型
  4. num_epochs = 100
  5. for epoch in range(num_epochs):
  6. for i in range(len(x)):
  7. # 随机选择一个样本
  8. single_x = x[i].unsqueeze(0)
  9. single_y = y[i].unsqueeze(0)
  10. # 前向传播
  11. outputs = model(single_x)
  12. loss = criterion(outputs, single_y)
  13. # 反向传播和优化
  14. optimizer.zero_grad()
  15. loss.backward()
  16. optimizer.step()
  17. if (epoch + 1) % 10 == 0:
  18. # 计算整个数据集的损失
  19. outputs = model(x)
  20. loss = criterion(outputs, y)
  21. print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')

4.3.3 小批量梯度下降(MBGD)

  1. from torch.utils.data import DataLoader, TensorDataset
  2. # 创建数据集和数据加载器
  3. dataset = TensorDataset(x, y)
  4. dataloader = DataLoader(dataset, batch_size=16, shuffle=True)
  5. # 定义优化器,使用随机梯度下降
  6. optimizer = optim.SGD(model.parameters(), lr=0.01)
  7. # 训练模型
  8. num_epochs = 100
  9. for epoch in range(num_epochs):
  10. for batch_x, batch_y in dataloader:
  11. # 前向传播
  12. outputs = model(batch_x)
  13. loss = criterion(outputs, batch_y)
  14. # 反向传播和优化
  15. optimizer.zero_grad()
  16. loss.backward()
  17. optimizer.step()
  18. if (epoch + 1) % 10 == 0:
  19. outputs = model(x)
  20. loss = criterion(outputs, y)
  21. print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')

五、总结

基本梯度下降算法是深度学习中最基础也是最重要的优化算法之一。批量梯度下降、随机梯度下降和小批量梯度下降各有优缺点,在实际应用中需要根据数据集的大小、计算资源和模型的特点来选择合适的算法。PyTorch 为我们提供了方便的优化器接口,使得实现这些算法变得非常简单。通过不断调整学习率、小批量大小等超参数,我们可以让模型更快、更稳定地收敛到最优解。希望通过本文的介绍,你对基本梯度下降算法在 PyTorch 中的应用有了更深入的理解。