学校网站建设是什么意思,芜湖市建设办网站,个人帮企业做网站,wordpress动图知识点回顾#xff1a; resnet结构解析CBAM放置位置的思考针对预训练模型的训练策略 差异化学习率三阶段微调 作业#xff1a; 好好理解下resnet18的模型结构尝试对vgg16cbam进行微调策略 import time
import torch
import torch.nn as nn
import torch.optim as optim
impo… 知识点回顾 resnet结构解析CBAM放置位置的思考针对预训练模型的训练策略 差异化学习率三阶段微调 作业 好好理解下resnet18的模型结构尝试对vgg16cbam进行微调策略 import time
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter # 新增TensorBoard导入# VGG16CBAM模型实现
class VGGBlock(nn.Module):def __init__(self, in_channels, out_channels, num_convs, use_cbamTrue):super(VGGBlock, self).__init__()layers []for _ in range(num_convs):layers.append(nn.Conv2d(in_channels, out_channels, kernel_size3, padding1))layers.append(nn.BatchNorm2d(out_channels))layers.append(nn.ReLU(inplaceTrue))in_channels out_channelsif use_cbam:layers.append(CBAM(out_channels))layers.append(nn.MaxPool2d(kernel_size2, stride2))self.block nn.Sequential(*layers)def forward(self, x):return self.block(x)# CBAM模块实现与之前相同
class ChannelAttention(nn.Module):def __init__(self, in_channels, reduction_ratio16):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, biasFalse),nn.ReLU(),nn.Conv2d(in_channels // reduction_ratio, in_channels, 1, biasFalse))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_size7):super(SpatialAttention, self).__init__()self.conv nn.Conv2d(2, 1, kernel_size, paddingkernel_size//2, biasFalse)def forward(self, x):avg_out torch.mean(x, dim1, keepdimTrue)max_out, _ torch.max(x, dim1, keepdimTrue)out torch.cat([avg_out, max_out], dim1)out self.conv(out)return torch.sigmoid(out)class CBAM(nn.Module):def __init__(self, in_channels, reduction_ratio16, kernel_size7):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 xclass VGG16_CBAM(nn.Module):def __init__(self, num_classes10, init_weightsTrue):super(VGG16_CBAM, self).__init__()# VGG16的配置每段表示[卷积层数, 输出通道数]cfg [[2, 64, True], # 第一段2个卷积层64通道使用CBAM[2, 128, True], # 第二段2个卷积层128通道使用CBAM[3, 256, True], # 第三段3个卷积层256通道使用CBAM[3, 512, True], # 第四段3个卷积层512通道使用CBAM[3, 512, False] # 第五段3个卷积层512通道不使用CBAM为了性能考虑]self.features self._make_layers(cfg)self.avgpool nn.AdaptiveAvgPool2d((7, 7))self.classifier nn.Sequential(nn.Linear(512 * 7 * 7, 4096),nn.ReLU(True),nn.Dropout(),nn.Linear(4096, 4096),nn.ReLU(True),nn.Dropout(),nn.Linear(4096, num_classes),)if init_weights:self._initialize_weights()def _make_layers(self, cfg):layers []in_channels 3for num_convs, out_channels, use_cbam in cfg:layers.append(VGGBlock(in_channels, out_channels, num_convs, use_cbam))in_channels out_channelsreturn nn.Sequential(*layers)def forward(self, x):x self.features(x)x self.avgpool(x)x torch.flatten(x, 1)x self.classifier(x)return xdef _initialize_weights(self):for m in self.modules():if isinstance(m, nn.Conv2d):nn.init.kaiming_normal_(m.weight, modefan_out, nonlinearityrelu)if m.bias is not None:nn.init.constant_(m.bias, 0)elif isinstance(m, nn.BatchNorm2d):nn.init.constant_(m.weight, 1)nn.init.constant_(m.bias, 0)elif isinstance(m, nn.Linear):nn.init.normal_(m.weight, 0, 0.01)nn.init.constant_(m.bias, 0)#
# 4. 结合了分阶段策略和详细打印的训练函数
#
def set_trainable_layers(model, trainable_parts):print(f\n--- 解冻以下部分并设为可训练: {trainable_parts})for name, param in model.named_parameters():param.requires_grad Falsefor part in trainable_parts:if part in name:param.requires_grad Truebreakdef train_staged_finetuning(model, criterion, train_loader, test_loader, device, epochs, writer):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)set_trainable_layers(model, [cbam, classifier])optimizer optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr1e-3)writer.add_scalar(learning_rate, 1e-3, epoch) # 记录学习率elif epoch 6:print(\n *50 \n✈️ **阶段 2解冻后两段卷积层 (block4, block5)**\n *50)set_trainable_layers(model, [cbam, classifier, features.3, features.4])optimizer optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr1e-4)writer.add_scalar(learning_rate, 1e-4, epoch) # 记录学习率elif epoch 21:print(\n *50 \n️ **阶段 3解冻所有层进行全局微调**\n *50)for param in model.parameters(): param.requires_grad Trueoptimizer optim.Adam(model.parameters(), lr1e-5)writer.add_scalar(learning_rate, 1e-5, epoch) # 记录学习率# --- 训练循环 ---model.train()running_loss, correct, total 0.0, 0, 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()# 记录每个iteration的损失iter_loss loss.item()all_iter_losses.append(iter_loss)iter_indices.append((epoch - 1) * len(train_loader) batch_idx 1)# 向TensorBoard添加迭代损失global_step (epoch - 1) * len(train_loader) batch_idx 1writer.add_scalar(train/iter_loss, iter_loss, global_step)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_train_loss running_loss / len(train_loader)epoch_train_acc 100. * correct / totaltrain_loss_history.append(epoch_train_loss)train_acc_history.append(epoch_train_acc)# 向TensorBoard添加epoch级训练指标writer.add_scalar(train/loss, epoch_train_loss, epoch)writer.add_scalar(train/accuracy, epoch_train_acc, epoch)# --- 测试循环 ---model.eval()test_loss, correct_test, total_test 0, 0, 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_loss_history.append(epoch_test_loss)test_acc_history.append(epoch_test_acc)# 向TensorBoard添加epoch级测试指标writer.add_scalar(test/loss, epoch_test_loss, epoch)writer.add_scalar(test/accuracy, epoch_test_acc, epoch)# 打印每个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()#
# 7. 数据加载和预处理
#
def load_data():# 数据预处理train_transform transforms.Compose([transforms.RandomResizedCrop(224),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])test_transform transforms.Compose([transforms.Resize(256),transforms.CenterCrop(224),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])# 加载数据集以CIFAR10为例train_dataset datasets.CIFAR10(root./data, trainTrue,downloadTrue, transformtrain_transform)test_dataset datasets.CIFAR10(root./data, trainFalse,downloadTrue, transformtest_transform)# 创建数据加载器train_loader DataLoader(train_dataset, batch_size32, shuffleTrue, num_workers4)test_loader DataLoader(test_dataset, batch_size32, shuffleFalse, num_workers4)return train_loader, test_loader#
# 6. 执行训练
#
if __name__ __main__:# 设置设备device torch.device(cuda if torch.cuda.is_available() else cpu)print(f使用设备: {device})# 初始化TensorBoard日志记录器自动生成带时间戳的日志目录writer SummaryWriter()# 加载数据train_loader, test_loader load_data()# 创建模型model VGG16_CBAM().to(device)# 记录模型结构需要提供一个输入样例input_sample torch.randn(1, 3, 224, 224).to(device)writer.add_graph(model, input_sample)criterion nn.CrossEntropyLoss()epochs 50print(开始使用带分阶段微调策略的VGG16CBAM模型进行训练...)final_accuracy train_staged_finetuning(model, criterion, train_loader, test_loader, device, epochs, writer)print(f训练完成最终测试准确率: {final_accuracy:.2f}%)# 关闭TensorBoard日志记录器writer.close()# torch.save(model.state_dict(), vgg16_cbam_finetuned.pth)# print(模型已保存为: vgg16_cbam_finetuned.pth)
浙大疏锦行