@TOC
本文将介绍 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 等,并且用户也能够自定义优化器来满足特定需要。
本文由 mdnice 多平台公布