百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

Pytorch入门-Day 14:实践与优化(pytorch 60分钟教程)

ztj100 2025-06-09 07:25 15 浏览 0 评论

学习目标

  1. 理解学习率衰减的作用:掌握学习率衰减如何帮助模型在训练后期更稳定地收敛。
  2. 学习使用 torch.optim.lr_scheduler:在PyTorch中实现学习率调度器(如StepLR、CosineAnnealingLR)。
  3. 优化CNN模型训练:通过改进训练流程(加入学习率衰减、Dropout等),提升模型性能。
  4. 实践调试与分析:通过监控损失和学习率,分析优化效果。

术语表

  • 学习率(Learning Rate):控制模型参数更新步长的超参数,影响训练速度和收敛性。
  • 学习率衰减(Learning Rate Decay):在训练过程中逐渐降低学习率,以在后期更精细地优化模型。
  • 学习率调度器(Learning Rate Scheduler):PyTorch中用于动态调整学习率的工具,如 StepLR、CosineAnnealingLR。
  • Dropout:一种正则化技术,在训练时随机丢弃部分神经元,防止过拟合。
  • 优化器(Optimizer):用于更新模型参数的算法,如Adam、SGD。
  • Epoch:模型遍历一次完整训练数据集的轮次。
  • Batch Size:每次训练迭代中使用的样本数量。
  • Overfitting(过拟合):模型在训练数据上表现很好,但在测试数据上表现较差。

代码示例:优化CNN模型并加入学习率衰减

以下是一个完整的PyTorch代码示例,基于MNIST数据集,展示如何改进CNN模型并加入学习率衰减。代码包含详细注释,涵盖模型定义、训练流程和优化技巧。

python

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import DataLoader
import torchvision
import torchvision.transforms as transforms
from torch.optim.lr_scheduler import StepLR, CosineAnnealingLR

# 设置随机种子以确保结果可重复
torch.manual_seed(42)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 定义CNN模型
class ImprovedCNN(nn.Module):
    def __init__(self):
        super(ImprovedCNN, self).__init__()
        # 第一个卷积层:输入1通道(灰度图),输出16通道,3x3卷积核
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, padding=1)
        # 第二个卷积层:输入16通道,输出32通道,3x3卷积核
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
        # Dropout层,随机丢弃30%的神经元,防止过拟合
        self.dropout = nn.Dropout(0.3)
        # 最大池化层:2x2窗口,步长2
        self.pool = nn.MaxPool2d(2, 2)
        # 全连接层1:将卷积层的输出展平后映射到128个神经元
        self.fc1 = nn.Linear(32 * 7 * 7, 128)
        # 全连接层2:映射到10个类别(MNIST数据集)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        # 输入x: [batch_size, 1, 28, 28]
        x = F.relu(self.conv1(x))  # 卷积 + ReLU激活
        x = self.pool(x)           # 池化,输出[batch_size, 16, 14, 14]
        x = F.relu(self.conv2(x))  # 卷积 + ReLU激活
        x = self.pool(x)           # 池化,输出[batch_size, 32, 7, 7]
        x = self.dropout(x)        # 应用Dropout
        x = x.view(-1, 32 * 7 * 7)  # 展平为[batch_size, 32*7*7]
        x = F.relu(self.fc1(x))    # 全连接层 + ReLU
        x = self.dropout(x)        # 再次应用Dropout
        x = self.fc2(x)            # 输出层,[batch_size, 10]
        return x

# 加载MNIST数据集
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))  # MNIST均值和标准差
])

train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = torchvision.datasets.MNIST(root='./data', train=False, transform=transform)

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

# 初始化模型、损失函数和优化器
model = ImprovedCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 设置学习率调度器
# StepLR:每step_size个epoch,学习率乘以gamma
scheduler = StepLR(optimizer, step_size=5, gamma=0.5)
# 或者使用CosineAnnealingLR:学习率按余弦函数衰减
# scheduler = CosineAnnealingLR(optimizer, T_max=20)

# 训练函数
def train(model, device, train_loader, optimizer, criterion, epoch):
    model.train()
    running_loss = 0.0
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()           # 清空梯度
        output = model(data)            # 前向传播
        loss = criterion(output, target) # 计算损失
        loss.backward()                 # 反向传播
        optimizer.step()                # 更新参数
        running_loss += loss.item()
        if batch_idx % 100 == 99:       # 每100个batch打印一次
            print(f'Epoch {epoch}, Batch {batch_idx + 1}, Loss: {running_loss / 100:.4f}')
            running_loss = 0.0
    # 更新学习率
    scheduler.step()
    print(f'Epoch {epoch}, Learning Rate: {scheduler.get_last_lr()[0]:.6f}')

# 测试函数
def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += criterion(output, target).item()
            pred = output.argmax(dim=1, keepdim=True)
            correct += pred.eq(target.view_as(pred)).sum().item()
    test_loss /= len(test_loader.dataset)
    accuracy = 100. * correct / len(test_loader.dataset)
    print(f'Test Loss: {test_loss:.4f}, Accuracy: {accuracy:.2f}%')

# 训练循环
num_epochs = 10
for epoch in range(1, num_epochs + 1):
    train(model, device, train_loader, optimizer, criterion, epoch)
    test(model, device, test_loader)


