PyTorch神经网络工具箱(优化器)

优化器

PyTorch常用的优化方法都封装在torch.optim里面,其设计很灵活,可以扩展为自定

义的优化方法。所有的优化方法都是继承了基类optim.Optimizer,并实现了自己的优化步

骤。最常用的优化算法就是梯度下降法及其各种变种,后续章节我们将介绍各种算法的原

理,这类优化算法通过使用参数的梯度值更新参数。

3.2节使用的随机梯度下降法(SGD)就是最普通的优化器,一般SGD并说没有加速

效果,3.2节使用的SGD包含动量参数Momentum,它是SGD的改良版。

我们结合3.2小结内容,说明使用优化器的一般步骤为:

(1)建立优化器实例

导入optim模块,实例化SGD优化器,这里使用动量参数momentum(该值一般在

(0,1)之间),是SGD的改进版,效果一般比不使用动量规则的要好。

python 复制代码
import torch.optim as optim
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)

以下步骤在训练模型的for循环中。

(2)向前传播

把输入数据传入神经网络Net实例化对象model中,自动执行forward函数,得到out输

出值,然后用out与标记label计算损失值loss。

python 复制代码
out = model(img)
loss = criterion(out, label)

(3)清空梯度

缺省情况梯度是累加的,在梯度反向传播前,先需把梯度清零。

python 复制代码
optimizer.zero_grad()

(4)反向传播

基于损失值,把梯度进行反向传播。

python 复制代码
loss.backward()

(5)更新参数

基于当前梯度(存储在参数的.grad属性中)更新参数。

python 复制代码
optimizer.step()

完整代码:

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset


# ===== 1. 修复未定义变量 =====
# 定义模型 (示例: 简单CNN)
class SimpleCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 16, 3)
        self.fc = nn.Linear(16 * 30 * 30, 10)  # 假设输入32x32图像

    def forward(self, x):
        x = torch.relu(self.conv1(x))
        x = x.view(x.size(0), -1)
        return self.fc(x)


model = SimpleCNN()  # [!修复model!]

# 定义超参数
EPOCHS = 100  # [!修复EPOCHS!]
LR = 0.01
MOMENTUM = 0.9  # 注意: 使用数值而非物理量

# 创建示例数据集 (实际应替换为真实数据)
dummy_imgs = torch.randn(1000, 3, 32, 32)  # [!修复img数据源!]
dummy_labels = torch.randint(0, 10, (1000,))  # [!修复label数据源!]
dataset = TensorDataset(dummy_imgs, dummy_labels)
dataloader = DataLoader(dataset, batch_size=64, shuffle=True)  # [!修复dataloader!]

criterion = nn.CrossEntropyLoss()  # [!修复criterion!]
optimizer = optim.SGD(model.parameters(), lr=LR, momentum=MOMENTUM)

# ===== 2. 增强型训练循环 =====
for epoch in range(EPOCHS):
    for batch in dataloader:
        img, label = batch  # [!解包获取img/label!]

        # 前向传播
        out = model(img)
        loss = criterion(out, label)

        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    print(f'Epoch {epoch + 1}/{EPOCHS} | Loss: {loss.item():.4f}')