当前位置: 首页 > news >正文

DAY49 超大力王爱学Python

知识点回顾:

  1. 通道注意力模块复习
  2. 空间注意力模块
  3. CBAM的定义

最近临近毕业,事情有点多。如果有之前的基础的话,今天的难度相对较低。

后面说完几种模块提取特征的组合方式后,会提供整理的开源模块的文件。

现在大家已近可以去读这类文章了,应该已经可以无压力看懂三四区的很多这类文章。

作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
import numpy as np
import matplotlib.pyplot as plt
import os# 设置随机种子以确保结果可复现
torch.manual_seed(42)
np.random.seed(42)
torch.backends.cudnn.deterministic = True# 定义CBAM模块
class ChannelAttention(nn.Module):def __init__(self, in_channels, reduction_ratio=16):super(ChannelAttention, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.max_pool = nn.AdaptiveMaxPool2d(1)self.fc = nn.Sequential(nn.Conv2d(in_channels, in_channels // reduction_ratio, 1, bias=False),nn.ReLU(),nn.Conv2d(in_channels // reduction_ratio, in_channels, 1, bias=False))def forward(self, x):avg_out = self.fc(self.avg_pool(x))max_out = self.fc(self.max_pool(x))out = avg_out + max_outreturn torch.sigmoid(out)class SpatialAttention(nn.Module):def __init__(self, kernel_size=7):super(SpatialAttention, self).__init__()self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False)def forward(self, x):avg_out = torch.mean(x, dim=1, keepdim=True)max_out, _ = torch.max(x, dim=1, keepdim=True)out = torch.cat([avg_out, max_out], dim=1)out = self.conv(out)return torch.sigmoid(out)class CBAM(nn.Module):def __init__(self, in_channels, reduction_ratio=16, kernel_size=7):super(CBAM, self).__init__()self.channel_att = ChannelAttention(in_channels, reduction_ratio)self.spatial_att = SpatialAttention(kernel_size)def forward(self, x):x = x * self.channel_att(x)x = x * self.spatial_att(x)return x# 定义带有CBAM的CNN模型
class CBAM_CNN(nn.Module):def __init__(self, num_classes=10):super(CBAM_CNN, self).__init__()# ---------------------- 第一个卷积块(带CBAM) ----------------------self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)self.bn1 = nn.BatchNorm2d(32)  # 批归一化self.relu1 = nn.ReLU()self.pool1 = nn.MaxPool2d(kernel_size=2)self.cbam1 = CBAM(in_channels=32)  # 在第一个卷积块后添加CBAM# ---------------------- 第二个卷积块(带CBAM) ----------------------self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)self.bn2 = nn.BatchNorm2d(64)self.relu2 = nn.ReLU()self.pool2 = nn.MaxPool2d(kernel_size=2)self.cbam2 = CBAM(in_channels=64)  # 在第二个卷积块后添加CBAM# ---------------------- 第三个卷积块(带CBAM) ----------------------self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)self.bn3 = nn.BatchNorm2d(128)self.relu3 = nn.ReLU()self.pool3 = nn.MaxPool2d(kernel_size=2)self.cbam3 = CBAM(in_channels=128)  # 在第三个卷积块后添加CBAM# ---------------------- 全连接层 ----------------------self.fc1 = nn.Linear(128 * 4 * 4, 512)self.dropout = nn.Dropout(p=0.5)self.fc2 = nn.Linear(512, num_classes)def forward(self, x):# 第一个卷积块x = self.conv1(x)x = self.bn1(x)x = self.relu1(x)x = self.pool1(x)x = self.cbam1(x)  # 应用CBAM# 第二个卷积块x = self.conv2(x)x = self.bn2(x)x = self.relu2(x)x = self.pool2(x)x = self.cbam2(x)  # 应用CBAM# 第三个卷积块x = self.conv3(x)x = self.bn3(x)x = self.relu3(x)x = self.pool3(x)x = self.cbam3(x)  # 应用CBAM# 全连接层x = x.view(-1, 128 * 4 * 4)x = self.fc1(x)x = self.relu3(x)x = self.dropout(x)x = self.fc2(x)return x# 1. 数据预处理
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])# 2. 加载CIFAR-10数据集
train_dataset = datasets.CIFAR10(root='./data',train=True,download=True,transform=transform
)test_dataset = datasets.CIFAR10(root='./data',train=False,transform=transform
)# 3. 创建数据加载器
batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=4)# CIFAR-10的类别名称
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')# 检查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")# 创建TensorBoard的SummaryWriter
log_dir = 'runs/cifar10_mlp_experiment'
# 自动生成唯一目录(避免覆盖)
if os.path.exists(log_dir):i = 1while os.path.exists(f"{log_dir}_{i}"):i += 1log_dir = f"{log_dir}_{i}"# 创建日志目录并验证
os.makedirs(log_dir, exist_ok=True)
print(f"TensorBoard日志将保存在: {log_dir}")# 检查目录是否创建成功
if not os.path.exists(log_dir):raise FileNotFoundError(f"无法创建日志目录: {log_dir}")writer = SummaryWriter(log_dir)# 模型保存路径
model_save_dir = 'saved_models'
os.makedirs(model_save_dir, exist_ok=True)
best_model_path = os.path.join(model_save_dir, 'best_model.pth')
final_model_path = os.path.join(model_save_dir, 'final_model.pth')# 初始化模型并移至设备
model = CBAM_CNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', patience=3, factor=0.5)# 5. 训练模型(优化TensorBoard日志写入)
# 训练函数
def train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs, writer, best_model_path):model.train()all_iter_losses = []iter_indices = []train_acc_history = []test_acc_history = []train_loss_history = []test_loss_history = []best_accuracy = 0.0for 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)optimizer.zero_grad()output = model(data)loss = criterion(output, target)loss.backward()optimizer.step()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()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_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)# 记录训练指标到TensorBoardwriter.add_scalar('Training Loss', epoch_train_loss, epoch)writer.add_scalar('Training Accuracy', epoch_train_acc, epoch)# 测试阶段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)# 记录测试指标到TensorBoardwriter.add_scalar('Test Loss', epoch_test_loss, epoch)writer.add_scalar('Test Accuracy', epoch_test_acc, epoch)# 学习率调整scheduler.step(epoch_test_loss)# 保存最佳模型if epoch_test_acc > best_accuracy:best_accuracy = epoch_test_acctorch.save(model.state_dict(), best_model_path)print(f'在Epoch {epoch+1} 保存了最佳模型,准确率: {best_accuracy:.2f}%')print(f'Epoch {epoch+1}/{epochs} 完成 | 训练准确率: {epoch_train_acc:.2f}% | 测试准确率: {epoch_test_acc:.2f}%')# 绘制损失和准确率曲线plot_iter_losses(all_iter_losses, iter_indices)plot_epoch_metrics(train_acc_history, test_acc_history, train_loss_history, test_loss_history)# 保存最终模型torch.save(model.state_dict(), final_model_path)print(f'保存了最终模型到 {final_model_path}')# 刷新并关闭TensorBoard写入器writer.flush()writer.close()return best_accuracy# 绘图函数
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()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()# 执行训练
epochs = 50
print("开始使用带CBAM的CNN训练模型...")
final_accuracy = train(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs, writer, best_model_path)
print(f"训练完成!最佳测试准确率: {final_accuracy:.2f}%")

