【day 50】预训练模型

@浙大疏锦行

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}") # 数据预处理(与原代码一致) 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)
import torch import torchvision.models as models from torchinfo import summary #之前的内容说了,推荐用他来可视化模型结构,信息最全 # 加载 ResNet18(预训练) model = models.resnet18(pretrained=True) model.eval() # 输出模型结构和参数概要 summary(model, input_size=(1, 3, 224, 224))

import torch import torch.nn as nn from torchvision import models # 自定义ResNet18模型,插入CBAM模块 class ResNet18_CBAM(nn.Module): def __init__(self, num_classes=10, pretrained=True, cbam_ratio=16, cbam_kernel=7): super().__init__() # 加载预训练ResNet18 self.backbone = models.resnet18(pretrained=pretrained) # 修改首层卷积以适应32x32输入(CIFAR10) self.backbone.conv1 = nn.Conv2d( in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1, bias=False ) self.backbone.maxpool = nn.Identity() # 移除原始MaxPool层(因输入尺寸小) # 在每个残差块组后添加CBAM模块 self.cbam_layer1 = CBAM(in_channels=64, ratio=cbam_ratio, kernel_size=cbam_kernel) self.cbam_layer2 = CBAM(in_channels=128, ratio=cbam_ratio, kernel_size=cbam_kernel) self.cbam_layer3 = CBAM(in_channels=256, ratio=cbam_ratio, kernel_size=cbam_kernel) self.cbam_layer4 = CBAM(in_channels=512, ratio=cbam_ratio, kernel_size=cbam_kernel) # 修改分类头 self.backbone.fc = nn.Linear(in_features=512, out_features=num_classes) def forward(self, x): # 主干特征提取 x = self.backbone.conv1(x) x = self.backbone.bn1(x) x = self.backbone.relu(x) # [B, 64, 32, 32] # 第一层残差块 + CBAM x = self.backbone.layer1(x) # [B, 64, 32, 32] x = self.cbam_layer1(x) # 第二层残差块 + CBAM x = self.backbone.layer2(x) # [B, 128, 16, 16] x = self.cbam_layer2(x) # 第三层残差块 + CBAM x = self.backbone.layer3(x) # [B, 256, 8, 8] x = self.cbam_layer3(x) # 第四层残差块 + CBAM x = self.backbone.layer4(x) # [B, 512, 4, 4] x = self.cbam_layer4(x) # 全局平均池化 + 分类 x = self.backbone.avgpool(x) # [B, 512, 1, 1] x = torch.flatten(x, 1) # [B, 512] x = self.backbone.fc(x) # [B, 10] return x # 初始化模型并移至设备 model = ResNet18_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)
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 = 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:训练注意力模块和分类头**\n" + "="*50) set_trainable_layers(model, ["cbam", "backbone.fc"]) optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=1e-3) elif epoch == 6: print("\n" + "="*50 + "\n✈️ **阶段 2:解冻高层卷积层 (layer3, layer4)**\n" + "="*50) set_trainable_layers(model, ["cbam", "backbone.fc", "backbone.layer3", "backbone.layer4"]) 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 = True optimizer = optim.Adam(model.parameters(), lr=1e-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(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 / 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_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(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 # ====================================================================== # 5. 绘图函数定义 # ====================================================================== 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 = ResNet18_CBAM().to(device) criterion = nn.CrossEntropyLoss() epochs = 50 print("开始使用带分阶段微调策略的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.mzph.cn/news/1169104.shtml

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

相关文章

矩阵方程求解

图片来自《鸢尾花书4矩阵力量》这张图在讲一件很核心、很“机器学习/线性代数”风格的事:把“两个方程”打包成一个矩阵方程 Axb,然后用逆矩阵 A⁻ 一步解出未知量 x。我按图里的顺序,用最通俗的方式解释一遍。1)左边:…

力扣刷题之路

在算法刷题中,“思路的迭代” 往往比 “写出代码” 更有价值 —— 从暴力遍历到贪心、从递归到迭代、从局部最优到全局最优,每一步优化都体现了算法思维的进阶。本文以 LeetCode 中 3 道经典题(岛屿面积、反转链表、分发糖果)为例…

【day 52】神经网络调参指南

浙大疏锦行 import torch import torch.nn as nn# 定义简单的线性模型(无隐藏层) # 输入2个纬度的数据,得到1个纬度的输出 class SimpleNet(nn.Module):def __init__(self):super(SimpleNet, self).__init__()# 线性层:2个输入特…

西门子 S7 - 200 SMART 与台达变频器 485 通讯实现触摸屏控制

西门子s7 200smart与台达变频器485通讯 目标:用触摸屏和西门子smart 控制变频器通讯 器件:西门子s7 200 smart PLC,台达VFD-M变频器,昆仑通态触摸屏(带以太网),中途可以加路由器 控制方式:触摸屏与plc以太网…

Java毕设项目推荐-基于SpringBoot+vue的保护动物公益救助交流活动平台基于SpringBoot濒危物种公益救助交流平台【附源码+文档,调试定制服务】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

收藏级!大模型核心架构与底层原理全解析,小白程序员入门必看

