Python训练打卡Day43

news2025/6/9 14:58:08

复习日

1.卷积神经网络的基本概念

2.kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化

进阶:并拆分成多个文件

tips:注册kaggle的注意事项

安装插件:Header Editor

然后打开扩展选项:

输入网址:https://www.azurezeng.com/static/HE-GoogleRedirect.json

导入保存即可,刷新注册页面完成注册。

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms, models
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
import torch.nn.functional as F
# 设置随机种子确保结果可复现
torch.manual_seed(42)
np.random.seed(42)
# 设置中文字体支持
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}")
# 1. 数据预处理
# 训练集:使用多种数据增强方法提高模型泛化能力
train_transform = transforms.Compose([
    # 新增:调整图像大小为统一尺寸
    transforms.Resize((32, 32)),  # 确保所有图像都是32x32像素
    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.485, 0.456, 0.406), (0.229, 0.224, 0.225))])
# 测试集:仅进行必要的标准化,保持数据原始特性
test_transform = transforms.Compose([
    # 新增:调整图像大小为统一尺寸
    transforms.Resize((32, 32)),  # 确保所有图像都是32x32像素
    transforms.ToTensor(),
    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
])
# 定义数据集根目录
root = r'day43'
train_dataset = datasets.ImageFolder(
    root=root + '/training_set',  # 指向 train 子文件夹
    transform=train_transform
)
test_dataset = datasets.ImageFolder(
    root=root + '/test_set',  # 指向 test 子文件夹
    transform=test_transform
)
# 打印类别信息,确认数据加载正确
print(f"训练集类别: {train_dataset.classes}")
print(f"测试集类别: {test_dataset.classes}")
# 3. 创建数据加载器
batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# 定义一个简单的CNN模型
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        # 第一个卷积层,输入通道为3(彩色图像),输出通道为32,卷积核大小为3x3,填充为1以保持图像尺寸不变
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
        # 第二个卷积层,输入通道为32,输出通道为64,卷积核大小为3x3,填充为1
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        # 第三个卷积层,输入通道为64,输出通道为128,卷积核大小为3x3,填充为1
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
        # 最大池化层,池化核大小为2x2,步长为2,用于下采样,减少数据量并提取主要特征
        self.pool = nn.MaxPool2d(2, 2)
        # 第一个全连接层,输入特征数为128 * 4 * 4(经过前面卷积和池化后的特征维度),输出为512
        self.fc1 = nn.Linear(128 * 4 * 4, 512)
        # 第二个全连接层,输入为512,输出为2(对应猫和非猫两个类别)
        self.fc2 = nn.Linear(512, 2)
    def forward(self, x):
        # 第一个卷积层后接ReLU激活函数和最大池化操作,经过池化后图像尺寸变为原来的一半,这里输出尺寸变为16x16
        x = self.pool(F.relu(self.conv1(x)))
        # 第二个卷积层后接ReLU激活函数和最大池化操作,输出尺寸变为8x8
        x = self.pool(F.relu(self.conv2(x)))
        # 第三个卷积层后接ReLU激活函数和最大池化操作,输出尺寸变为4x4
        x = self.pool(F.relu(self.conv3(x)))
        # 将特征图展平为一维向量,以便输入到全连接层
        x = x.view(-1, 128 * 4 * 4)
        # 第一个全连接层后接ReLU激活函数
        x = F.relu(self.fc1(x))
        # 第二个全连接层输出分类结果
        x = self.fc2(x)
        return x
# 初始化模型
model = SimpleCNN()
print("模型已创建")
# 如果有GPU则使用GPU,将模型转移到对应的设备上
model = model.to(device)
# 训练模型
def train_model(model, train_loader, test_loader, epochs=20):
    # 定义损失函数为交叉熵损失,用于分类任务
    criterion = nn.CrossEntropyLoss()
    # 定义优化器为Adam,用于更新模型参数,学习率设置为0.001
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
 
    for epoch in range(epochs):
        # 训练阶段
        model.train()
        running_loss = 0.0
        correct = 0
        total = 0
 
        for i, data in enumerate(train_loader, 0):
            # 从数据加载器中获取图像和标签
            inputs, labels = data
            # 将图像和标签转移到对应的设备(GPU或CPU)上
            inputs, labels = inputs.to(device), labels.to(device)
            # 清空梯度,避免梯度累加
            optimizer.zero_grad()
            # 模型前向传播得到输出
            outputs = model(inputs)
            # 计算损失
            loss = criterion(outputs, labels)
            # 反向传播计算梯度
            loss.backward()
            # 更新模型参数
            optimizer.step()
 
            running_loss += loss.item()
            _, predicted = outputs.max(1)
            total += labels.size(0)
            correct += predicted.eq(labels).sum().item()
 
        # 测试阶段
        model.eval()
        test_loss = 0
        correct = 0
        total = 0
        with torch.no_grad():
            for data in test_loader:
                images, labels = data
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)
                test_loss += criterion(outputs, labels).item()
                _, predicted = outputs.max(1)
                total += labels.size(0)
                correct += predicted.eq(labels).sum().item()
        print(f'测试集 [{epoch + 1}] 损失: {test_loss/len(test_loader):.3f} | 准确率: {100.*correct/total:.2f}%')
    print("训练完成")
    return model
