python学习打卡day52

DAY 52 神经网络调参指南

知识点回顾:

  1. 随机种子
  2. 内参的初始化
  3. 神经网络调参指南
    1. 参数的分类
    2. 调参的顺序
    3. 各部分参数的调整心得

作业:对于day'41的简单cnn,看看是否可以借助调参指南进一步提高精度。

day41的简单CNN最后的结果,今天要做的是使用调参指南中的方法进一步提高精度

 

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np# 定义通道注意力
class ChannelAttention(nn.Module):def __init__(self, in_channels, ratio=16):"""通道注意力机制初始化参数:in_channels: 输入特征图的通道数ratio: 降维比例,用于减少参数量,默认为16"""super().__init__()# 全局平均池化,将每个通道的特征图压缩为1x1,保留通道间的平均值信息self.avg_pool = nn.AdaptiveAvgPool2d(1)# 全局最大池化,将每个通道的特征图压缩为1x1,保留通道间的最显著特征self.max_pool = nn.AdaptiveMaxPool2d(1)# 共享全连接层,用于学习通道间的关系# 先降维(除以ratio),再通过ReLU激活,最后升维回原始通道数self.fc = nn.Sequential(nn.Linear(in_channels, in_channels // ratio, bias=False),  # 降维层nn.ReLU(),  # 非线性激活函数nn.Linear(in_channels // ratio, in_channels, bias=False)   # 升维层)# Sigmoid函数将输出映射到0-1之间,作为各通道的权重self.sigmoid = nn.Sigmoid()def forward(self, x):"""前向传播函数参数:x: 输入特征图,形状为 [batch_size, channels, height, width]返回:调整后的特征图,通道权重已应用"""# 获取输入特征图的维度信息,这是一种元组的解包写法b, c, h, w = x.shape# 对平均池化结果进行处理:展平后通过全连接网络avg_out = self.fc(self.avg_pool(x).view(b, c))# 对最大池化结果进行处理:展平后通过全连接网络max_out = self.fc(self.max_pool(x).view(b, c))# 将平均池化和最大池化的结果相加并通过sigmoid函数得到通道权重attention = self.sigmoid(avg_out + max_out).view(b, c, 1, 1)# 将注意力权重与原始特征相乘,增强重要通道,抑制不重要通道return x * attention #这个运算是pytorch的广播机制## 空间注意力模块
class SpatialAttention(nn.Module):def __init__(self, kernel_size=7):super().__init__()self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False)self.sigmoid = nn.Sigmoid()def forward(self, x):# 通道维度池化avg_out = torch.mean(x, dim=1, keepdim=True)  # 平均池化:(B,1,H,W)max_out, _ = torch.max(x, dim=1, keepdim=True)  # 最大池化:(B,1,H,W)pool_out = torch.cat([avg_out, max_out], dim=1)  # 拼接:(B,2,H,W)attention = self.conv(pool_out)  # 卷积提取空间特征return x * self.sigmoid(attention)  # 特征与空间权重相乘## CBAM模块
class CBAM(nn.Module):def __init__(self, in_channels, ratio=16, kernel_size=7):super().__init__()self.channel_attn = ChannelAttention(in_channels, ratio)self.spatial_attn = SpatialAttention(kernel_size)def forward(self, x):x = self.channel_attn(x)x = self.spatial_attn(x)return x
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np# 设置中文字体支持
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题# 检查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")# 1. 数据预处理
# 训练集:使用多种数据增强方法提高模型泛化能力
train_transform = transforms.Compose([# 随机裁剪图像,从原图中随机截取32x32大小的区域transforms.RandomCrop(32, padding=4),# 随机水平翻转图像(概率0.5)transforms.RandomHorizontalFlip(),# 随机颜色抖动:亮度、对比度、饱和度和色调随机变化transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),# 随机旋转图像(最大角度15度)transforms.RandomRotation(15),# 将PIL图像或numpy数组转换为张量transforms.ToTensor(),# 标准化处理:每个通道的均值和标准差,使数据分布更合理transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])# 测试集:仅进行必要的标准化,保持数据原始特性,标准化不损失数据信息,可还原
test_transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])# 2. 加载CIFAR-10数据集
train_dataset = datasets.CIFAR10(root='./data',train=True,download=True,transform=train_transform  # 使用增强后的预处理
)test_dataset = datasets.CIFAR10(root='./data',train=False,transform=test_transform  # 测试集不使用增强
)# 3. 创建数据加载器
batch_size = 80
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# 4. 定义CNN模型的定义(替代原MLP)
class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()# 初始卷积层self.conv_init = nn.Sequential(nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False),nn.BatchNorm2d(64),nn.ReLU())# 第一卷积块(含CBAM)self.block1 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False),nn.BatchNorm2d(64),nn.ReLU(),nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False),nn.BatchNorm2d(64),CBAM(64)  # 在卷积块后添加CBAM)self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)self.drop1 = nn.Dropout2d(0.1)# 第二卷积块(含CBAM)self.block2 = nn.Sequential(nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1, bias=False),  # stride=2降维nn.BatchNorm2d(128),nn.ReLU(),nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1, bias=False),nn.BatchNorm2d(128),CBAM(128)  # 在卷积块后添加CBAM)self.pool2 = nn.AvgPool2d(kernel_size=2, stride=2)self.drop2 = nn.Dropout2d(0.2)# 第三卷积块(含CBAM)self.block3 = nn.Sequential(nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1, bias=False),nn.BatchNorm2d(256),nn.ReLU(),nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1, bias=False),nn.BatchNorm2d(256),CBAM(256)  # 在卷积块后添加CBAM)self.pool3 = nn.AdaptiveAvgPool2d(4)self.drop3 = nn.Dropout2d(0.3)# 全连接层self.fc = nn.Sequential(nn.Linear(256 * 4 * 4, 512),nn.BatchNorm1d(512),nn.ReLU(),nn.Dropout(0.5),nn.Linear(512, 128),nn.BatchNorm1d(128),nn.ReLU(),nn.Dropout(0.3),nn.Linear(128, 10))def forward(self, x):x = self.conv_init(x)x = self.block1(x)x = self.pool1(x)x = self.drop1(x)x = self.block2(x)x = self.pool2(x)x = self.drop2(x)x = self.block3(x)x = self.pool3(x)x = self.drop3(x)x = x.view(-1, 256 * 4 * 4)x = self.fc(x)return x# 初始化模型
model = CNN()
model = model.to(device)  # 将模型移至GPU(如果可用)
criterion = nn.CrossEntropyLoss()  # 交叉熵损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam优化器# 引入学习率调度器,在训练过程中动态调整学习率--训练初期使用较大的 LR 快速降低损失,训练后期使用较小的 LR 更精细地逼近全局最优解。
# 在每个 epoch 结束后,需要手动调用调度器来更新学习率,可以在训练过程中调用 scheduler.step()
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,        # 指定要控制的优化器(这里是Adam)mode='min',       # 监测的指标是"最小化"(如损失函数)patience=3,       # 如果连续3个epoch指标没有改善,才降低LRfactor=0.5        # 降低LR的比例(新LR = 旧LR × 0.5)
)
# 5. 训练模型(记录每个 iteration 的损失)
def train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs):model.train()  # 设置为训练模式# 记录每个 iteration 的损失all_iter_losses = []  # 存储所有 batch 的损失iter_indices = []     # 存储 iteration 序号# 记录每个 epoch 的准确率和损失train_acc_history = []test_acc_history = []train_loss_history = []test_loss_history = []# 早停相关参数best_test_acc = 0.0patience = 5  # 早停耐心值,5个epochcounter = 0   # 计数器,记录连续未改进的epoch数early_stop = False  # 早停标志for epoch in range(epochs):running_loss = 0.0correct = 0total = 0for batch_idx, (data, target) in enumerate(train_loader):data, target = data.to(device), target.to(device)  # 移至GPUoptimizer.zero_grad()  # 梯度清零output = model(data)  # 前向传播loss = criterion(output, target)  # 计算损失loss.backward()  # 反向传播optimizer.step()  # 更新参数# 记录当前 iteration 的损失iter_loss = loss.item()all_iter_losses.append(iter_loss)iter_indices.append(epoch * len(train_loader) + batch_idx + 1)# 统计准确率和损失running_loss += iter_loss_, predicted = output.max(1)total += target.size(0)correct += predicted.eq(target).sum().item()# 每100个批次打印一次训练信息if (batch_idx + 1) % 100 == 0:print(f'Epoch: {epoch+1}/{epochs} | Batch: {batch_idx+1}/{len(train_loader)} 'f'| 单Batch损失: {iter_loss:.4f} | 累计平均损失: {running_loss/(batch_idx+1):.4f}')# 计算当前epoch的平均训练损失和准确率epoch_train_loss = running_loss / len(train_loader)epoch_train_acc = 100. * correct / totaltrain_acc_history.append(epoch_train_acc)train_loss_history.append(epoch_train_loss)# 测试阶段model.eval()  # 设置为评估模式test_loss = 0correct_test = 0total_test = 0with 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()_, predicted = output.max(1)total_test += target.size(0)correct_test += predicted.eq(target).sum().item()epoch_test_loss = test_loss / len(test_loader)epoch_test_acc = 100. * correct_test / total_testtest_acc_history.append(epoch_test_acc)test_loss_history.append(epoch_test_loss)# 更新学习率调度器scheduler.step(epoch_test_loss)print(f'Epoch {epoch+1}/{epochs} 完成 | 训练准确率: {epoch_train_acc:.2f}% | 测试准确率: {epoch_test_acc:.2f}%')# 早停检查if epoch_test_acc > best_test_acc:best_test_acc = epoch_test_acccounter = 0# 保存最佳模型(可选)torch.save(model.state_dict(), 'best_model.pth')print(f"找到更好的模型,准确率: {best_test_acc:.2f}%,已保存")else:counter += 1print(f"早停计数器: {counter}/{patience}")if counter >= patience:print(f"早停触发!连续 {patience} 个epoch测试准确率未提高")early_stop = True# 如果触发早停,跳出训练循环if early_stop:print(f"训练在第 {epoch+1} 个epoch提前结束")break# 绘制所有 iteration 的损失曲线plot_iter_losses(all_iter_losses, iter_indices)# 绘制每个 epoch 的准确率和损失曲线plot_epoch_metrics(train_acc_history, test_acc_history, train_loss_history, test_loss_history)return epoch_test_acc  # 返回最终测试准确率# 6. 绘制每个 iteration 的损失曲线
def plot_iter_losses(losses, indices):plt.figure(figsize=(10, 4))plt.plot(indices, losses, 'b-', alpha=0.7, label='Iteration Loss')plt.xlabel('Iteration(Batch序号)')plt.ylabel('损失值')plt.title('每个 Iteration 的训练损失')plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 7. 绘制每个 epoch 的准确率和损失曲线
def plot_epoch_metrics(train_acc, test_acc, train_loss, test_loss):epochs = range(1, len(train_acc) + 1)plt.figure(figsize=(12, 4))# 绘制准确率曲线plt.subplot(1, 2, 1)plt.plot(epochs, train_acc, 'b-', label='训练准确率')plt.plot(epochs, test_acc, 'r-', label='测试准确率')plt.xlabel('Epoch')plt.ylabel('准确率 (%)')plt.title('训练和测试准确率')plt.legend()plt.grid(True)# 绘制损失曲线plt.subplot(1, 2, 2)plt.plot(epochs, train_loss, 'b-', label='训练损失')plt.plot(epochs, test_loss, 'r-', label='测试损失')plt.xlabel('Epoch')plt.ylabel('损失值')plt.title('训练和测试损失')plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 8. 执行训练和测试
epochs = 40  # 增加训练轮次以获得更好效果
print("开始使用CNN训练模型...")
final_accuracy = train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs)
print(f"训练完成!最终测试准确率: {final_accuracy:.2f}%")# # 保存模型
# torch.save(model.state_dict(), 'cifar10_cnn_model.pth')
# print("模型已保存为: cifar10_cnn_model.pth")