Files already downloaded and verified

使用设备: cuda

TensorBoard日志将保存在: runs/cifar10_mlp_experiment_3

开始使用带CBAM的CNN训练模型... Epoch: 1/50 | Batch: 100/782 | 单Batch损失: 1.5347 | 累计平均损失: 1.7286 Epoch: 1/50 | Batch: 200/782 | 单Batch损失: 1.6409 | 累计平均损失: 1.5906 Epoch: 1/50 | Batch: 300/782 | 单Batch损失: 1.2963 | 累计平均损失: 1.4923 Epoch: 1/50 | Batch: 400/782 | 单Batch损失: 1.2433 | 累计平均损失: 1.4150 Epoch: 1/50 | Batch: 500/782 | 单Batch损失: 0.9714 | 累计平均损失: 1.3561 Epoch: 1/50 | Batch: 600/782 | 单Batch损失: 1.3788 | 累计平均损失: 1.3111 Epoch: 1/50 | Batch: 700/782 | 单Batch损失: 1.1744 | 累计平均损失: 1.2702 在Epoch 1 保存了最佳模型,准确率: 63.80% Epoch 1/50 完成 | 训练准确率: 55.06% | 测试准确率: 63.80% Epoch: 2/50 | Batch: 100/782 | 单Batch损失: 0.8755 | 累计平均损失: 0.9532 Epoch: 2/50 | Batch: 200/782 | 单Batch损失: 0.9961 | 累计平均损失: 0.9275 Epoch: 2/50 | Batch: 300/782 | 单Batch损失: 0.8786 | 累计平均损失: 0.9017 Epoch: 2/50 | Batch: 400/782 | 单Batch损失: 0.8517 | 累计平均损失: 0.8855 Epoch: 2/50 | Batch: 500/782 | 单Batch损失: 0.6945 | 累计平均损失: 0.8724 Epoch: 2/50 | Batch: 600/782 | 单Batch损失: 0.9180 | 累计平均损失: 0.8587 Epoch: 2/50 | Batch: 700/782 | 单Batch损失: 0.7349 | 累计平均损失: 0.8446 在Epoch 2 保存了最佳模型,准确率: 72.18% Epoch 2/50 完成 | 训练准确率: 70.55% | 测试准确率: 72.18% Epoch: 3/50 | Batch: 100/782 | 单Batch损失: 0.8370 | 累计平均损失: 0.6600 Epoch: 3/50 | Batch: 200/782 | 单Batch损失: 0.6755 | 累计平均损失: 0.6713 Epoch: 3/50 | Batch: 300/782 | 单Batch损失: 0.7057 | 累计平均损失: 0.6630