# 训练模型
try:
    # 尝试加载预训练模型(如果存在)
    model.load_state_dict(torch.load('cat_classifier.pth'))
    print("已加载预训练模型")
except:
    print("无法加载预训练模型,训练新模型")
    model = train_model(model, train_loader, test_loader, epochs=10)
    # 保存训练后的模型参数
    torch.save(model.state_dict(), 'cat_classifier.pth')
# 设置模型为评估模式
model.eval()
# Grad-CAM实现
class GradCAM:
    def __init__(self, model, target_layer):
        self.model = model
        self.target_layer = target_layer
        self.gradients = None
        self.activations = None
        # 注册钩子,用于获取目标层的前向传播输出和反向传播梯度
        self.register_hooks()
    def register_hooks(self):
        # 前向钩子函数,在目标层前向传播后被调用,保存目标层的输出(激活值)
        def forward_hook(module, input, output):
            self.activations = output.detach()
        # 反向钩子函数,在目标层反向传播后被调用,保存目标层的梯度
        def backward_hook(module, grad_input, grad_output):
            self.gradients = grad_output[0].detach()
        # 在目标层注册前向钩子和反向钩子
        self.target_layer.register_forward_hook(forward_hook)
        self.target_layer.register_backward_hook(backward_hook)
    def generate_cam(self, input_image, target_class=None):
        # 前向传播,得到模型输出
        model_output = self.model(input_image)
        if target_class is None:
            # 如果未指定目标类别,则取模型预测概率最大的类别作为目标类别
            target_class = torch.argmax(model_output, dim=1).item()
        # 清除模型梯度,避免之前的梯度影响
        self.model.zero_grad()
        # 反向传播,构造one-hot向量,使得目标类别对应的梯度为1,其余为0,然后进行反向传播计算梯度
        one_hot = torch.zeros_like(model_output)
        one_hot[0, target_class] = 1
        model_output.backward(gradient=one_hot)
        # 获取之前保存的目标层的梯度和激活值
        gradients = self.gradients
        activations = self.activations
        # 对梯度进行全局平均池化,得到每个通道的权重,用于衡量每个通道的重要性
        weights = torch.mean(gradients, dim=(2, 3), keepdim=True)
        # 加权激活映射,将权重与激活值相乘并求和,得到类激活映射的初步结果
        cam = torch.sum(weights * activations, dim=1, keepdim=True)
        # ReLU激活,只保留对目标类别有正贡献的区域,去除负贡献的影响
        cam = F.relu(cam)
        # 调整大小并归一化,将类激活映射调整为与输入图像相同的尺寸(32x32),并归一化到[0, 1]范围
        cam = F.interpolate(cam, size=(32, 32), mode='bilinear', align_corners=False)
        cam = cam - cam.min()
        cam = cam / cam.max() if cam.max() > 0 else cam
        return cam.cpu().squeeze().numpy(), target_class
# 可视化Grad-CAM结果的函数
import warnings
warnings.filterwarnings("ignore")
import matplotlib.pyplot as plt
# 设置中文字体支持
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
# 选择一个随机图像
# idx = np.random.randint(len(test_dataset))
idx = 50  # 选择测试集中的第49张图片 (索引从0开始)
image, label = test_dataset[idx]
print(f"选择的图像类别: {test_dataset.classes[label]}")
# 转换图像以便可视化
def tensor_to_np(tensor):
    img = tensor.cpu().numpy().transpose(1, 2, 0)
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    img = std * img + mean
    img = np.clip(img, 0, 1)
    return img