训练完成!最终测试准确率: 87.04%

@浙大疏精行 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/84737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自定义线程池 4.0

自定义线程池 4.0 1. 简介 上次我们实现了自定义线程池的 3.1 版本,提供了线程工厂创建线程和工具类创建简单线程池的功能,增强了线程池的灵活性,并且用起来更加方便了,本文我们将做如下的优化: 给线程池添加关闭的…

list is not in GROUPBY clause and contains nonaggregated column ‘*.*‘

SELECT list is not in GROUP BY clause and contains nonaggregated column mydb.t.address which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_modeonly_full_group_by 关于查询列不在分组字段内触发错误 之前我一直使用其…

Linux vmware image iso qcow2镜像大全

Download Linux VMware Images | Linux VMware Images

城市排水管网液位流量监测系统解决方案

一、方案背景 城市排水管网作为城市的“生命线”,其运行状况直接关系到城市的防洪排涝、水环境质量以及居民的生活质量。随着城市化进程的加速,城市排水管网规模不断扩大,结构日益复杂,传统的人工巡检和简单监测手段已难以满足对排…

算法学习笔记:3.广度优先搜索 (BFS)——二叉树的层序遍历

什么是广度优先搜索 (BFS)? 想象一下你在玩一个迷宫游戏,你需要找到从起点到终点的最短路径。广度优先搜索 (BFS) 就像是你在迷宫中逐层探索的过程: 先探索距离起点最近的所有位置然后探索距离起点第二近的所有位置以此类推,直到找到终点 …

