2026/5/24 4:42:36
网站建设
项目流程
手机网站怎么做优化,黄山网络推广哪家好,网站建设价格多少,网络营销分类# DAY 44 预训练模型CBAM 模块
知识点回顾#xff1a;
1. resnet结构解析
2. CBAM 放置位置的思考
3. 针对预训练模型的训练策略 a. 差异化学学习率 b. 三阶段微调
作业:
1. 好好理解下 resnet18 的模型结构
2. 尝试对 vgg16cbam 进行微调策略
# 1. 环境准备与库…# DAY 44 预训练模型CBAM 模块知识点回顾1. resnet结构解析2. CBAM 放置位置的思考3. 针对预训练模型的训练策略a. 差异化学学习率b. 三阶段微调作业:1. 好好理解下 resnet18 的模型结构2. 尝试对 vgg16cbam 进行微调策略# 1. 环境准备与库导入 import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms from torch.utils.data import DataLoader import matplotlib.pyplot as plt import numpy as np import time # 设置中文字体 plt.rcParams[font.family] [SimHei] plt.rcParams[axes.unicode_minus] False # 设备配置 device torch.device(cuda if torch.cuda.is_available() else cpu) print(f使用设备: {device}) # 2. CBAM模块定义复用经典实现 class ChannelAttention(nn.Module): def __init__(self, in_channels, ratio16): super().__init__() self.avg_pool nn.AdaptiveAvgPool2d(1) self.max_pool nn.AdaptiveMaxPool2d(1) self.fc nn.Sequential( nn.Linear(in_channels, in_channels // ratio, biasFalse), nn.ReLU(), nn.Linear(in_channels // ratio, in_channels, biasFalse) ) self.sigmoid nn.Sigmoid() def forward(self, x): 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)) attention self.sigmoid(avg_out max_out).view(b, c, 1, 1) return x * attention class SpatialAttention(nn.Module): def __init__(self, kernel_size7): super().__init__() self.conv nn.Conv2d(2, 1, kernel_size, paddingkernel_size//2, biasFalse) self.sigmoid nn.Sigmoid() def forward(self, x): avg_out torch.mean(x, dim1, keepdimTrue) max_out, _ torch.max(x, dim1, keepdimTrue) pool_out torch.cat([avg_out, max_out], dim1) attention self.conv(pool_out) return x * self.sigmoid(attention) class CBAM(nn.Module): def __init__(self, in_channels, ratio16, kernel_size7): 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 # 3. VGG16CBAM模型构建 class VGG16_CBAM(nn.Module): def __init__(self, num_classes10): super().__init__() # 加载预训练VGG16去掉分类头 vgg16_pretrained torchvision.models.vgg16(pretrainedTrue) self.features vgg16_pretrained.features # VGG16特征提取层 # 在VGG16的5个卷积块后插入CBAM适配VGG16的features结构 # VGG16 features结构block1(0-4), block2(5-9), block3(10-16), block4(17-23), block5(24-30) self.cbam1 CBAM(in_channels64) # block1输出通道64 self.cbam2 CBAM(in_channels128) # block2输出通道128 self.cbam3 CBAM(in_channels256) # block3输出通道256 self.cbam4 CBAM(in_channels512) # block4输出通道512 self.cbam5 CBAM(in_channels512) # block5输出通道512 # 替换VGG16的分类头适配CIFAR10的10分类 self.classifier nn.Sequential( nn.Linear(512 * 1 * 1, 4096), # CIFAR10经VGG16 features后尺寸为1x1 nn.ReLU(True), nn.Dropout(), nn.Linear(4096, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, num_classes), ) def forward(self, x): # 前向传播VGG16卷积块 对应CBAM x self.features[:5](x) # block1 x self.cbam1(x) x self.features[5:10](x) # block2 x self.cbam2(x) x self.features[10:17](x) # block3 x self.cbam3(x) x self.features[17:24](x) # block4 x self.cbam4(x) x self.features[24:](x) # block5 x self.cbam5(x) # 展平分类头 x torch.flatten(x, 1) x self.classifier(x) return x # 4. 分阶段微调核心函数 def set_trainable_layers(model, trainable_parts): 冻结所有层仅解冻包含trainable_parts关键词的层 print(f\n--- 解冻以下部分并设为可训练: {trainable_parts}) for name, param in model.named_parameters(): param.requires_grad False # 先全冻结 for part in trainable_parts: if part in name: param.requires_grad True break def train_staged_finetuning(model, criterion, train_loader, test_loader, device, epochs): optimizer None # 初始化历史记录 all_iter_losses, iter_indices [], [] train_acc_history, test_acc_history [], [] train_loss_history, test_loss_history [], [] for epoch in range(1, epochs 1): epoch_start_time time.time() # --- 分阶段调整冻结层和学习率 --- if epoch 1: print(\n *50 \n **阶段 1训练CBAM模块和分类头**\n *50) # 解冻CBAMcbam1-cbam5和分类头classifier set_trainable_layers(model, [cbam, classifier]) optimizer optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr1e-3) elif epoch 6: print(\n *50 \n✈️ **阶段 2解冻VGG16高层卷积features.24:**\n *50) # 解冻CBAM 分类头 VGG16 block5features.24后 set_trainable_layers(model, [cbam, classifier, features.24, features.25, features.26, features.27, features.28, features.29, features.30]) optimizer optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr1e-4) elif epoch 21: print(\n *50 \n️ **阶段 3解冻所有层全局微调**\n *50) # 解冻所有层 for param in model.parameters(): param.requires_grad True optimizer optim.Adam(model.parameters(), lr1e-5) # --- 训练循环 --- model.train() running_loss, correct, total 0.0, 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() # 记录每个iteration的损失 iter_loss loss.item() all_iter_losses.append(iter_loss) iter_indices.append((epoch - 1) * 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个batch打印一次 if (batch_idx 1) % 100 0: print(fEpoch: {epoch}/{epochs} | Batch: {batch_idx1}/{len(train_loader)} f| 单Batch损失: {iter_loss:.4f} | 累计平均损失: {running_loss/(batch_idx1):.4f}) # 计算epoch级训练指标 epoch_train_loss running_loss / len(train_loader) epoch_train_acc 100. * correct / total train_loss_history.append(epoch_train_loss) train_acc_history.append(epoch_train_acc) # --- 测试循环 --- model.eval() test_loss, correct_test, total_test 0, 0, 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() _, predicted output.max(1) total_test target.size(0) correct_test predicted.eq(target).sum().item() # 计算epoch级测试指标 epoch_test_loss test_loss / len(test_loader) epoch_test_acc 100. * correct_test / total_test test_loss_history.append(epoch_test_loss) test_acc_history.append(epoch_test_acc) # 打印epoch结果 print(fEpoch {epoch}/{epochs} 完成 | 耗时: {time.time() - epoch_start_time:.2f}s | 训练准确率: {epoch_train_acc:.2f}% | 测试准确率: {epoch_test_acc:.2f}%) # 训练结束绘图 print(\n训练完成! 开始绘制结果图表...) plot_iter_losses(all_iter_losses, iter_indices) plot_epoch_metrics(train_acc_history, test_acc_history, train_loss_history, test_loss_history) return epoch_test_acc # 5. 可视化函数 def plot_iter_losses(losses, indices): plt.figure(figsize(10, 4)) plt.plot(indices, losses, b-, alpha0.7, labelIteration Loss) plt.xlabel(IterationBatch序号) 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() # 6. 数据加载CIFAR10 # 数据预处理适配VGG16的输入要求 transform_train transforms.Compose([ transforms.Resize((224, 224)), # VGG16默认输入224x224 transforms.RandomHorizontalFlip(), transforms.RandomCrop(224, padding4), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), # ImageNet归一化 ]) transform_test transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) # 加载CIFAR10数据集 train_dataset torchvision.datasets.CIFAR10(root./data, trainTrue, downloadTrue, transformtransform_train) test_dataset torchvision.datasets.CIFAR10(root./data, trainFalse, transformtransform_test) train_loader DataLoader(train_dataset, batch_size32, shuffleTrue, num_workers2) test_loader DataLoader(test_dataset, batch_size32, shuffleFalse, num_workers2) # 7. 执行训练 if __name__ __main__: # 初始化模型 model VGG16_CBAM(num_classes10).to(device) criterion nn.CrossEntropyLoss() epochs 50 # 开始分阶段微调 print(开始使用带分阶段微调策略的VGG16CBAM模型进行训练...) final_accuracy train_staged_finetuning(model, criterion, train_loader, test_loader, device, epochs) print(f训练完成最终测试准确率: {final_accuracy:.2f}%) # 保存模型可选 # torch.save(model.state_dict(), vgg16_cbam_finetuned.pth) # print(模型已保存为: vgg16_cbam_finetuned.pth)浙大疏锦行