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

网站建设品牌好app推广接单

网站建设品牌好,app推广接单,有没有在家做的兼职网站,佛山微信网站建设DAY 50 预训练模型CBAM模块 知识点回顾: resnet结构解析CBAM放置位置的思考针对预训练模型的训练策略 差异化学习率三阶段微调 ps:今日的代码训练时长较长,3080ti大概需要40min的训练时长 作业: 好好理解下resnet18的模型结构尝试…

DAY 50 预训练模型+CBAM模块

知识点回顾:

  1. resnet结构解析
  2. CBAM放置位置的思考
  3. 针对预训练模型的训练策略
    1. 差异化学习率
    2. 三阶段微调

ps:今日的代码训练时长较长,3080ti大概需要40min的训练时长

作业:

  1. 好好理解下resnet18的模型结构
  2. 尝试对vgg16+cbam进行微调策略

1.CBMA定义

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 ximport 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}")# 数据预处理(与原代码一致)
train_transform = transforms.Compose([transforms.RandomCrop(32, padding=4),transforms.RandomHorizontalFlip(),transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),transforms.RandomRotation(15),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))
])# 加载数据集(与原代码一致)
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=train_transform)
test_dataset = datasets.CIFAR10(root='./data', train=False, transform=test_transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

2.VGG16模型结构

VGG16 的模型结构如下2:

 
  1. 输入层:输入图片的尺寸(imagenet)是 224×224×3,即彩色图像,通道为 3。
  2. 第一层卷积层
    • 卷积:使用 64 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 224×224×64。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 卷积:使用 64 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 224×224×64。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 池化:使用 2×2,stride=2 的池化单元进行最大池化操作,输出为 112×112×64。
  3. 第二层卷积层
    • 卷积:输入是 112×112×64,使用 128 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 112×112×128。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 卷积:输入是 112×112×128,使用 128 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 112×112×128。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 池化:使用 2×2,stride=2 的池化单元进行最大池化操作,输出为 56×56×128。
  4. 第三层卷积层
    • 卷积:输入是 56×56×128,使用 256 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 56×56×256。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 卷积:输入是 56×56×256,使用 256 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 56×56×256。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 卷积:输入是 56×56×256,使用 256 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 56×56×256。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 池化:使用 2×2,stride=2 的池化单元进行最大池化操作,输出为 28×28×256。
  5. 第四层卷积层
    • 卷积:输入是 28×28×256,使用 512 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 28×28×512。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 卷积:输入是 28×28×512,使用 512 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 28×28×512。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 卷积:输入是 28×28×512,使用 512 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 28×28×512。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 池化:使用 2×2,stride=2 的池化单元进行最大池化操作,输出为 14×14×512。
  6. 第五层卷积层
    • 卷积:输入是 14×14×512,使用 512 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 14×14×512。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 卷积:输入是 14×14×512,使用 512 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 14×14×512。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 卷积:输入是 14×14×512,使用 512 个 3×3 的卷积核进行卷积,padding=1,stride=1,输出是 14×14×512。
    • ReLU:将卷积层输出的 FeatureMap 输入到 ReLU 函数中。
    • 池化:使用 2×2,stride=2 的池化单元进行最大池化操作,输出为 7×7×512。
  7. 全连接层
    • FC-4096:第一个全连接层,包含 4096 个神经元(工程上的经验)。
    • FC-4096:第二个全连接层,包含 4096 个神经元。
    • FC-1000:第三个全连接层,包含 1000 个神经元,用于输出分类结果。

3.VGG16_CBAM的定义

class VGG16_CBAM(nn.Module):def __init__(self, num_classes=10, pretrained=True, cbam_ratio=16, cbam_kernel=7):super().__init__()# 加载预训练VGG16vgg16 = models.vgg16(pretrained=pretrained)# 提取特征部分self.features = vgg16.features# 修改首层卷积以适应32x32输入(CIFAR10)self.features[0] = nn.Conv2d(3, 64, kernel_size=3, padding=1)# 在每个最大池化层后添加CBAM模块self.cbam1 = CBAM(in_channels=64, ratio=cbam_ratio, kernel_size=cbam_kernel)self.cbam2 = CBAM(in_channels=128, ratio=cbam_ratio, kernel_size=cbam_kernel)self.cbam3 = CBAM(in_channels=256, ratio=cbam_ratio, kernel_size=cbam_kernel)self.cbam4 = CBAM(in_channels=512, ratio=cbam_ratio, kernel_size=cbam_kernel)self.cbam5 = CBAM(in_channels=512, ratio=cbam_ratio, kernel_size=cbam_kernel)# 分类部分self.classifier = nn.Sequential(nn.Linear(512 * 1 * 1, 4096),  # 因为输入尺寸为32x32,经过多次下采样后变为1x1nn.ReLU(True),nn.Dropout(),nn.Linear(4096, 4096),nn.ReLU(True),nn.Dropout(0.5),nn.Linear(4096, num_classes),)def forward(self, x):# 第一组卷积 + 池化 + CBAMx = self.features[:5](x)  # 到第一个MaxPool2dx = self.cbam1(x)# 第二组卷积 + 池化 + CBAMx = self.features[5:10](x)  # 到第二个MaxPool2dx = self.cbam2(x)# 第三组卷积 + 池化 + CBAMx = self.features[10:17](x)  # 到第三个MaxPool2dx = self.cbam3(x)# 第四组卷积 + 池化 + CBAMx = self.features[17:24](x)  # 到第四个MaxPool2dx = self.cbam4(x)# 第五组卷积 + 池化 + CBAMx = self.features[24:31](x)  # 到第五个MaxPool2dx = self.cbam5(x)# 全局平均池化x = nn.AdaptiveAvgPool2d((1, 1))(x)# 展平并分类x = torch.flatten(x, 1)x = self.classifier(x)return x
# 初始化模型并移至设备
model = VGG16_CBAM().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)