代码注释与优化说明

  1. 模型结构改进: 添加了Dropout层(nn.Dropout(0.3)),在训练时随机丢弃30%的神经元,防止过拟合。 使用两层卷积+池化结构,增加模型深度,同时保持计算效率。 全连接层减少到128个神经元,降低参数量,适合MNIST数据集。
  2. 学习率衰减: 使用 StepLR 调度器,每5个epoch将学习率乘以0.5,逐步减小步长以稳定收敛。 注释中提供了 CosineAnnealingLR 的替代方案,适合需要平滑衰减的场景。 学习率变化在训练时打印,便于监控。
  3. 训练流程优化: 使用Adam优化器,初始学习率0.001,适合快速收敛。 每100个batch打印一次损失,减少输出冗余。 测试函数计算平均损失和准确率,评估模型性能。
  4. 数据预处理: 对MNIST数据进行归一化(均值0.1307,标准差0.3081),提高训练稳定性。 使用DataLoader批量加载数据,batch_size=64,平衡效率和内存使用。

运行结果预期

  • 损失下降:随着epoch增加,训练损失逐渐降低,学习率衰减后更稳定。
  • 准确率提升:测试集准确率通常可达98%以上(MNIST数据集)。
  • 学习率变化:StepLR每5个epoch将学习率减半,例如从0.001到0.0005,再到0.00025。



任务完成与扩展建议

  1. 已完成任务: 实现了改进的CNN模型,加入Dropout和学习率衰减。 使用 torch.optim.lr_scheduler.StepLR 动态调整学习率。 提供详细注释,涵盖模型、训练和测试流程。
  2. 扩展练习: 尝试 CosineAnnealingLR 或 ReduceLROnPlateau(基于验证损失调整学习率)。 增加Batch Normalization层,进一步提升模型稳定性。 记录并可视化训练/测试损失曲线(使用matplotlib或tensorboard)。 调整Dropout比例(如0.2或0.5),观察对过拟合的影响。

相关推荐

这个 JavaScript Api 已被废弃!请慎用!

在开发过程中,我们可能会不自觉地使用一些已经被标记为废弃的JavaScriptAPI。这些...

JavaScript中10个“过时”的API,你的代码里还在用吗?

JavaScript作为一门不断发展的语言,其API也在持续进化。新的、更安全、更高效的API不断涌现,而一些旧的API则因为各种原因(如安全问题、性能瓶颈、设计缺陷或有了更好的替代品)被标记为“废...

几大开源免费的 JavaScript 富文本编辑器测评

MarkDown编辑器用的时间长了,发现发现富文本编辑器用起来是真的舒服。...

比较好的网页里面的 html 编辑器 推荐

如果您正在寻找嵌入到网页中的HTML编辑器,以便用户可以直接在网页上编辑HTML内容,以下是几个备受推荐的:CKEditor:CKEditor是一个功能强大的、开源的富文本编辑器,可以嵌入到...

Luckysheet 实现excel多人在线协同编辑

前言前些天看到Luckysheet支持协同编辑Excel,正符合我们协同项目的一部分,故而想进一步完善协同文章,但是遇到了一下困难,特此做声明哈,若侵权,请联系我删除文章!若侵犯版权、个人隐私,请联系...

从 Element UI 源码的构建流程来看前端 UI 库设计

作者:前端森林转发链接:https://mp.weixin.qq.com/s/ziDMLDJcvx07aM6xoEyWHQ引言...

手把手教你如何用 Decorator 装饰你的 Typescript?「实践」

作者:Nealyang转发连接:https://mp.weixin.qq.com/s/PFgc8xD7gT40-9qXNTpk7A...

推荐五个优秀的富文本编辑器

富文本编辑器是一种可嵌入浏览器网页中,所见即所得的文本编辑器。对于许多从事前端开发的小伙伴来说并不算陌生,它的应用场景非常广泛,平时发个评论、写篇博客文章等都能见到它的身影。...

基于vue + element的后台管理系统解决方案

作者:林鑫转发链接:https://github.com/lin-xin前言该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(WebManagementSystem)开发。基于v...

开源富文本编辑器Quill 2.0重磅发布

开源富文本编辑器Quill正式发布2.0版本。官方TypeScript声明...

Python之Web开发框架学习 Django-表单处理

在Django中创建表单实际上类似于创建模型。同样,我们只需要从Django类继承,则类属性将是表单字段。让我们在myapp文件夹中添加一个forms.py文件以包含我们的应用程序表单。我们将创建一个...

Django测试入门:打造坚实代码基础的钥匙

这一篇说一下django框架的自动化测试,...

Django ORM vs SQLAlchemy:到底谁更香?从入门到上头的选择指南

阅读文章前辛苦您点下“关注”,方便讨论和分享,为了回馈您的支持,我将每日更新优质内容。...

超详细的Django 框架介绍,它来了!

时光荏苒,一晃小编的Tornado框架系列也结束了。这个框架虽然没有之前的FastAPI高流量,但是,它也是小编的心血呀。总共16篇博文,从入门到进阶,包含了框架的方方面面。虽然小编有些方面介绍得不是...

20《Nginx 入门教程》使用 Nginx 部署 Python 项目

今天的目标是完成一个PythonWeb项目的线上部署,我们使用最新的Django项目搭建一个简易的Web工程,然后基于Nginx服务部署该PythonWeb项目。1.前期准备...

取消回复欢迎 发表评论: