反向传播与优化器
3.8.1 反向传播
反向传播(Backpropagation) 是一种用于训练神经网络的算法,它通过计算梯度并根据梯度调整网络中的权重,从而使得模型能够学习到最佳参数,以最小化损失函数。反向传播是深度学习中最常用的优化方法之一。
- 原理:
- 前向传播(Forward Propagation): 输入数据从网络的输入层开始,经过每一层的计算(如加权求和、激活函数等),最终输出预测结果。这一过程的主要目的是计算出模型的输出,并与真实标签进行对比,从而计算损失函数。
- 计算损失(Loss Calculation): 在前向传播完成后,使用损失函数(例如均方误差、交叉熵等)计算模型预测结果与真实标签之间的差异(损失)。
- 反向传播(Backward Propagation): 反向传播的目的是根据损失函数的结果来调整网络中的每个参数(权重和偏置)。反向传播通过链式法则逐层计算损失函数相对于每个权重和偏置的梯度(即梯度是损失函数对这些参数的偏导数)。
- 从输出层开始,计算损失函数对输出层的梯度。
- 然后,根据链式法则将梯度传递到上一层,逐层计算每个层的梯度,直到输入层。
- 更新权重(Weights Update): 反向传播计算出的梯度指示了如何调整权重。通过优化算法(如梯度下降法),根据梯度的大小更新每个权重和偏置。
3.8.2 优化器
PyTorch 中的优化器是用来更新模型参数,以最小化损失函数的工具。在训练深度学习模型时,优化器会根据损失函数计算出的梯度来调整模型的权重,优化模型的表现。PyTorch 提供了多种优化器供用户选择,其中最常用的是梯度下降类优化器,如 SGD
和 Adam
。
- 常见的优化算法
-
SGD (Stochastic Gradient Descent)
这是最基本的优化方法,按比例调整参数,使用单个样本或批量样本来更新模型参数。
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
momentum
: 动量项,可以帮助优化器避免局部最小值,提升收敛速度。
-
Adam (Adaptive Moment Estimation)
Adam 是基于梯度的一阶和二阶矩估计的优化器,它计算每个参数的自适应学习率,在许多任务中表现优秀。
optimizer = optim.Adam(model.parameters(), lr=0.001)
lr
: 学习率betas
: 用于计算一阶矩和二阶矩估计的参数,默认为(0.9, 0.999)
。eps
: 防止除以零的数值稳定常数,默认是1e-8
。
-
RMSprop (Root Mean Square Propagation)
RMSprop 对每个参数自适应调整学习率,适用于递归神经网络(RNN)。
optimizer = optim.RMSprop(model.parameters(), lr=0.01)
lr
: 学习率alpha
: 衰减因子,控制历史梯度的权重,默认0.99
。
- 优化器的使用步骤:
- 搭建基本网络模型
import torchvision
from torch import nn as nn
from torch.utils.data import DataLoader
class CIFAR10_test(nn.Module):
def __init__(self):
super().__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Flatten(),
nn.Linear(in_features=1024, out_features=64),
nn.Linear(in_features=64, out_features=10)
)
def forward(self, input):
return self.model(input)
# 2.加载数据集
data = torchvision.datasets.CIFAR10('data-train', train=False, transform=torchvision.transforms.ToTensor(),
download=True)
data_loader = DataLoader(data, batch_size=1)
# 初始化模型
model = CIFAR10_test()
- 根据算法选择不同的优化器并设置参数
optim_sgd = torch.optim.SGD(
# 返回模型中所有可训练的参数。通常,这些参数包括模型的权重(weights)和偏置(biases)。
params=model.parameters(),
# 设置模型学习速率:梯度的下降速率
lr=0.01
)
- 定义损失函数
loss = nn.CrossEntropyLoss()
- 训练模型
for epoch in range(10): # 训练10个epoch
epoch_loss = 0.0 # 记录每个epoch的总损失
for x in data_loader: # 遍历数据加载器中的每个batch
img, target = x
input = model(img) # 获取模型的输出
res_loss = loss(input, target) # 计算当前批次的损失
optim_sgd.zero_grad() # 清除上一次的梯度
res_loss.backward() # 反向传播计算当前批次的梯度
optim_sgd.step() # 优化器进行一步更新
epoch_loss += res_loss # 累加当前batch的损失值
print(epoch_loss)
- 结果:优化后损失值在减小
tensor(18707.5059, grad_fn=<AddBackward0>)
tensor(16250.5391, grad_fn=<AddBackward0>)