并发编程-Synchronized

Mark Word 什么是Mark Word? Mark Word是Java对象头中的一个字段,它是一个32位或64位的字段(取决于系统架构),用于存储对象的元数据信息。这些信息包括对象的哈希码、锁状态、年龄等。 Mark Word有什么用&#xff1f…

【51单片机】5. 矩阵键盘与矩阵键盘密码锁Demo

1. 矩阵键盘原理 通过矩阵连接的模式,原本需要16个引脚连接的按钮只需要8个引脚就能连接好,减少了I/O口的占用。 矩阵按钮是通过扫描来读取状态的。 2. 扫描的概念 输出扫描示例:数码管扫描 原理:显示第1位→显示第2位→显示第…

Android Studio jetpack compose折叠日历日期选择器【折叠日历】

今天写一个日期选择器,大家根据自己需求改代码,记得点赞支持,谢谢~ 这是进入的默认状态 折叠状态选中本周其他日期状态 切换上下周状态 展开日历状态 切换上下月状态 选中状态 代码如下: import android.content.C…

驭码CodeRider 2.0全栈开发实战指南:从零构建现代化电商平台

驭码CodeRider 2.0全栈开发实战指南:从零构建现代化电商平台 一、CodeRider 2.0:重新定义全栈智能开发 1.1 革命性升级亮点 #mermaid-svg-AKjytNB4hD95UZtF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-AKjyt…

