使用 PyTorch 实现 ZFNet 进行 MNIST 图像分类
在本篇博客中,我们将通过两个主要部分来演示如何使用 PyTorch 实现 ZFNet,并在 MNIST 数据集上进行训练和测试。ZFNet(ZFNet)是基于卷积神经网络(CNN)的图像分类模型,广泛用于图像识别任务。
环境准备
在开始之前,请确保你的环境已经安装了以下依赖:
pip install torch torchvision matplotlib tqdm
一、训练部分:训练 ZFNet 模型
首先,我们需要准备训练数据、定义 ZFNet 模型,并进行模型训练。
1. 数据加载与预处理
MNIST 数据集由 28x28 的手写数字图像组成。我们将通过 torchvision.datasets 来加载数据,并进行必要的预处理。
import torch
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
from zfnet import ZFNet # 假设 ZFNet 定义在 zfnet.py 文件中
from tqdm import tqdm # 导入 tqdm
from torch.cuda.amp import autocast, GradScaler # 导入混合精度训练def prepare_data(batch_size=128, num_workers=2, data_dir='D:/workspace/data'):"""准备 MNIST 数据集并返回数据加载器:param batch_size: 批处理大小:param num_workers: 数据加载的工作线程数:param data_dir: 数据存储的目录:return: 训练数据加载器"""transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,)) # 正则化])trainset = datasets.MNIST(root=data_dir, train=True, download=True, transform=transform)trainloader = DataLoader(trainset, batch_size=batch_size, shuffle=True, pin_memory=True, num_workers=num_workers)return trainloader
2. 初始化模型与优化器
在这里,我们将初始化模型和优化器。我们选择 Adam 优化器,并且为提高计算效率,我们采用混合精度训练。
def initialize_device():"""初始化计算设备(GPU 或 CPU):return: 计算设备"""device = torch.device("cuda" if torch.cuda.is_available() else "cpu")print(f"Using device: {device}")return devicedef initialize_model(device):"""初始化模型并移动到指定设备:param device: 计算设备:return: 初始化好的模型"""model = ZFNet().to(device) # 假设 ZFNet 是自定义模型return modeldef initialize_optimizer(model, lr=0.001):"""初始化优化器:param model: 需要优化的模型:param lr: 学习率:return: 优化器"""optimizer = optim.Adam(model.parameters(), lr=lr)return optimizer
3. 训练模型
使用训练数据进行训练,并且每训练一个 epoch 就更新一次进度条,同时使用混合精度训练来提高效率。
def train_model(model, trainloader, criterion, optimizer, num_epochs=5, device='cuda'):"""训练模型:param model: 训练的模型:param trainloader: 数据加载器:param criterion: 损失函数:param optimizer: 优化器:param num_epochs: 训练的轮数:param device: 计算设备"""scaler = GradScaler() # 用于自动缩放梯度for epoch in range(num_epochs):model.train()running_loss = 0.0# 使用 tqdm 包裹 DataLoader 来显示进度条with tqdm(trainloader, unit="batch", desc=f"Epoch {epoch + 1}/{num_epochs}") as tepoch:for inputs, labels in tepoch:# 直接将数据和标签移动到 GPUinputs, labels = inputs.to(device, non_blocking=True), labels.to(device, non_blocking=True)optimizer.zero_grad()# 混合精度前向和反向传播with autocast(): # 自动混合精度outputs = model(inputs)loss = criterion(outputs, labels)# 反向传播与优化scaler.scale(loss).backward() # 使用混合精度反向传播scaler.step(optimizer) # 更新参数scaler.update() # 更新缩放因子running_loss += loss.item()# 更新进度条显示tepoch.set_postfix(loss=running_loss / (tepoch.n + 1))# 打印每个 epoch 的平均损失print(f"Epoch {epoch + 1}, Loss: {running_loss / len(trainloader)}")# 保存模型torch.save(model.state_dict(), 'zfnet_model.pth')print("Model saved as zfnet_model.pth")
4. 主函数
在主函数中,我们会初始化设备、模型、损失函数,并启动训练过程。
if __name__ == '__main__':"""主函数:组织所有步骤的执行"""# 数据加载trainloader = prepare_data()# 设备选择device = initialize_device()# 模型初始化model = initialize_model(device)# 损失函数criterion = torch.nn.CrossEntropyLoss()# 优化器初始化optimizer = initialize_optimizer(model)# 启动训练train_model(model, trainloader, criterion, optimizer, num_epochs=5, device=device)
二、测试部分:评估 ZFNet 模型
训练完成后,我们将加载训练好的模型,并在测试集上评估其性能。
1. 加载和预处理数据
import torch
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
from zfnet import ZFNet # 假设 ZFNet 定义在 zfnet.py 文件中def load_and_preprocess_data(batch_size=1000):"""加载并预处理 MNIST 数据集:param batch_size: 数据加载的批次大小:return: 测试数据加载器"""transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,))])# 下载 MNIST 测试集testset = datasets.MNIST(root='D:/workspace/data', train=False, download=True, transform=transform)# 数据加载器testloader = DataLoader(testset, batch_size=batch_size, shuffle=False)return testloader
2. 加载训练好的模型
def load_and_preprocess_data(batch_size=1000):"""加载并预处理 MNIST 数据集:param batch_size: 数据加载的批次大小:return: 测试数据加载器"""transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,))])# 下载 MNIST 测试集testset = datasets.MNIST(root='D:/workspace/data', train=False, download=True, transform=transform)# 数据加载器testloader = DataLoader(testset, batch_size=batch_size, shuffle=False)return testloaderdef load_trained_model(model_path='zfnet_model.pth'):"""加载训练好的模型:param model_path: 模型文件路径:return: 加载的模型"""model = ZFNet()model.load_state_dict(torch.load(model_path))model.eval() # 设置为评估模式return model
3. 评估模型
def evaluate_model(model, testloader):"""评估模型在测试集上的表现:param model: 训练好的模型:param testloader: 测试数据加载器:return: 模型准确率"""correct = 0total = 0with torch.no_grad():for inputs, labels in testloader:outputs = model(inputs)_, predicted = torch.max(outputs, 1)total += labels.size(0)correct += (predicted == labels).sum().item()accuracy = correct / totalreturn accuracy
4. 可视化预测结果
def visualize_predictions(model, testloader, num_images=6):"""可视化模型对多张测试图片的预测结果:param model: 训练好的模型:param testloader: 测试数据加载器:param num_images: 显示图像的数量"""model.eval()data_iter = iter(testloader)images, labels = next(data_iter)outputs = model(images)_, predicted = torch.max(outputs, 1)# 绘制结果fig, axes = plt.subplots(2, 3, figsize=(10, 7))axes = axes.ravel()for i in range(num_images):ax = axes[i]img = images[i].numpy().transpose(1, 2, 0) # 将 Tensor 转换为 NumPy 数组并转置为 HWC 格式ax.imshow(img.squeeze(), cmap='gray') # squeeze 去除单通道维度ax.set_title(f"Pred: {predicted[i].item()} | Actual: {labels[i].item()}")ax.axis('off')plt.tight_layout()plt.show()
5. 主函数
在测试阶段,我们加载模型并在测试数据集上评估它。
def main():"""主函数,组织数据加载、模型加载、评估和可视化步骤"""# 加载并预处理数据testloader = load_and_preprocess_data()# 加载训练好的模型model = load_trained_model()# 评估模型accuracy = evaluate_model(model, testloader)print(f"Accuracy: {accuracy * 100:.2f}%")# 可视化预测结果visualize_predictions(model, testloader, num_images=6)if __name__ == '__main__':main()
结语
通过本文的介绍,我们实现了一个基于 ZFNet 模型的图像分类任务,使用 PyTorch 对 MNIST 数据集进行训练与测试,并展示了如何进行混合精度训练以提高效率。在未来,你可以根据不同的任务修改模型结构、优化器或者训练策略,进一步提升性能。
完整项目ZFNet-PyTorch: 使用 PyTorch 实现 ZFNet 进行 MNIST 图像分类
https://gitee.com/qxdlll/zfnet-py-torch
相关文章:
使用 PyTorch 实现 ZFNet 进行 MNIST 图像分类
在本篇博客中,我们将通过两个主要部分来演示如何使用 PyTorch 实现 ZFNet,并在 MNIST 数据集上进行训练和测试。ZFNet(ZFNet)是基于卷积神经网络(CNN)的图像分类模型,广泛用于图像识别任务。 环…...
车轮上的科技:Spring Boot汽车新闻集散地
1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理汽车资讯网站的相关信息成为必然。开发合适…...
IDEA2023 SpringBoot整合Web开发(二)
一、SpringBoot介绍 由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。SpringBoot提供了一种新的编程范式,可以更加快速便捷…...
国产三维CAD 2025新动向:推进MBD模式,联通企业设计-制造数据
本文为CAD芯智库原创整理,未经允许请勿复制、转载! 上一篇文章阿芯分享了影响企业数字化转型的「MBD」是什么、对企业优化产品设计流程有何价值——这也是国产三维CAD软件中望3D 2024发布会上,胡其登先生(中望软件产品规划与GTM中…...
ubuntu 之 安装mysql8
安装 # 如果 ubuntu 版本 > 20.04 则不用执行 wget 这步 wget https://dev.mysql.com/get/mysql-apt-config_0.8.12-1_all.debsudo apt-get updatesudo apt-get install mysql-server mysql-client 安装过程中如果没有提示输入密码 sudo cat /etc/mysql/debian.cnf # 查…...
Flink Lookup Join(维表 Join)
Lookup Join 定义(支持 Batch\Streaming) Lookup Join 其实就是维表 Join,比如拿离线数仓来说,常常会有用户画像,设备画像等数据,而对应到实时数仓场景中,这种实时获取外部缓存的 Join 就叫做维…...
Elasticsearch retrievers 通常与 Elasticsearch 8.16.0 一起正式发布!
作者:来自 Elastic Panagiotis Bailis Elasticsearch 检索器经过了重大改进,现在可供所有人使用。了解其架构和用例。 在这篇博文中,我们将再次深入探讨检索器(retrievers)。我们已经在之前的博文中讨论过它们…...
【并发模式】Go 常见并发模式实现Runner、Pool、Work
通过并发编程在 Go 程序中实现的3种常见的并发模式。 参考:https://cloud.tencent.com/developer/article/1720733 1、Runner 定时任务 Runner 模式有代表性,能把(任务队列,超时,系统中断信号)等结合起来…...
【前端知识】Javascript前端框架Vue入门
前端框架VUE入门 概述基础语法介绍组件特性组件注册Props 属性声明事件组件 v-model(双向绑定)插槽Slots内容与出口 组件生命周期样式文件使用1. 直接在<style>标签中写CSS2. 引入外部CSS文件3. 使用CSS预处理器4. 在main.js中全局引入CSS文件5. 使用CSS Modules6. 使用P…...
Springboot3.3.5 启动流程之 Bean创建流程
在文章Springboot3.3.5 启动流程(源码分析)中我们只是粗略的介绍了bean 的装配(Bean的定义)流程和实例化流程分别开始于 finishBeanFactoryInitialization 和 preInstantiateSingletons. 其实,在Spring boot中,Bean 的装配是多阶段的…...
golang反射函数注册
package main import ( “fmt” “reflect” ) type Job interface { New([]interface{}) interface{} Run() (interface{}, error) } type DetEd struct { Name string Age int } // 为什么这样设计 // 这样就避免了 在创建新的实例的之后 结构体的方法中接受者为指针类型…...
【Spring】Bean
Spring 将管理对象称为 Bean。 Spring 可以看作是一个大型工厂,用于生产和管理 Spring 容器中的 Bean。如果要使用 Spring 生产和管理 Bean,那么就需要将 Bean 配置在 Spring 的配置文件中。Spring 框架支持 XML 和 Properties 两种格式的配置文件&#…...
深入解析TK技术下视频音频不同步的成因与解决方案
随着互联网和数字视频技术的飞速发展,音视频同步问题逐渐成为网络视频播放、直播、编辑等过程中不可忽视的技术难题。尤其是在采用TK(Transmission Keying)技术进行视频传输时,由于其特殊的时序同步要求,音视频不同步现…...
为什么要使用Ansible实现Linux管理自动化?
自动化和Linux系统管理 多年来,大多数系统管理和基础架构管理都依赖于通过图形或命令行用户界面执行的手动任务。系统管理员通常使用清单、其他文档或记忆的例程来执行标准任务。 这种方法容易出错。系统管理员很容易跳过某个步骤或在某个步骤上犯错误。验证这些步…...
Android:任意层级树形控件(有效果图和Demo示例)
先上效果图: 1.创建treeview文件夹 2.treeview -> adapter -> SimpleTreeAdapter.java import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ListView; i…...
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
引言 C 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C 的开发者来说,了解这些容…...
C++---类型转换
文章目录 C的类型转换C的4种强制类型转换RTTI C的类型转换 类型转换 内置类型之间的转换 // a、内置类型之间 // 1、隐式类型转换 整形之间/整形和浮点数之间 // 2、显示类型的转换 指针和整形、指针之间 int main() {int i 1;// 隐式类型转换double d i;printf("%d…...
CSS基础学习练习题
编程题 1.为下面这段文字定义字体样式,要求字体类型指定多种、大小为14px、粗细为粗体、颜色为蓝色。 “有规划的人生叫蓝图,没规划的人生叫拼图。” 代码: <!DOCTYPE html> <html lang"en"> <head><me…...
TypeScript知识点总结和案例使用
TypeScript 是一种由微软开发的开源编程语言,它是 JavaScript 的超集,提供了静态类型检查和其他一些增强功能。以下是一些 TypeScript 的重要知识点总结: 1. 基本类型 TypeScript 支持多种基本数据类型,包括: numbe…...
解决BUG: Since 17.0, the “attrs“ and “states“ attributes are no longer used.
从Odoo 17.0开始,attrs和states属性不再使用,取而代之的是使用depends和domain属性来控制字段的可见性和其他行为。如果您想要在选择国家之后继续选择州,并且希望在选择了国家之后才显示州字段,您可以使用depends属性来实现这一点…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
