猫狗大战(猫狗识别)

1.问题简介

1.1问题描述

        在这个问题中,你将面临一个经典的机器学习分类挑战——猫狗大战。你的任务是建立一个分类模型,能够准确地区分图像中是猫还是狗。 

1.2预期解决方案

        你的目标是通过训练一个机器学习模型,使其在给定一张图像时能够准确地预测图像中是猫还是狗。模型应该能够推广到未见过的图像,并在测试数据上表现良好。我们期待您将其部署到模拟的生产环境中——这里推理时间和二分类准确度(F1分数)将作为评分的主要依据。

1.3数据集

        链接:百度网盘 请输入提取码

        提取码:jc34

2.数据处理

2.1数据集特征

        训练数据集包括 25000 张图片,其中类别为猫的图片有 12500 张图片,类别为狗的图片有12500 张,两种类别比例为 1:1


 2.2数据预处理

        将数据 resize 到 224×224×3 的维度,Cats vs. Dogs 数据集中的数据较为干净,不需要额外的清洗工作。 图片数据集的命名方式是 type.num.jpg,根据文件的命名,将不同类别的图片划分到 cat 和 dog 两个文件夹中。 划分后的文件夹结构,在 train 文件夹下有 Cats 和 Dogs 两 个文件夹,每个包含 12500 张样本图片数据集结构。由于没有测试集文件由于验证模型,因此后续只使用train文件将其按4:1比例分割出测试集文件。

2.3数据集划分

        猫狗分类:图片数据集的命名方式是 type.num.jpg,首先根据train目录下的文件名称前缀识别动物类别,并且将其放入对应文件夹(cat、dog)中。

# 指定目录
source_dir = './dataset/train'
dogs_dir = './train_data/dog'
cats_dir = './train_data/cat'# 创建目标目录
os.makedirs(dogs_dir, exist_ok=True)
os.makedirs(cats_dir, exist_ok=True)# 获取目录下所有文件
files = os.listdir(source_dir)# 遍历文件
for file in files:
#     根据前缀分类if file.startswith('dog'):shutil.move(os.path.join(source_dir, file), os.path.join(dogs_dir, file))elif file.startswith('cat'):shutil.move(os.path.join(source_dir, file), os.path.join(cats_dir, file))

        划分测试集:由于需要测试数据验证模型好坏,将从cat与dog目录中随机取出20%的数据作为测试集。

# 源目录路径
src_dir = './train_data'# 目标目录路径
dst_dir = './test_data'# 确保目标目录存在
if not os.path.exists(dst_dir):os.makedirs(dst_dir)# 遍历源目录下的cat和dog子目录
for animal in ['cat', 'dog']:src_animal_dir = os.path.join(src_dir, animal)dst_animal_dir = os.path.join(dst_dir, animal)# 确保动物子目录在目标目录下存在if not os.path.exists(dst_animal_dir):os.makedirs(dst_animal_dir)# 获取源目录下所有图片文件img_files = [f for f in os.listdir(src_animal_dir) if os.path.isfile(os.path.join(src_animal_dir, f)) and f.endswith(('.jpg', '.png', '.jpeg'))]# 计算需要移动的图片数量(20%)num_to_move = int(len(img_files) * 0.2)# 随机选取20%的图片selected_files = random.sample(img_files, num_to_move)# 移动选中的图片到目标目录for file in selected_files:src_file_path = os.path.join(src_animal_dir, file)dst_file_path = os.path.join(dst_animal_dir, file)shutil.move(src_file_path, dst_file_path)print("已完成图片迁移操作!")

2.4数据加载器的构建 

数据预处理:transforms.Compose类定义了一系列图像转换操作。
        注意:标签是由ImageFolder类通过目录结构自动获取的。ImageFolder会将catdog作为标签,内部创建一个字典来映射类别名称到索引,并且每个子目录中的图片都将被标记为相应的类别,如{'cat': 0, 'dog': 1}

# 数据预处理
transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])# 数据集路径
train_dir = './train_data'# 创建ImageFolder实例时,使用filter参数来排除不需要的文件夹
train_dataset = ImageFolder(train_dir, transform=transform)# 创建数据加载器
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True, num_workers=4)# 数据长度
print(len(train_dataset))
# 标签
# print(train_dataset.classes)  # 输出: ['cat', 'dog']
print(train_dataset.class_to_idx)  # 输出: {'cat': 0, 'dog': 1}

         报错:有可能出现错误——在遍历加载图片使,遇见了“.ipynb_checkpoints”,具体产生原因未知。