# 添加批次维度并移动到设备
input_tensor = image.unsqueeze(0).to(device)
# 初始化Grad-CAM(选择最后一个卷积层)
grad_cam = GradCAM(model, model.conv3)
# 生成热力图
heatmap, pred_class = grad_cam.generate_cam(input_tensor)
# 可视化
plt.figure(figsize=(12, 4))
# 原始图像
plt.subplot(1, 3, 1)
plt.imshow(tensor_to_np(image))
plt.title(f"原始图像: {test_dataset.classes[label]}")
plt.axis('off')
# 热力图
plt.subplot(1, 3, 2)
plt.imshow(heatmap, cmap='jet')
plt.title(f"Grad-CAM热力图: {test_dataset.classes[pred_class]}")
plt.axis('off')
# 叠加的图像
plt.subplot(1, 3, 3)
img = tensor_to_np(image)
heatmap_resized = np.uint8(255 * heatmap)
heatmap_colored = plt.cm.jet(heatmap_resized)[:, :, :3]
superimposed_img = heatmap_colored * 0.4 + img * 0.6
plt.imshow(superimposed_img)
plt.title("叠加热力图")
plt.axis('off')
plt.tight_layout()
plt.show()

@浙大疏锦行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2405493.html

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

相关文章

227.2018年蓝桥杯国赛 - 交换次数(中等)- 贪心

227. 交换次数(贪心) 1. 2018年蓝桥杯国赛 - 交换次数(中等) 标签:2018 暴力 国赛 1.1 题目描述 IT 产业人才需求节节攀升。业内巨头百度、阿里巴巴、腾讯(简称 BAT )在某海滩进行招聘活动。…

STM32入门学习之系统时钟配置

1. 时钟就是单片机的心脏。单片机根据时钟频率来控制每个部件的工作,时钟是单片机的脉搏,决定了每条命令运行的速率,没有时钟单片机将停止工作。 如何理解“时钟决定了单片机每条命令运行的速率”? 首先需要去理解单片机中的时…

【ArcGIS Pro微课1000例】0072:如何自动保存编辑内容及保存工程?

文章目录 一、自动保存编辑内容二、自动保存工程在使用ArcGIS或者ArcGIS Pro时,经常会遇到以下报错,无论点击【发送报告】,还是【不发送】,软件都会强制退出,这时如果对所操作没有保存,就会前功尽弃。 此时,自动保存工作就显得尤为重要,接下来讲解两种常见的自动保存方…

AU音频软件|Audition 2025网盘下载与安装教程指南

说起AU,有些小伙伴可能第一印象是化学元素金(Aurum)。实际上,本文要介绍的AU,全称是Adobe Audition,是一款专业音频编辑和混音软件‌,广泛应用于音乐制作、广播、电影及视频声音设计等领域。 目…

网络编程(TCP编程)

思维导图 1.基础流程 流程图中是TCP连接的基础步骤&#xff0c;其他操作都是在此基础上进行添加修改。 2.函数接口 2.1 创建套接字&#xff08;socket&#xff09; int socket(int domain, int type, int protocol); 头文件&#xff1a;#include <sys/types.h> …

热成像实例分割电力设备数据集(3类,838张)

在现代电力系统的运维管理中&#xff0c;红外热成像已经成为检测设备隐患、预防故障的重要手段。相比传统可见光图像&#xff0c;红外图像可揭示设备温度分布&#xff0c;从而更直观地反映过热、老化等问题。而在AI赋能下&#xff0c;通过实例分割技术对热成像中的电力设备进行…

用电脑通过USB总线连接控制keysight示波器

通过USB总线控制示波器的优势 在上篇文章我介绍了如何通过网线远程连接keysight示波器&#xff0c;如果连接的距离不是很远&#xff0c;也可以通过USB线将示波器与电脑连接起来&#xff0c;实现对示波器的控制和截图。 在KEYSIGHT示波器DSOX1204A的后端&#xff0c;除了有网口…

uni-app学习笔记二十四--showLoading和showModal的用法

showLoading(OBJECT) 显示 loading 提示框, 需主动调用 uni.hideLoading 才能关闭提示框。 OBJECT参数说明 参数类型必填说明平台差异说明titleString是提示的文字内容&#xff0c;显示在loading的下方maskBoolean否是否显示透明蒙层&#xff0c;防止触摸穿透&#xff0c;默…

【Linux】centos软件安装

目录 Linux下安装软件的办法什么是yum使用yum试着安装软件查看yum源配置额外的第三方库 Linux下安装软件的办法 做为一个操作系统&#xff0c;与win和mac一样&#xff0c;安装软件无可厚非。那Linux下安装软件有哪些办法呢&#xff1f;第一种是直接下载源代码本地编译安装&…

基于Vue3.0的在线工具网站