...

Epoch: 50/50 | Batch: 500/782 | 单Batch损失: 0.0000 | 累计平均损失: 0.0000 Epoch: 50/50 | Batch: 600/782 | 单Batch损失: 0.0000 | 累计平均损失: 0.0000 Epoch: 50/50 | Batch: 700/782 | 单Batch损失: 0.0000 | 累计平均损失: 0.0000 Epoch 50/50 完成 | 训练准确率: 100.00% | 测试准确率: 79.78%

@浙大疏锦行

相关文章:

  • 网络编程(HTTP协议)
  • 讲一下进程和线程
  • 大模型笔记4:RAG检索增强生成
  • MobaXterm首次连接Ubuntu失败
  • 浏览器基础及缓存
  • 02-Timer0-Timer1-Timer2-Timer3-Timer4测试程序
  • O - 方差
  • 湖北理元理律师事务所:债务优化中如何保障债务人生存权益
  • 安装 WSL2 与设置​
  • 基于MSE-Nacos实现服务的动态发现和配置动态管理
  • mac如何使用tensorboardx?
  • Hive集成Paimon
  • 【Erdas实验教程】022:遥感图像辐射增强(直方图均衡化)
  • 【性能调优系列】如何分析火焰图
  • 计算机操作系统(计算题公式)
  • React组件通信——props
  • MyBatisPlus 全面学习路径
  • 【AI学习】【Ubuntu 22.04】【安装Ollama】两种方式
  • Spring-ai 1.0.0 学习(三)——流式调用及模型参数
  • JavaScript学习笔记
  • 培训web网站开发/如何建立电商平台
  • 市政府门户网站建设/哈尔滨关键词排名工具
  • 潍坊网站建设最新报价/重庆网站建设软件
  • 上海做网站的公司多少钱/百度网盘人工客服电话多少
  • 中国佛山手机网站建设/南京谷歌seo
  • b赣州网站建设/网页制作费用大概多少