5层卷积神经网络MNIST实战:学习率设置的科学与艺术

1次阅读
没有评论

共计 1377 个字符,预计需要花费 4 分钟才能阅读完成。

image.webp

背景痛点

MNIST 手写数字识别是深度学习的经典入门项目。使用 5 层卷积神经网络 (CNN) 的典型结构如下:

5 层卷积神经网络 MNIST 实战:学习率设置的科学与艺术

  1. 第一层:卷积层(Conv2d) + ReLU 激活 + 最大池化(MaxPool2d)
  2. 第二层:卷积层 + ReLU + 最大池化
  3. 第三层:全连接层(Linear) + Softmax 输出

新手常遇到的最大困扰就是学习率 (learning rate) 设置不当:

  • 学习率过大:损失函数震荡不收敛,准确率波动剧烈
  • 学习率过小:训练进度缓慢,可能需要数百 epoch 才能达到较好效果

技术方案对比

固定学习率 vs 动态调整

  1. 固定学习率:
  2. 最简单直接,但需要反复试错
  3. 推荐初始尝试值:0.01(SGD 优化器)或 0.001(Adam)

  4. 阶梯衰减(StepLR):

  5. 每 N 个 epoch 将学习率乘以衰减系数
  6. 例如:初始 0.1,每 30epoch 衰减为 0.1 倍

  7. 余弦退火(CosineAnnealingLR):

  8. 学习率呈余弦曲线变化
  9. 适合跳出局部最优

优化器选择

  • SGD:对学习率敏感,需要精细调整
  • Adam:自适应调整学习率,新手友好

核心实现

import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR

# 模型定义
class CNN5(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.fc = nn.Linear(1600, 10)  # MNIST 最终输出 10 类

    def forward(self, x):
        x = torch.relu(self.conv1(x))
        x = torch.max_pool2d(x, 2)
        x = torch.relu(self.conv2(x))
        x = torch.max_pool2d(x, 2)
        x = torch.flatten(x, 1)
        return self.fc(x)

# 初始化
model = CNN5()
optimizer = optim.Adam(model.parameters(), lr=0.001)  # 初始学习率
scheduler = StepLR(optimizer, step_size=30, gamma=0.1)  # 每 30epoch 衰减

# 训练循环
for epoch in range(100):
    # ... 训练代码 ...
    scheduler.step()  # 更新学习率

避坑指南

  1. 学习率与 batch size:
  2. 增大 batch size 时,应同比增大学习率
  3. 例如 batch size 从 128→256,学习率从 0.01→0.02

  4. 早停机制:

  5. 当验证集准确率连续 N 次不提升时终止训练
  6. 避免过拟合

  7. 梯度检查:

  8. 健康训练时梯度值应在 1e- 3 到 1e- 1 之间
  9. 过大可能爆炸,过小可能消失

延伸思考

如果测试集准确率突然下降,可能原因包括:

  1. 学习率衰减过快,模型无法继续优化
  2. 后期学习率过大导致震荡
  3. 优化器动量 (momentum) 设置不当

建议尝试将本方案迁移到 CIFAR-10 数据集,注意:

  • 调整输入尺寸(32×32 RGB 图像)
  • 可能需要更深的网络结构
  • 学习率通常需要设置得更小

通过合理设置学习率,你的模型应该能在 MNIST 上达到 99%+ 的测试准确率。记住:调参是一门需要实践的艺术,多尝试不同组合才能找到最佳配置。

正文完
 0
评论(没有评论)