# 通常.ipynb_checkpoints 是 Jupyter Notebook 的自动保存副本存放位置
# 查找 .ipynb_checkpoints 目录并删除(包括其所有子文件和子目录)
checkpoints_path = os.path.join(train_dir, '.ipynb_checkpoints')
if os.path.exists(checkpoints_path):shutil.rmtree(checkpoints_path)
else:print(f"The directory '{checkpoints_path}' does not exist and therefore cannot be removed.")

数据加载器——训练集:

train_loader​​​​

数据加载器——测试集:

test_loader


 3.猫狗分类器设计

3.1模型选择

        ResNet18是深度残差网络(Residual Network)的一个具体实现。该网络架构的设计目的是为了缓解随着网络深度增加带来的梯度消失和训练困难问题。ResNet通过引入“残差块”(Residual Block)结构来改进传统的卷积神经网络(CNN),使得网络能够更容易地学习到更深层次的特征表达。ResNet18之所以得名,是因为它有18层深(不包括输入层和输出层),其深层设计得益于残差连接机制。这种结构使得网络可以轻易地构建超过100层甚至更深,而不会遇到梯度消失或梯度爆炸的问题,因此它具有很强的深度可扩展性。所以本次研究选用了 ResNet18模型。

3.2平台搭建

硬件平台

本研究采用NVIDIA GeForce RTX 3060 GPU作为主要的计算硬件平台。该GPU基于先进的NVIDIA Ampere架构设计,拥有强大的并行处理能力和高效能的显存系统。GeForce RTX 3060配备了充足的CUDA核心以支持大规模的数据并行计算任务,并且内建RT Core与Tensor Core技术,为深度学习模型训练提供实时光线追踪加速以及DLSS等AI运算优化能力。

软件栈

在软件层面,我们选择了PyTorch开源深度学习框架作为主要的开发工具。PyTorch以其灵活动态的计算图特性、直观易用的API以及丰富的社区资源而著称,特别适合于科研探索与原型开发。通过集成对CUDA和cuDNN库的支持,PyTorch能够在NVIDIA GeForce RTX 3060 GPU上充分利用硬件加速优势,实现高效的深度学习模型训练与推断。

  

其次,使用了intel官网提供的oneAPI云环境(oneapi.devcloud)进行模型的迁移与优化。

3.3ResNet的主要优势

        ResNet的设计主要针对解决随着网络深度增加而出现的训练困难问题,如梯度消失和爆炸问题,这些问题使得在网络加深后准确率不再提升甚至下降。

        ResNet引入了残差块(Residual Block)的概念:一个残差块包含多个卷积层,其核心思想是引入“快捷连接”或“跳跃连接”,允许信息直接从输入跳过一些中间层传递到输出。通过构建由多个残差块堆叠而成的网络,ResNet能够实现上百层的深度。

        解决退化现象:线性转换是关键目标,它将数据映射到高纬空间以便于更好的完成“数据分类”。随着网络深度的不断增大,所引入的激活函数也越来越多,数据被映射到更加离散的空间,此时已经难以让数据回到原点(恒等变换)。或者说,神经网络将这些数据映射回原点所需要的计算量,已经远远超过我们所能承受的。

        退化现象让我们对非线性转换进行反思,非线性转换极大的提高了数据分类能力,但是,随着网络的深度不断的加大,我们在非线性转换方面已经走的太远,竟然无法实现线性转换。显然,在神经网络中增加线性转换分支成为很好的选择,于是,ResNet团队在ResNet模块中增加了快捷连接分支,在线性转换和非线性转换之间寻求一个平衡。

3.4自定义网络架构

        基础的猫狗大战问题属于二分类问题,因此最后输出层输出大小为2。

model = torchvision.models.resnet18(pretrained=False)
num_features = model.fc.in_features
# 加载预训练的模型
model.load_state_dict(torch.load("./resnet18-f37072fd.pth"))
# print(model)# 输出类别数等于数据集类别数
model.fc = nn.Linear(num_features, len(train_dataset.classes)) 

4.模型训练

4.1模型基本参数设置

# 设定设备(GPU或CPU)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

4.2模型训练

        为了提高效率,首先在本机的GPU上进行模型的训练。