文章目录 1、初始化项目1.1 创建项目1.2 安装vue路由1.3 安装UI库2、首页搭建2.0 页面布局2.1 页头2.2 侧边栏2.3 内容显示区域3、字符串加密解密功能实现3.1 页面构建3.2 实现加密/解密4、Json工具4.1 Json格式化4.1.1 搭建页面4.1.2 实现Json格式化4.2 Json转XML4.1.1 搭建页…

STM32H562----------串口通信(UART)

1、串口介绍 1.1、 数据通信概念 在单片机中我们常用的通信方式有 USART、IIC、SPI、CAN、USB 等; 1、数据通信方式 根据数据通信方式可分为串行通信和并行通信两种,如下图: 串行通信基本特征是数据逐位顺序依次传输,优点:传输线少成本低,抗干扰能力强可用于远距离传…

webpack其余配置

webpack搭建本地服务器 首先是要安装一个webpack-dev-server npm install webpack-dev-server -D 安装后在package.json中添加&#xff1a; {"name": "babel_core_demo","version": "1.0.0","main": "index.js"…

【CUDA 】第5章 共享内存和常量内存——5.3减少全局内存访问(2)

CUDA C编程笔记 第五章 共享内存和常量内存5.3 减少全局内存访问5.3.2 使用展开的并行规约思路reduceSmemUnroll4&#xff08;共享内存&#xff09;具体代码&#xff1a;运行结果意外发现书上全局加载事务和全局存储事务和ncu中这两个值相同 5.3.3 动态共享内存的并行规约reduc…

Python 训练营打卡 Day 46

通道注意力 一、什么是注意力 注意力机制是一种让模型学会「选择性关注重要信息」的特征提取器&#xff0c;就像人类视觉会自动忽略背景&#xff0c;聚焦于图片中的主体&#xff08;如猫、汽车&#xff09;。 transformer中的叫做自注意力机制&#xff0c;他是一种自己学习自…

Rust学习(1)

声明&#xff1a;学习来源于 《Rust 圣经》 变量的绑定和解构 变量绑定 let a "hello world":这个过程称之为变量绑定。绑定就是把这个对象绑定给一个变量&#xff0c;让这个变量成为它的主人。 变量可变性 Rust 变量默认情况下不可变&#xff0c;可以通过 mut …

鸿蒙仓颉语言开发实战教程:商城应用个人中心页面

又到了高考的日子&#xff0c;幽蓝君在这里祝各位考生朋友冷静答题&#xff0c;超常发挥。 今天要分享的内容是仓颉语言商城应用的个人中心页面&#xff0c;先看效果图&#xff1a; 下面介绍下这个页面的实现过程。 我们可以先分析下整个页面的布局结构。可以看出它是纵向的布…

智能生成完整 Java 后端架构,告别手动编写 ControllerServiceDao

在 Java 后端开发的漫长征途上&#xff0c;开发者们常常深陷繁琐的基础代码编写泥潭。尤其是 Controller、Service、Dao 这三层代码的手动编写&#xff0c;堪称开发效率的 “拦路虎”。从搭建项目骨架到填充业务逻辑&#xff0c;每一个环节都需要开发者投入大量精力&#xff0c…

Python----目标检测(yolov5-7.0安装及训练细胞)

一、下载项目代码 yolov5代码源 GitHub - ultralytics/yolov5: YOLOv5 &#x1f680; in PyTorch > ONNX > CoreML > TFLite yolov5-7.0代码源 Release v7.0 - YOLOv5 SOTA Realtime Instance Segmentation ultralytics/yolov5 GitHub 二、创建虚拟环境 创建一个3.8…

【Linux】文件赋权(指定文件所有者、所属组)、挂载光驱(图文教程)

文章目录 文件赋权创建文件 testChmod查看文件的当前权限使用 chmod 命令修改权限验证权限关键命令总结答案汇总 光驱挂载确认文件是否存在打包压缩压缩验证创建 work 目录将压缩文件复制到 work 目录新建挂载点 /MNT/CDROM 并挂载光驱答案汇总 更多相关内容可查看 此篇用以解决…

第22讲、Odoo18 QWeb 模板引擎详解

Odoo QWeb 模板引擎详解与实战 Odoo 的 QWeb 是其自研的模板引擎&#xff0c;广泛应用于 HTML、XML、PDF 等内容的生成&#xff0c;支撑了前端页面渲染、报表输出、门户页面、邮件模板等多种场景。本文将系统介绍 QWeb 的核心用法、工作原理&#xff0c;并通过实战案例演示如何…