在每一组卷积后+CBAM模块

4.冻结和微调策略

3阶段解冻策略:

  • 阶段 1:epoch=1 时,解冻注意力模块 (cbam) 和分类头 (classifier),使用较高的学习率 (1e-3)
  • 阶段 2:epoch=6 时,解冻高层特征提取层 (features.24 及之后),学习率降低 (1e-4)
  • 阶段 3:epoch=21 时,解冻所有层,进行全局微调,学习率进一步降低 (1e-5)
  • 阶段解冻时机(epoch)解冻模块学习率代码对应逻辑
    阶段 11cbam、classifier1e-3if epoch == 1分支,调用set_trainable_layers并设置优化器
    阶段 26新增 features.24 及之后的高层卷积层1e-4elif epoch == 6分支,扩展解冻范围并降低学习率
    阶段 321所有层1e-5elif epoch == 21分支,设置param.requires_grad = True并进一步降低学习率
import time# ======================================================================
# 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):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:解冻注意力模块和分类头**\n" + "="*50)set_trainable_layers(model, ["cbam", "classifier"])optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=1e-3)elif epoch == 6:print("\n" + "="*50 + "\n✈️ **阶段 2:解冻高层特征提取层 (features.24及之后)**\n" + "="*50)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()), lr=1e-4)elif epoch == 21:print("\n" + "="*50 + "\n🛰️ **阶段 3:解冻所有层,进行全局微调**\n" + "="*50)for param in model.parameters(): param.requires_grad = Trueoptimizer = optim.Adam(model.parameters(), lr=1e-5)# --- 训练循环 ---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)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(f'Epoch: {epoch}/{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_loss_history.append(epoch_train_loss)train_acc_history.append(epoch_train_acc)# --- 测试循环 ---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)# 打印每个epoch的最终结果print(f'Epoch {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# ======================================================================
# 3. 绘图函数定义
# ======================================================================
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()# ======================================================================
# 6. 执行训练
# ======================================================================
model = VGG16_CBAM().to(device)
criterion = nn.CrossEntropyLoss()
epochs = 50print("开始使用带分阶段微调策略的ResNet18+CBAM模型进行训练...")
final_accuracy = train_staged_finetuning(model, criterion, train_loader, test_loader, device, epochs)
print(f"训练完成!最终测试准确率: {final_accuracy:.2f}%")# torch.save(model.state_dict(), 'resnet18_cbam_finetuned.pth')
# print("模型已保存为: resnet18_cbam_finetuned.pth")

@浙大疏锦行

http://www.dtcms.com/wzjs/312642.html

相关文章:

  • 上海定制化网站开发公司网络营销推广难做吗
  • 跑步机 东莞网站建设网络营销策划书ppt
  • 广水网站定制西安网站建设公司排行榜
  • 秦皇岛网站团队企业文化的重要性和意义
  • 商城网站开发平台旺道seo软件
  • 做网站包括图片设计吗百度有人工客服吗
  • 安全狗网站白名单指什么建立企业网站步骤
  • 中国建设银行官网站大连最好的做网站的公司
  • 网站数据没有更新百度平台推广联系方式
  • 长沙哪家公司做网站网站自动推广软件
  • wordpress文章内容编辑器seo系统
  • 如何制作购物网站高级搜索百度
  • 南京网站建设公司 w推广官网
  • 自己有网站怎么赚钱免费的网站推广
  • 企业年金可以取出来吗广州网站优化页面
  • 荆门哪里有专门做企业网站的快速排名精灵
  • 济南 网站建设公司 医疗优化网站排名费用
  • 不用写代码做网站软件创建网址快捷方式
  • wordpress做app下载文件网站编辑seo
  • php做网站框架seo是什么职业
  • php网站开发工程师待遇郑州厉害的seo顾问
  • 企业网站模板下载网址网络营销策略分析报告
  • 南京电子商务网站建设营销推广公司案例
  • 盛泽做网站百度知道官网
  • 网店美工的工作内容是什么网站关键词优化教程
  • 如东住房和城乡建设局网站快速优化系统
  • 洛阳住房和城乡建设部网站seo学习网站
  • WordPress二维码动态图片seo的搜索排名影响因素主要有
  • 网站做百度推广多少钱宣传软文怎么写
  • 做直播大秀的平台和网站seo推广优化方案