# 训练
# 使用预训练的ResNet18,并且只修改最后一层适应我们的分类任务(假设类别数为2:dog和cat)model = torchvision.models.resnet18(pretrained=False)
num_features = model.fc.in_features
# 加载预训练的模型
model.load_state_dict(torch.load("./resnet18-f37072fd.pth"))
# print(model)model.fc = nn.Linear(num_features, len(train_dataset.classes))  # 输出类别数等于数据集类别数# 设定设备(GPU或CPU)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)# 训练轮数
num_epochs = 1
i=0
# 计时
start_time = time.time()  # 记录开始时间for epoch in range(num_epochs):model.train()  # 设置模型为训练模式print("num:",epoch)for inputs, labels in train_loader:print(i, end=" ")i+=1inputs, labels = inputs.to(device), labels.to(device)  # 将数据转移到设备上optimizer.zero_grad()  # 清零梯度outputs = model(inputs)  # 前向传播loss = criterion(outputs, labels)  # 计算损失loss.backward()  # 反向传播optimizer.step()  # 更新权重print(f'Epoch {epoch + 1}/{num_epochs}, Loss: {loss.item():.4f}')end_time = time.time()  # 记录结束时间elapsed_time = end_time - start_timeprint(f'轮数{epoch} 训练集用的时间为: {elapsed_time:.2f} seconds')

如果直接使用cpu:

4.3训练结果

4.4保存模型

# 在训练完成后保存模型权重
torch.save(model.state_dict(), './my_model_weights.pth')# 若要加载保存的模型权重
# 加载模型架构
model = torchvision.models.resnet18(pretrained=False)
num_features = model.fc.in_features
model.fc = nn.Linear(num_features, len(train_dataset.classes))# 将模型加载到GPU或CPU上
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)# 加载之前保存的权重
model.load_state_dict(torch.load('./my_model_weights.pth'))# 保存和加载整个模型(包括模型结构和权重),可以这样做:
# 保存整个模型
torch.save(model, './my_model.pth')# 加载整个模型
# model = torch.load('./my_model.pth', map_location=device)  

效果演示: 

5.将模型移植至intel 云平台

5.1加载模型

        保存模型后将其上传至云平台,再加载模型至云平台上运行。

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = torch.load('./my_model.pth', map_location=device)  

 5.3预测结果

5.4公共测试集预测结果 

        后续补发了公共测试集:猫狗数据各500张。

 

6.可视化模型预测

6.1自定义数据

        方式:从抖音获取截图。

 

        6.2模型尝试分类

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = torch.load('./my_model.pth', map_location=device) 
model.eval()  # 设置模型为评估模式# 定义测试图像的路径
test_image_path = './free_test/tiktokCat.jpg'# 定义图像预处理的变换
transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])# 加载测试图像
test_image = Image.open(test_image_path)plt.imshow(test_image)
#变换
test_image = transform(test_image).unsqueeze(0)  # 添加一个批次维度start_time = time.time()  # 记录开始时间
# 进行预测
with torch.no_grad():  # 测试阶段不需要计算梯度output = model(test_image)
#     概率大的解释预测结果_, predicted = torch.max(output, 1)end_time = time.time()  # 记录结束时间
elapsed_time = end_time - start_time
print(f'预测一张自定义图片所用的时间为: {elapsed_time:.2f} seconds')# 根据类别数量,我们可以直接映射
predicted_label = predicted.item()# cat: 0, dog: 1
if predicted_label == 0:predicted_class_name = 'cat'
else:predicted_class_name = 'dog'# print(f'Predicted: {predicted_class_name}')
plt.axis('off')  
plt.title("Predicted:    "+predicted_class_name)
plt.show()
print(predicted_class_name)

6.3预测结果

7.使用OneAPI组件

        Intel oneAPI 是一个跨行业、开放、基于标准的统一的编程模型,旨在提供一个适用于各类计算架构的统一编程模型和应用程序接口。也就是说,应用程序的开发者只需要开发一次代码,就可以让代码在跨平台的异构系统上执行,底层的硬件架构可以是CPU、GPU、FPGA、神经网络处理器,或者其他针对不同应用的硬件加速器等等。由此可见,oneAPI既提高开发效率,又可以具有一定的性能可移植性。
 

7.1使用Intel Extension for PyTorch进行优化

简介:

        Intel Extension for PyTorch(也称为IPEX)是Intel为PyTorch深度学习框架开发的一系列优化库,旨在提高在Intel架构上的性能表现,特别是针对CPU和GPU(如Intel Xeon和Intel Data Center GPU Flex Series)。这个扩展提供了以下功能:

**自动混合精度**:对于支持的硬件平台,可能包括自动混合精度训练功能,通过动态地将部分计算从单精度浮点(FP32)转换到半精度浮点(FP16),从而减少内存占用并加速计算。

使用Intel Extension for PyTorch可以简化代码调整过程,并且无需大量修改现有PyTorch代码即可获得显著性能提升。只需导入相应的库并调用特定函数或方法,就可以利用这些优化特性。

