Pytorch入门-Day 14:实践与优化(pytorch 60分钟教程)
ztj100 2025-06-09 07:25 21 浏览 0 评论
学习目标
- 理解学习率衰减的作用:掌握学习率衰减如何帮助模型在训练后期更稳定地收敛。
- 学习使用 torch.optim.lr_scheduler:在PyTorch中实现学习率调度器(如StepLR、CosineAnnealingLR)。
- 优化CNN模型训练:通过改进训练流程(加入学习率衰减、Dropout等),提升模型性能。
- 实践调试与分析:通过监控损失和学习率,分析优化效果。
术语表
- 学习率(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)
代码注释与优化说明
- 模型结构改进: 添加了Dropout层(nn.Dropout(0.3)),在训练时随机丢弃30%的神经元,防止过拟合。 使用两层卷积+池化结构,增加模型深度,同时保持计算效率。 全连接层减少到128个神经元,降低参数量,适合MNIST数据集。
- 学习率衰减: 使用 StepLR 调度器,每5个epoch将学习率乘以0.5,逐步减小步长以稳定收敛。 注释中提供了 CosineAnnealingLR 的替代方案,适合需要平滑衰减的场景。 学习率变化在训练时打印,便于监控。
- 训练流程优化: 使用Adam优化器,初始学习率0.001,适合快速收敛。 每100个batch打印一次损失,减少输出冗余。 测试函数计算平均损失和准确率,评估模型性能。
- 数据预处理: 对MNIST数据进行归一化(均值0.1307,标准差0.3081),提高训练稳定性。 使用DataLoader批量加载数据,batch_size=64,平衡效率和内存使用。
运行结果预期
- 损失下降:随着epoch增加,训练损失逐渐降低,学习率衰减后更稳定。
- 准确率提升:测试集准确率通常可达98%以上(MNIST数据集)。
- 学习率变化:StepLR每5个epoch将学习率减半,例如从0.001到0.0005,再到0.00025。
任务完成与扩展建议
- 已完成任务: 实现了改进的CNN模型,加入Dropout和学习率衰减。 使用 torch.optim.lr_scheduler.StepLR 动态调整学习率。 提供详细注释,涵盖模型、训练和测试流程。
- 扩展练习: 尝试 CosineAnnealingLR 或 ReduceLROnPlateau(基于验证损失调整学习率)。 增加Batch Normalization层,进一步提升模型稳定性。 记录并可视化训练/测试损失曲线(使用matplotlib或tensorboard)。 调整Dropout比例(如0.2或0.5),观察对过拟合的影响。
相关推荐
- Linux集群自动化监控系统Zabbix集群搭建到实战
-
自动化监控系统...
- systemd是什么如何使用_systemd/system
-
systemd是什么如何使用简介Systemd是一个在现代Linux发行版中广泛使用的系统和服务管理器。它负责启动系统并管理系统中运行的服务和进程。使用管理服务systemd可以用来启动、停止、...
- Linux服务器日常巡检脚本分享_linux服务器监控脚本
-
Linux系统日常巡检脚本,巡检内容包含了,磁盘,...
- 7,MySQL管理员用户管理_mysql 管理员用户
-
一、首次设置密码1.初始化时设置(推荐)mysqld--initialize--user=mysql--datadir=/data/3306/data--basedir=/usr/local...
- Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门
-
1.1数据库的核心概念在开始Python数据库编程之前,我们需要先理解几个核心概念。数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它就像一个电子化的文件柜,能让我们高效...
- Linux自定义开机自启动服务脚本_linux添加开机自启动脚本
-
设置WGCloud开机自动启动服务init.d目录下新建脚本在/etc/rc.d/init.d新建启动脚本wgcloudstart.sh,内容如下...
- linux系统启动流程和服务管理,带你进去系统的世界
-
Linux启动流程Rhel6启动过程:开机自检bios-->MBR引导-->GRUB菜单-->加载内核-->init进程初始化Rhel7启动过程:开机自检BIOS-->M...
- CentOS7系统如何修改主机名_centos更改主机名称
-
请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习1.前言本文将讲解CentOS7系统如何修改主机名。...
- 前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令
-
在Linux服务器管理中,SSH(SecureShell)是远程操作的核心工具。以下是SSH终端操作的常用命令和技巧,涵盖连接、文件操作、系统管理等场景:一、SSH连接服务器1.基本连接...
- Linux开机自启服务完全指南:3步搞定系统服务管理器配置
-
为什么需要配置开机自启?想象一下:电商服务器重启后,MySQL和Nginx没自动启动,整个网站瘫痪!这就是为什么开机自启是Linux运维的必备技能。自启服务能确保核心程序在系统启动时自动运行,避免人工...
- Kubernetes 高可用(HA)集群部署指南
-
Kubernetes高可用(HA)集群部署指南本指南涵盖从概念理解、架构选择,到kubeadm高可用部署、生产优化、监控备份和运维的全流程,适用于希望搭建稳定、生产级Kubernetes集群...
- Linux项目开发,你必须了解Systemd服务!
-
1.Systemd简介...
- Linux系统systemd服务管理工具使用技巧
-
简介:在Linux系统里,systemd就像是所有进程的“源头”,它可是系统中PID值为1的进程哟。systemd其实是一堆工具的组合,它的作用可不止是启动操作系统这么简单,像后台服务...
- Linux下NetworkManager和network的和平共处
-
简介我们在使用CentoOS系统时偶尔会遇到配置都正确但network启动不了的问题,这问题经常是由NetworkManager引起的,关闭NetworkManage并取消开机启动network就能正...
你 发表评论:
欢迎- 一周热门
-
-
MySQL中这14个小玩意,让人眼前一亮!
-
旗舰机新标杆 OPPO Find X2系列正式发布 售价5499元起
-
Linux下NetworkManager和network的和平共处
-
Kubernetes 高可用(HA)集群部署指南
-
linux系统启动流程和服务管理,带你进去系统的世界
-
7,MySQL管理员用户管理_mysql 管理员用户
-
面试官:使用int类型做加减操作,是线程安全吗
-
C++编程知识:ToString()字符串转换你用正确了吗?
-
【Spring Boot】WebSocket 的 6 种集成方式
-
PyTorch 深度学习实战(26):多目标强化学习Multi-Objective RL
-
- 最近发表
-
- Linux集群自动化监控系统Zabbix集群搭建到实战
- systemd是什么如何使用_systemd/system
- Linux服务器日常巡检脚本分享_linux服务器监控脚本
- 7,MySQL管理员用户管理_mysql 管理员用户
- Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门
- Linux自定义开机自启动服务脚本_linux添加开机自启动脚本
- linux系统启动流程和服务管理,带你进去系统的世界
- CentOS7系统如何修改主机名_centos更改主机名称
- 前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令
- Linux开机自启服务完全指南:3步搞定系统服务管理器配置
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)