guog算法笔记

V1

2023/04/06阅读:61主题:默认主题

PyTorch中的9种常见梯度下降算法与案例

@

本文将介绍PyTorch中的几种常见梯度下降算法,并提供相应的Python案例。

1. 批量梯度下降(Batch Gradient Descent)

批量梯度下降是最基础的梯度下降算法,通过使用全部训练数据计算损失函数的梯度来更新参数。在PyTorch中,可以通过定义损失函数和优化器来实现批量梯度下降。

例如,在简单线性回归问题中使用批量梯度下降:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 定义损失函数
loss_fn = torch.nn.MSELoss()

# 定义优化器和超参数
optimizer = torch.optim.SGD([w, b], lr=0.01)
epochs = 100

# 批量梯度下降
for epoch in range(epochs):
# 前向传播
Y_pred = w * X + b
# 计算损失
loss = loss_fn(Y_pred, Y)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()

# 输出结果
print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 1.9999034404754639, b = 0.00041007260753999686

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

2. 随机梯度下降(Stochastic Gradient Descent)

随机梯度下降是一种在每次更新时随机选择一个样本进行梯度计算和参数更新的梯度下降算法。相比批量梯度下降,随机梯度下降具有更快的收敛速度,但更新过程较为不稳定。在PyTorch中,可以通过定义DataLoader来实现随机梯度下降。

例如,在简单线性回归问题中使用随机梯度下降:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 定义损失函数和优化器
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.SGD([w, b], lr=0.01)

# 定义超参数
batch_size = 1
epochs = 100

# 随机梯度下降
for epoch in range(epochs):
# 创建DataLoader
loader = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(X, Y), batch_size=batch_size, shuffle=True)
for x_batch, y_batch in loader:
# 前向传播
y_pred = w * x_batch + b
# 计算损失
loss = loss_fn(y_pred, y_batch)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()


# 输出结果

print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 2.0002050399780273, b = -0.0005163848866038325

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

3. 小批量梯度下降(Mini-batch Gradient Descent)

小批量梯度下降是介于批量梯度下降和随机梯度下降之间的梯度下降算法,即每次更新时选取一定数量的样本进行梯度计算和参数更新。在PyTorch中,可以通过定义DataLoader来实现小批量梯度下降。

例如,在简单线性回归问题中使用小批量梯度下降:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 定义损失函数和优化器
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.SGD([w, b], lr=0.01)

# 定义超参数
batch_size = 2
epochs = 100

# 小批量梯度下降
for epoch in range(epochs):
# 创建DataLoader
loader = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(X, Y), batch_size=batch_size, shuffle=True)
for x_batch, y_batch in loader:
# 前向传播
y_pred = w * x_batch + b
# 计算损失
loss = loss_fn(y_pred, y_batch)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()

# 输出结果
print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 1.9998304843902588, b = -0.00010240276428798664

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

4. 动量梯度下降(Momentum Gradient Descent)

动量梯度下降是一种在梯度下降更新过程中加入动量项的优化算法,可以加速收敛并减少震荡。在PyTorch中,可以通过设置momentum参数实现动量梯度下降。

例如,在简单线性回归问题中使用动量梯度下降:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数和动量
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)
momentum = 0.9

# 定义损失函数和优化器
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.SGD([w, b], lr=0.01, momentum=momentum)



# 定义超参数
epochs = 100

# 动量梯度下降
for epoch in range(epochs):
# 前向传播
y_pred = w * X + b
# 计算损失
loss = loss_fn(y_pred, Y)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()

# 输出结果
print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 1.9999991655349731, b = -3.718109681471333e-05

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

5. AdaGrad

AdaGrad是一种自适应学习率的优化算法,在更新参数时根据历史梯度信息来动态调整每个参数的学习率。在PyTorch中,可以通过设置optim.Adagrad()来使用该优化器。

例如,在简单线性回归问题中使用AdaGrad:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 定义损失函数和优化器
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.Adagrad([w, b], lr=0.1)

# 定义超参数
epochs = 100

# AdaGrad
for epoch in range(epochs):
# 前向传播
y_pred = w * X + b
# 计算损失
loss = loss_fn(y_pred, Y)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()

# 输出结果
print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 1.999985694885254, b = -0.0010528544095081096

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

6. RMSprop

RMSprop是一种自适应学习率的优化算法,在更新参数时根据历史梯度平方的加权平均来动态调整每个参数的学习率。在PyTorch中,可以通过设置optim.RMSprop()来使用该优化器。

例如,在简单线性回归问题中使用RMSprop:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 定义损失函数和优化器
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.RMSprop([w, b], lr=0.01)

# 定义超参数
epochs = 100

# RMSprop
for epoch in range(epochs):
# 前向传播
y_pred = w * X + b
# 计算损失
loss = loss_fn(y_pred, Y)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()

# 输出结果
print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 2.000011920928955, b = -0.00020079404229614145

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

7. Adam

Adam是一种融合了动量梯度下降和自适应学习率的优化算法,在更新参数时既考虑历史梯度的加权平均又考虑历史梯度平方的加权平均。在PyTorch中,可以通过设置optim.Adam()来使用该优化器。

例如,在简单线性回归问题中使用Adam:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 定义损失函数和优化器
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.Adam([w, b], lr=0.01)

# 定义超参数
epochs = 100

# Adam
for epoch in range(epochs):
# 前向传播
y_pred = w * X + b
# 计算损失
loss = loss_fn(y_pred, Y)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()

# 输出结果
print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 2.0000016689300537, b = -1.788223307551633e-05

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

8. AdamW

AdamW是一种基于Adam优化算法的变体,它引入了权重衰减(weight decay)来解决Adam可能存在的参数过度拟合问题。在PyTorch中,可以通过设置optim.AdamW()来使用该优化器。

例如,在简单线性回归问题中使用AdamW:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 定义损失函数和优化器
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.AdamW([w, b], lr=0.01, weight_decay=0.1)

# 定义超参数
epochs = 100

# AdamW
for epoch in range(epochs):
# 前向传播
y_pred = w * X + b
# 计算损失
loss = loss_fn(y_pred, Y)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()

# 输出结果
print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 1.9564942121505737, b = 0.063056387424469

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

9. Adadelta

Adadelta是一种自适应学习率的优化算法,它与RMSprop相似,但引入了一个衰减系数来平衡历史梯度平方和目标函数变化量。在PyTorch中,可以通过设置optim.Adadelta()来使用该优化器。

例如,在简单线性回归问题中使用Adadelta:

import torch
import matplotlib.pyplot as plt

# 定义训练数据
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)

# 初始化模型参数
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 定义损失函数和优化器
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.Adadelta([w, b], lr=0.1)

# 定义超参数
epochs = 100

# Adadelta
for epoch in range(epochs):
# 前向传播
y_pred = w * X + b
# 计算损失
loss = loss_fn(y_pred, Y)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()

# 输出结果
print(f"w = {w.item()}, b = {b.item()}")

# 绘制拟合直线
plt.scatter(X.numpy(), Y.numpy())
plt.plot(X.numpy(), (w * X + b).detach().numpy(), 'r')
plt.show()

输出:

w = 2.0000007152557373, b = 4.5047908031606675e-08

绘制的拟合直线如下图所示:

在这里插入图片描述
在这里插入图片描述

以上是常见的优化算法,它们在不同的场景下表现出不同的效果。除此之外,PyTorch还支持其他优化算法,如Adagrad、Adamax等,并且用户也可以自定义优化器来满足特定需求。

分类:

人工智能

标签:

人工智能

作者介绍

guog算法笔记
V1