# 将模型移动到CPU
# print(model)
device = torch.device('cpu')
model.to(device)model = torch.load('./my_model.pth', map_location=device)  
# 重新构建优化器
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)# 使用Intel Extension for PyTorch进行优化
my_model, optimizer = ipex.optimize(model=model, optimizer=optimizer, dtype=torch.float32)

保存优化模型

# 保存模型参数
torch.save(my_model.state_dict(), 'my_model_optimized.pth')# 加载模型参数
my_model.load_state_dict(torch.load('my_model_optimized.pth'))

优化结果:

优化前
优化后

 

7.2使用 Intel® Neural Compressor 量化模型 

# 将模型移动到CPUmodel.load_state_dict(torch.load('my_model_optimized.pth'))
model.to('cpu')  # 将模型移动到 CPU
model.eval()
model.eval()# 定义评估函数
def eval_func(model):with torch.no_grad():y_true = []y_pred = []for inputs, labels in train_loader:inputs = inputs.to('cpu')labels = labels.to('cpu')outputs = model(inputs)_, predicted = torch.max(outputs, 1)
#         print(predicted,labels,end="  ")y_pred.extend(predicted.cpu().tolist())y_true.extend(labels.cpu().tolist())return accuracy_score(y_true, y_pred)# 配置量化参数
conf = PostTrainingQuantConfig(backend='ipex',  # 使用 Intel PyTorch Extensionaccuracy_criterion=AccuracyCriterion(higher_is_better=True, criterion='relative',  tolerable_loss=0.01))
start_time = time.time()  # 记录开始时间
# 执行量化
q_model = quantization.fit(model,conf,calib_dataloader=train_loader,eval_func=eval_func)
end_time = time.time()  # 记录结束时间
elapsed_time = end_time - start_time
print(f'量化用时: {elapsed_time:.2f} seconds')
# 保存量化模型
quantized_model_path = './quantized_models'
if not os.path.exists(quantized_model_path):os.makedirs(quantized_model_path)q_model.save(quantized_model_path)

量化结果:

量化后


 

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

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

相关文章

Open3D对产生偏差的点云数据进行校正

由于相机安装问题,导致点云数据两边翘起来,为了计算把翘起来的部分拉平整 import time import open3d as o3d; import numpy as np; import matplotlib.pyplot as plt from scipy.signal import find_peaks import pandas as pdOriginalPly o3d.io.rea…

【代码随想录04】24. 两两交换链表中的节点 19. 删除链表的倒数第 N 个结点 面试题 02.07. 链表相交 142. 环形链表 II

24. 两两交换链表中的节点 题目描述 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 做题思路 可以设置虚拟头结点cur和画图…

MySQL 从零开始:05 MySQL 数据类型

文章目录 1、数值类型1.1 整形数值1.2 浮点型数值1.3 布尔值 2、日期和时间类型3、字符串类型3.1 CHAR 和 VARCHAR3.2 BINARY 和 VARBINARY3.3 BLOB 和 TEXT3.4 ENUM 类型3.5 SET 类型 4、空间数据类型5、JSON 数据类型5、JSON 数据类型 前面的讲解中已经接触到了表的创建&…

跟着cherno手搓游戏引擎【5】layer(层)

编写基类层: Layer.h:提供Attach链接、Detach解绑、Update刷新、Event事件、GetName方法 #pragma once #include"YOTO/Core.h" #include"YOTO/Event/Event.h" namespace YOTO {class YOTO_API Layer{public:Layer(const std::string& nam…

基于kkFileView实现万能文件预览

基于kkFileView实现万能文件预览 1.简介 文档在线预览项目解决方案,项目使用流行的spring boot搭建,易上手和部署。万能的文件预览开源项目,基本支持主流文档格式预览 官网:https://kkview.cn/zh-cn/docs/home.html github地址…

使用 Docker 进行 Go 应用程序引导指南

为在 Docker 中部署的 Go 应用程序做准备 在使用 Go 开发 Web 应用程序时,无论是用于 HTTP 还是其他类型的服务,部署到不同的阶段或环境(本地开发、生产环境等)都是一个常见的考虑因素。在本文中,我们将探讨在 Docker …

浅析Linux进程管理:current宏实现

本文基于Linux 5.10.186版本内核源码进行分析。 文章目录 current概述早期内核版本实现最新版本内核实现x86体系下的current宏实现ARMv8体系下的current实现 相关参考 current概述 Linux内核在运行时经常需要访问当前运行进程的task_struct指针,于是,系…

CRM-如何做好客户管理

客户是企业最重要的资源,也是客户360视图管理的主数据,企业的运转都是围绕客户来开展的,如何做好客户数据的管理是一门学问,也需要企业动态的调整战略。 客户分为企业客户(Account)与个人客户(…

NUS CS1101S:SICP JavaScript 描述:前言、序言和致谢

前言 原文:Foreword 译者:飞龙 协议:CC BY-NC-SA 4.0 我有幸在我还是学生的时候见到了了不起的 Alan Perlis,并和他交谈了几次。他和我共同深爱和尊重两种非常不同的编程语言:Lisp 和 APL。跟随他的脚步是一项艰巨的任…

大创项目推荐 深度学习疫情社交安全距离检测算法 - python opencv cnn

文章目录 0 前言1 课题背景2 实现效果3 相关技术3.1 YOLOV43.2 基于 DeepSort 算法的行人跟踪 4 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习疫情社交安全距离检测算法 ** 该项目较为新颖,适合作为竞赛…

基于深度学习的婴儿啼哭识别项目详解

基于深度学习的婴儿啼哭识别项目详解 基于深度学习的婴儿啼哭识别项目详解一、项目背景1.1 项目背景1.2 数据说明 二、PaddleSpeech环境准备三、数据预处理3.1 数据解压缩3.2 查看声音文件3.3 音频文件长度处理 四、自定义数据集与模型训练4.1 自定义数据集4.2 模型训练4.3 模型…

Linux截图方法推荐

因为经常会遇到以图为证的情况,而办公设备基本都是linux,所以汇总一下常见的linux截图方式。 1:在 Linux 中系统集成的截图的默认方式 你想要截取整个屏幕?屏幕中的某个区域?某个特定的窗口? 如果只需要获取一张屏幕…

Servlet-体系结构

一、思考 读者阅读完上一篇关于Servlet基本概念的文章后,我们知道每次实现一个Servlet,都需要覆盖五个接口,我们对除service接口外的其它四个接口,我们通常不会做什么处理。那么,这种实现方式是否有些繁琐呢&#xff…

【Linux实用篇】Linux常用命令(2)

目录 1.3 拷贝移动命令 1.3.1 cp 1.3.2 mv 1.4 打包压缩命令 1.5 文本编辑命令 1.5.1 vi&vim介绍 1.5.2 vim安装 1.5.3 vim使用 1.6 查找命令 1.6.1 find 1.6.2 grep 1.3 拷贝移动命令 1.3.1 cp 作用: 用于复制文件或目录 语法: cp [-r] source dest ​ 说明: …

深入理解@DubboReference与@DubboService【三】

欢迎来到我的博客,代码的世界里,每一行都是一个故事 探索Dubbo的核心:深入理解DubboReference与DubboService【三】 前言DubboService注解基本概念使用示例高级特性 DubboReference注解基本概念使用示例服务调用流程 最佳实践注解的最佳使用方…

什么是云服务器,阿里云优势如何?

阿里云服务器ECS英文全程Elastic Compute Service,云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务,阿里云提供多种云服务器ECS实例规格,如经济型e实例、通用算力型u1、ECS计算型c7、通用型g7、GPU实例等,阿里云百科aliyunbai…

Fabric2.2:在有系统通道的情况下搭建应用通道

写在最前 在使用Fabric-SDK-Go1.0.0操作Fabric网络时遇到了bug。Fabric-SDK-GO的当前版本没有办法在没有系统通道的情况下创建应用通道,而Fabric的最新几个版本允许在没有系统通道的情况下搭建应用通道。为了解决这个矛盾并使用Fabric-SDK-GO完成后续的项目开发&…

Web前端 ---- 【Vue3】ref和reactive实现响应式的区别和联系

目录 前言 setup ref 基本数据类型 对象形式 reactive ref和reactive的区别与联系 前言 本文介绍函数ref和函数reactive实现响应式 setup 在介绍ref和reactive之前,先介绍setup,vue3新引入的配置项。在该配置项中,在vue2中的data、methods、comput…

xtu oj 1475 冰墩墩和冰壶

题目描述 冰壶是被誉为“冰面上的国际象棋”,其计分规则是各自投壶,最后在大本营内,你有几个壶离圆心比对方所有壶离圆心都近就得到几分。 比如红方有两个壶,分别在坐标(1,1),(−2,1);黄方也有两个壶,分别…

GULP 案例 4:如何计算热力学性质(热容、熵、焓、自由能等)?

---------------------------------------------------------------------- 物体的热力学性质是指物质处于平衡状态下压力 P、体积 V、温度 T、组成以及其他的热力学函数之间的变化规律。一般将材料的压力 P、体积 V、温度 T、内能 U、焓 H、熵 S 等统称为物体热力学性质。 热…