大模型智能体AutoGen面试题及参考答案

目录 AutoGen 的核心是什么? Agent 在 AutoGen 中承担什么角色? AutoGen 是如何定义 AssistantAgent、UserProxyAgent 等代理类型的? 什么是 GroupChat(组对话)模式? AutoGen 的 system message 在框架中扮演什么作用? 如何通过 Agent 实现自然语言处理? AutoGen…

深度学习笔记26-天气预测(Tensorflow)

🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 一、前期准备 1.数据导入 import numpy as np import pandas as pd import warnings import seaborn as sns import matplotlib.pyplot as plt warnings.filt…

day54 python对抗生成网络

目录 一、GAN对抗生成网络思想 二、实践过程 1. 数据准备 2. 构建生成器和判别器 3. 训练过程 4. 生成结果与可视化 三、学习总结 一、GAN对抗生成网络思想 GAN的核心思想非常有趣且富有对抗性。它由两部分组成:生成器(Generator)和判…

龙虎榜——20250613

上证指数放量下跌收阴线,个股下跌超4000只,受外围消息影响情绪总体较差。 深证指数放量下跌,收阴线,6月总体外围风险较高,转下跌走势的概率较大,注意风险。 2025年6月13日龙虎榜行业方向分析 1. 石油石化&…

Linux常用命令加强版替代品

Linux常用命令加强版替代品 还在日复一日地使用 ls、grep、cd 这些“上古”命令吗?是时候给你的终端来一次大升级了!本文将为你介绍一系列强大、高效且设计现代的Linux命令行工具,它们将彻底改变你的工作流,让你爱上在终端里操作…

Hadoop 003 — JAVA操作MapReduce入门案例

MapReduce入门案例-分词统计 文章目录 MapReduce入门案例-分词统计1.xml依赖2.编写MapReduce处理逻辑3.上传统计文件到HDFS3.配置MapReduce作业并测试4.执行结果 1.xml依赖 <dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-commo…

Python打卡第53天

浙大疏锦行 作业&#xff1a; 对于心脏病数据集&#xff0c;对于病人这个不平衡的样本用GAN来学习并生成病人样本&#xff0c;观察不用GAN和用GAN的F1分数差异。 import pandas as pd import numpy as np import torch import torch.nn as nn import torch.optim as optim from…

力扣-279.完全平方数

题目描述 给你一个整数 n &#xff0c;返回 和为 n 的完全平方数的最少数量 。 完全平方数 是一个整数&#xff0c;其值等于另一个整数的平方&#xff1b;换句话说&#xff0c;其值等于一个整数自乘的积。例如&#xff0c;1、4、9 和 16 都是完全平方数&#xff0c;而 3 和 1…

前端构建工具Webapck、Vite——>前沿字节开源Rspack详解——2023D2大会

Rspack 以下是针对主流构建工具&#xff08;Webpack、Vite、Rollup、esbuild&#xff09;的核心不足分析&#xff0c;以及 Rspack 如何基于这些痛点进行针对性改进 的深度解析&#xff1a; 一、主流构建工具的不足 1. Webpack&#xff1a;性能与生态的失衡 核心问题 冷启动慢…

输入法,开头输入这U I V 三个字母会不显示 任何中文

1. 汉语拼音规则的限制 汉语拼音中不存在以“V”“U”“I”为声母的情况&#xff1a; 汉语拼音的声母是辅音&#xff0c;而“V”“U”“I”在汉语拼音中都是元音&#xff08;或韵母的一部分&#xff09;。汉语拼音的声母系统中没有“V”“U”“I”作为声母的音节。例如&#xf…

Linux文件权限详解:从入门到精通

前言 权限是什么&#xff1f; 本质&#xff1a;无非就是能做和不能做什么。 为什么要有权限呢&#xff1f; 目的&#xff1a;为了控制用户行为&#xff0c;防止发生错误。 1.权限的理解 在学习下面知识之前要先知道的一点是&#xff1a;linux下一切皆文件&#xff0c;对li…