python学习打卡day45

news2025/6/7 11:53:58
DAY 45 Tensorboard使用介绍

知识点回顾:

  1. tensorboard的发展历史和原理
  2. tensorboard的常见操作
  3. tensorboard在cifar上的实战:MLP和CNN模型

效果展示如下,很适合拿去组会汇报撑页数:

作业:对resnet18在cifar10上采用微调策略下,用tensorboard监控训练过程。

PS:

  1. tensorboard和torch版本存在一定的不兼容性,如果报错请新建环境尝试。
  2. tensorboard的代码还有有一定的记忆量,实际上深度学习的经典代码都是类似于八股文,看多了就习惯了,难度远远小于考研数学等需要思考的内容
  3. 实际上对目前的ai而言,你只需要先完成最简单的demo,然后让他给你加上tensorboard需要打印的部分即可。---核心是弄懂tensorboard可以打印什么信息,以及如何看可视化后的结果,把ai当成记忆大师用到的时候通过它来调取对应的代码即可。
    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
    from torch.utils.tensorboard import SummaryWriter
    import os
    import torchvision
    # 设置中文字体支持
    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.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))
    ])
    
    # 2. 加载CIFAR-10数据集
    train_dataset = datasets.CIFAR10(
        root='./data',
        train=True,
        download=True,
        transform=train_transform
    )
    
    test_dataset = datasets.CIFAR10(
        root='./data',
        train=False,
        transform=test_transform
    )
    
    # 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)
    
    log_dir = "runs/cifar10_resnet18_exp"
    if os.path.exists(log_dir):
        version = 1
        while os.path.exists(f"{log_dir}_v{version}"):
            version += 1
        log_dir = f"{log_dir}_v{version}"
    writer = SummaryWriter(log_dir)
    
    # 4. 定义ResNet18模型
    def create_resnet18(pretrained=True, num_classes=10):
        model = models.resnet18(pretrained=pretrained)
        
        # 修改最后一层全连接层
        in_features = model.fc.in_features
        model.fc = nn.Linear(in_features, num_classes)
        
        return model.to(device)
    
    # 5. 冻结/解冻模型层的函数
    def freeze_model(model, freeze=True):
        """冻结或解冻模型的卷积层参数"""
        # 冻结/解冻除fc层外的所有参数
        for name, param in model.named_parameters():
            if 'fc' not in name:
                param.requires_grad = not freeze
        
        # 打印冻结状态
        frozen_params = sum(p.numel() for p in model.parameters() if not p.requires_grad)
        total_params = sum(p.numel() for p in model.parameters())
        
        if freeze:
            print(f"已冻结模型卷积层参数 ({frozen_params}/{total_params} 参数)")
        else:
            print(f"已解冻模型所有参数 ({total_params}/{total_params} 参数可训练)")
        
        return model
    
    # 6. 训练函数(支持阶段式训练)
    def train_with_freeze_schedule(model, train_loader, test_loader, criterion, optimizer, scheduler, device, epochs, freeze_epochs=5):
        """
        前freeze_epochs轮冻结卷积层,之后解冻所有层进行训练
        """
        train_loss_history = []
        test_loss_history = []
        train_acc_history = []
        test_acc_history = []
        all_iter_losses = []
        iter_indices = []
        global_step=0
        # 初始冻结卷积层
        if freeze_epochs > 0:
            model = freeze_model(model, freeze=True)
        
        for epoch in range(epochs):
            # 解冻控制:在指定轮次后解冻所有层
            if epoch == freeze_epochs:
                model = freeze_model(model, freeze=False)
                # 解冻后调整优化器(可选)
                optimizer.param_groups[0]['lr'] = 1e-4  # 降低学习率防止过拟合
            
            model.train()  # 设置为训练模式
            running_loss = 0.0
            correct_train = 0
            total_train = 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 * len(train_loader) + batch_idx + 1)
                
                # 统计训练指标
                running_loss += iter_loss
                _, predicted = output.max(1)
                total_train += target.size(0)
                correct_train += predicted.eq(target).sum().item()
    
                # ======================== TensorBoard 标量记录 ========================
                # 记录每个 batch 的损失、准确率
                batch_acc = 100. * correct_train / total_train
                writer.add_scalar('Train/Batch Loss', iter_loss, global_step)
                writer.add_scalar('Train/Batch Accuracy', batch_acc, global_step)
                # 记录学习率(可选)
                writer.add_scalar('Train/Learning Rate', optimizer.param_groups[0]['lr'], global_step)
                # 每 200 个 batch 记录一次参数直方图
                if (batch_idx + 1) % 200 == 0:
                    for name, param in model.named_parameters():
                        writer.add_histogram(f'Weights/{name}', param, global_step)
                        if param.grad is not None:
                            writer.add_histogram(f'Gradients/{name}', param.grad, global_step)
    
                global_step += 1
    
                
                # 每100批次打印进度
                if (batch_idx + 1) % 100 == 0:
                    print(f"Epoch {epoch+1}/{epochs} | Batch {batch_idx+1}/{len(train_loader)} "
                          f"| 单Batch损失: {iter_loss:.4f}")
            
            # 计算 epoch 级指标
            epoch_train_loss = running_loss / len(train_loader)
            epoch_train_acc = 100. * correct_train / total_train
    
            # ======================== TensorBoard  epoch 标量记录 ========================
            writer.add_scalar('Train/Epoch Loss', epoch_train_loss, epoch)
            writer.add_scalar('Train/Epoch Accuracy', epoch_train_acc, epoch)
    
            
            # 测试阶段
            model.eval()
            correct_test = 0
            total_test = 0
            test_loss = 0.0
            
            wrong_images = []  # 存储错误预测样本(用于可视化)
            wrong_labels = []
            wrong_preds = []
            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()
                    # 收集错误预测样本(用于可视化)
                    wrong_mask = (predicted != target)
                    if wrong_mask.sum() > 0:
                        wrong_batch_images = data[wrong_mask][:8].cpu()  # 最多存8张
                        wrong_batch_labels = target[wrong_mask][:8].cpu()
                        wrong_batch_preds = predicted[wrong_mask][:8].cpu()
                        wrong_images.extend(wrong_batch_images)
                        wrong_labels.extend(wrong_batch_labels)
                        wrong_preds.extend(wrong_batch_preds)
    
            
            epoch_test_loss = test_loss / len(test_loader)
            epoch_test_acc = 100. * correct_test / total_test
    
            # ======================== TensorBoard 测试集记录 ========================
            writer.add_scalar('Test/Epoch Loss', epoch_test_loss, epoch)
            writer.add_scalar('Test/Epoch Accuracy', epoch_test_acc, epoch)
    
            
            # 记录历史数据
            train_loss_history.append(epoch_train_loss)
            test_loss_history.append(epoch_test_loss)
            train_acc_history.append(epoch_train_acc)
            test_acc_history.append(epoch_test_acc)
            # 可视化错误预测样本
            if wrong_images:
                wrong_img_grid = torchvision.utils.make_grid(wrong_images)
                writer.add_image('错误预测样本', wrong_img_grid, epoch)
                wrong_text = [f"真实: {classes[wl]}, 预测: {classes[wp]}" 
                             for wl, wp in zip(wrong_labels, wrong_preds)]
                writer.add_text('错误预测标签', '\n'.join(wrong_text), epoch)
            # 更新学习率调度器
            scheduler.step(epoch_test_loss)
            print(f'Epoch {epoch+1}/{epochs} 完成 | 测试准确率: {epoch_test_acc:.2f}%')
    
        writer.close()
        return epoch_test_acc
    # (可选)CIFAR-10 类别名
    classes = ('plane', 'car', 'bird', 'cat',
               'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    
    # 主函数:训练模型
    def main():
        # 参数设置
        epochs = 30  # 总训练轮次
        freeze_epochs = 5  # 冻结卷积层的轮次
        learning_rate = 1e-3  # 初始学习率
        weight_decay = 1e-4  # 权重衰减
        
        # 创建ResNet18模型(加载预训练权重)
        model = create_resnet18(pretrained=True, num_classes=10)
        
        # 定义优化器和损失函数
        optimizer = optim.Adam(model.parameters(), lr=learning_rate, weight_decay=weight_decay)
        criterion = nn.CrossEntropyLoss()
        
        # 定义学习率调度器
        scheduler = optim.lr_scheduler.ReduceLROnPlateau(
            optimizer, mode='min', factor=0.5, patience=2
        )
        
        # 开始训练(前5轮冻结卷积层,之后解冻)
        final_accuracy = train_with_freeze_schedule(
            model=model,
            train_loader=train_loader,
            test_loader=test_loader,
            criterion=criterion,
            optimizer=optimizer,
            scheduler=scheduler,
            device=device,
            epochs=epochs,
            freeze_epochs=freeze_epochs
        )
        
        print(f"训练完成!最终测试准确率: {final_accuracy:.2f}%")
        print("训练后执行: tensorboard --logdir=runs 查看可视化")
        # # 保存模型
        # torch.save(model.state_dict(), 'resnet18_cifar10_finetuned.pth')
        # print("模型已保存至: resnet18_cifar10_finetuned.pth")
    
    if __name__ == "__main__":
        main()

部分结果图像展示 

 

@浙大疏锦行 

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

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

相关文章

Verilog编程技巧01——如何编写三段式状态机

前言 Verilog编程技巧系列文章将聚焦于介绍Verilog的各种编程范式或者说技巧,编程技巧和编程规范有部分重合,但并非完全一样。规范更注重编码的格式,像变量命名、缩进、注释风格等,而编程技巧则更偏重更直观易读、更便于维护、综合…

智启未来:当知识库遇见莫奈的调色盘——API工作流重构企业服务美学

目录 引言 一、初识蓝耘元生代MaaS平台 1.1 平台架构 1.2 平台的优势 1.3 应用场景 二、手把手教你如何在蓝耘进行注册 (1)输入手机号,将验证码正确填入即可快速完成注册 (2)进入下面的页面表示已经成功注册&…

如何在 Windows 11 中永久更改默认浏览器:阻止 Edge 占据主导地位

在 Windows 11 中更改默认浏览器对于新手或技术不太熟练的用户来说可能会令人沮丧。 为什么要在 Windows 11 中更改默认浏览器? 这是一个重要的问题:你为什么要从 Microsoft Edge 切换过来? 生态系统集成:如果你已经在广泛使用 Google 服务,Chrome 可以提供无缝集成。同…

量子比特实现方式

经典计算机是通过电子电路运转起来的。使用硅制半导体制成的名为晶体管的小元件发挥了开关的作用,将其与金属布线组合起来即可实现逻辑门,再将逻辑门集成起来就能制造出经典计算机。量子计算机的制造过程则要复杂许多,因为量子计算机既需要量…

智慧水务发展迅猛:从物联网架构到AIoT系统的跨越式升级

AI大模型引领智慧水务迈入新纪元 2025年5月25日,水利部自主研发的“水利标准AI大模型”正式发布,它标志着水务行业智能化进程的重大突破。该模型集成1800余项水利标准、500余项法规及海量科研数据,支持立项、编制、审查等全流程智能管理&…

Java高级 | 【实验五】Spring boot+mybatis操作数据库

隶书文章:Java高级 | (二十二)Java常用类库-CSDN博客 系列文章:Java高级 | 【实验一】Springboot安装及测试 |最新-CSDN博客 Java高级 | 【实验二】Springboot 控制器类相关注解知识-CSDN博客 Java高级 | 【实验三】Springboot 静…

在MATLAB中使用自定义的ROS2消息

简明结论: 无论ROS2节点和MATLAB运行在哪,MATLAB本机都必须拥有自定义消息源码并本地用ros2genmsg生成,才能在Simulink里订阅这些消息。只要你想让MATLAB或Simulink能识别自定义消息,必须把消息包源码(.msg等)拷到本机指定目录&a…

【MATLAB去噪算法】基于ICEEMDAN联合小波阈值去噪算法

ICEEMDAN联合小波阈值去噪算法相关文献 (注:目前相关论文较少,应用该套代码可发直接一些水刊) 一、CEEMDAN的局限性 模式残留噪声问题:原始CEEMDAN在计算每个IMF时直接对噪声扰动的信号进行模态分解并平均。 后果&a…

XXTEA,XTEA与TEA

TEA、XTEA和XXTEA都是分组加密算法,它们在设计、安全性、性能等方面存在显著区别。以下是它们的主要区别: 密钥长度 TEA:使用128位密钥。 XTEA:通常使用128位或256位密钥。 XXTEA:密钥长度更灵活,可以使用任…

机器人玩转之---嵌入式开发板基础知识到实战选型指南(包含ORIN、RDK X5、Raspberry pi、RK系列等)

1. 基础知识讲解 1.1 什么是嵌入式开发板? 嵌入式开发板是一种专门设计用于嵌入式系统开发的硬件平台,它集成了微处理器、内存、存储、输入输出接口等核心组件于单块印刷电路板上。与传统的PC不同,嵌入式开发板具有体积小、功耗低、成本适中…

腾讯云国际版和国内版账户通用吗?一样吗?为什么?

在当今全球化的数字化时代,云计算服务成为众多企业和个人拓展业务、存储数据的重要选择。腾讯云作为国内领先的云服务提供商,其国际版和国内版备受关注。那么,腾讯云国际版和国内版账户是否通用?它们究竟一样吗?背后又…

OrCAD X Capture CIS设计小诀窍系列第二季--03.如何在Capture中输出带有目录和元器件信息的PDF

背景介绍:我们在进行原理图设计时,经常需要输出PDF来查看或评审,但通过”Print”功能导出的PDF较为简单,只能查看设计视图;而通过使用Ghostscript软件可以输出带有目录和元器件信息的PDF,让设计师可以直接在…

汽车的安全性能测试:试验台铁地板的重要性

汽车的安全性能测试是非常重要的,其中试验台铁地板的设计和材料选择起着至关重要的作用。试验台铁地板是指在进行汽车碰撞、侧翻等试验时,用于支撑汽车底部和提供稳定支撑的重要部件。 在进行汽车碰撞试验时,试验台铁地板的设计和材料需要具…

实践指南:从零开始搭建RAG驱动的智能问答系统

LLM 赋能的最强大的应用之一是复杂的问答 (Q&A) 聊天机器人。这些是可以回答关于特定来源信息问题的应用程序。这些应用程序使用一种称为检索增强生成的技术,或 RAG。本文将展示如何基于 LangChain 构建一个简单的基于非结构化数据文本数据源的问答应用程序。 温…

边缘计算服务器

边缘计算服务器的核心要点解析,综合技术架构、应用场景与部署方案: 一、核心定义与技术特性‌ 本质定位‌ 部署在网络边缘侧的专用计算设备(如工厂车间、智慧路灯等),直接处理终端设备(传感器、摄像头等…

第R9周:阿尔茨海默病诊断(优化特征选择版)

文章目录 1. 导入数据2. 数据处理2.1 患病占比2.2 相关性分析2.3 年龄与患病探究 3. 特征选择4. 构建数据集4.1 数据集划分与标准化4.2 构建加载 5. 构建模型6. 模型训练6.1 构建训练函数6.2 构建测试函数6.3 设置超参数 7. 模型训练8. 模型评估8.1 结果图 8.2 混淆矩阵9. 总结…

电动螺丝刀-多实体拆图建模案例

多实体建模要注意下面两点: 多实体建模的合并结果一定要谨慎在实际工作中多实体建模是一个非常好的思路,先做产品的整体设计,再将个体零件导出去做局部细节设计 电动螺丝刀模型动图展示 爆炸视图动图展示 案例素材点击此处获取 建模步骤 1. …

当丰收季遇上超导磁测量:粮食产业的科技新征程

麦浪藏光阴,心田种丰年!又到了一年中最令人心潮澎湃的粮食丰收季。金色的麦浪随风翻滚,沉甸甸的稻穗谦逊地低垂着,处处洋溢着丰收的喜悦。粮食产业,无疑是国家发展的根基与命脉,是民生稳定的压舱石。在现代…

电子电气架构 --- 什么是功能架构?

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

AudioRelay 0.27.5 手机充当电脑音响

—————【下 载 地 址】——————— 【​本章下载一】:https://pan.xunlei.com/s/VOS4MvfPxrnfS2Zu_YS4egykA1?pwdi2we# 【​本章下载二】:https://pan.xunlei.com/s/VOS4MvfPxrnfS2Zu_YS4egykA1?pwdi2we# 【百款黑科技】:https://uc…