当下,生成式大模型正以颠覆性态势席卷全球科技领域,一场围绕“模型主导未来”的产业竞争已全面铺开。对于深耕IT行业的从业者而言,这场技术浪潮绝非单纯的迭代升级,更在悄然重塑整个技术生态——过去依赖独立软件实现功能的传统模…

定时任务简单源码思路手撕实现

定时任务简单源码思路手撕实现 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.locks.LockSupport;public class ScheduleService {Trigger trigger …

Java swing mysql实现的酒店管理系统_javswing酒店管理系统mysql,零基础入门到精通,收藏这篇就够了

1、散客开单:完成散客的开单,可一次最多开5间相同类型的房间。 2、团体开单:完成团体的开单,开放数量没有限制,可同时开不同类型的房间。 3、宾客结帐:自动统计每个登记客人在店时所发生的消费额和应付款额…

没加 FOR UPDATE 也会加锁吗?真相来了!

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!很多开发者有个误区:“只有写了 SELECT ... FOR UPDATE 才会加锁,普通的 UPDATE 不会加锁。”这是完全错误的!今天我们就用 Spring Boot MySQL(…

Commons-io工具包与Hutool工具包

Commons-io Commons-io是apache开源基金组织提供的一组有关IO操作的开源工具包 作用:提高I0流的开发效率。 FileUtils类(文件/文件夹相关) static void copyFile(File srcFile,File destFile) 复制文件 static void copyDirectory(File srcDir,File destDir) 复制文件夹 stat…

TRO 基于扩散模型的轮椅共享控制用户意图估计研究

在智能轮椅的辅助导航中,如何在保障安全的同时尊重用户的自主意愿,一直是人机交互领域的核心难题。传统的意图预测方法往往试图给出唯一的“标准答案”,这容易在复杂环境中引发误判。本文介绍了一种名为 DIWIE(基于扩散模型的轮椅…

MySQL性能优化:从底层原理到实战落地的全维度方案

在数据驱动的业务场景中,MySQL作为主流开源关系型数据库,其性能直接决定系统响应速度、吞吐量与运维成本。尤其对于高并发、大数据量的平台(如DeepSeek这类AI服务场景),慢查询与不合理索引设计可能引发系统卡顿甚至雪崩…

【课程设计/毕业设计】基于SpringBoot保护濒危野生动物公益救助交流平台基于SpringBoot濒危物种公益救助交流平台【附源码、数据库、万字文档】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

JVM 里的逻辑漏洞,居然让你的哈希表慢了 20%!

首先来看一段 Java 代码&#xff1a; int sumMapElements(ConcurrentHashMap<Integer, Integer> map) {int sum 0;Enumeration<Integer> it map.elements();while (it.hasMoreElements()) {sum (int) it.nextElement();}return sum; } 函数 sumMapElements 使…

构建智能Agent的三大支柱:上下文工程、会话管理与记忆系统

Google白皮书系统阐述了构建有状态LLM智能体的核心方法——上下文工程。通过上下文工程、会话管理和记忆系统三大支柱&#xff0c;文章详细介绍了如何突破LLM无状态限制&#xff0c;实现智能体的记忆、学习和个性化交互能力。通过动态组装相关信息、管理会话状态和持久化关键记…

收藏备用!AI+多领域变革全解析:大模型如何重塑产业生态

本文深度拆解“AI”在医疗、金融、制造等核心领域的颠覆性变革&#xff0c;结合大模型应用实例&#xff0c;具象化展现人工智能如何重构行业运行逻辑与生态格局。从医疗健康领域“治未病”的主动防控&#xff0c;到金融行业“数字神经系统”的智能风控&#xff0c;从制造业向“…

收藏备用|RAG技术架构三阶段演进全解析(从入门到进阶,小白也能懂)

RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09;作为大语言模型&#xff08;LLM&#xff09;落地垂直领域的核心支撑技术&#xff0c;其核心价值在于为LLM“外挂”可定制化专属知识库&#xff0c;通过“检索外部信息→精准辅助生成”的闭环…

毕业论文通关秘籍:宏智树 AI 教你避开 80% 写作坑

作为深耕论文写作科普的教育博主&#xff0c;每年毕业季后台都会被各种论文难题刷屏&#xff1a;“选题太老被导师驳回怎么办&#xff1f;”“文献综述写得像流水账怎么救&#xff1f;”“查重率降不下来&#xff0c;越改越乱咋整&#xff1f;” 毕业论文写作&#xff0c;就像一…

AI 写论文哪个软件最好?实测封神!宏智树 AI 堪称毕业论文通关外挂

作为深耕论文写作科普的教育测评博主&#xff0c;后台每天都被毕业生的灵魂拷问刷屏&#xff1a;“AI 写论文工具琳琅满目&#xff0c;到底哪款能真正解决选题难、文献杂、数据空、查重高的痛点&#xff1f;” 市面上的 AI 写作软件分为三个梯队&#xff1a;文字生成器只会简单…

写论文软件哪个好?实测宏智树 AI:毕业论文的全流程效率神器

作为深耕论文写作科普的教育测评博主&#xff0c;每年毕业季后台都会被 “写论文软件哪个好” 的提问刷屏。不少同学踩坑无数&#xff1a;有的工具生成内容空洞无物&#xff0c;有的文献引用漏洞百出&#xff0c;有的查重结果与学校标准脱节。经过多轮深度实测&#xff0c;宏智…