从0开始做yolov5模型剪枝

news2024/11/19 18:34:16

文章目录

  • 从0开始做yolov5模型剪枝 **·**
    • 1 前言
    • 2 GitHub取源码
    • 3 原理
      • 3.1 原理
      • 3.2 network slimming过程
    • 4 具体实施步骤
      • 4.1 安装虚拟环境
      • 4.2 配置参数
        • 4.2.1 数据集参数
        • 4.2.2 模型结构参数
        • 4.2.3 train.py中的参数
      • 4.3 正常训练
        • 4.3.1 准备
        • 4.3.2 训练及问题解决
      • 4.4 稀疏化训练
        • 4.4.1 参数设置
        • 4.4.2 稀疏化训练与问题
      • 4.5 剪枝
        • 4.5.1 参数设置
        • 4.5.2 剪枝
      • 4.6 finetune剪枝的网络
        • 4.6.1 参数设置
        • 4.6.2 finetune
      • 4.7 循环稀疏训练->剪枝->finetune网络

从0开始做yolov5模型剪枝 ·

1 前言

【整个流程中,在正常train,sparityTrain,prune,finetune遇到10多个的问题,包括AttributeError、ModuleNotFoundError、RuntimeError、SyntaxError、TypeError等问题的解决方法,详见内容】

为了将现有模型移植到ARM平台,同时保证模型准确率的基础上,减少模型的算力消耗和推理时间。

之前有做实验对比了YOLOv5、 YOLOv7、 YOLOv8,结合不同版本模型推理时间和准确率,并查了很多资料,包括大部分人博客描述,结合大部分人经验,我们觉的yolov5的泛化能力较好。故在考虑训练自己的模型且在X86和ARM平台上部署,我们针对yolov5做模型的训练和剪枝,以便轻量化小模型的部署。

当然,我们还需要对最终的模型执行INT8量化的操作,以便降低目标检测的推理时间。

2 GitHub取源码

下载如下路径的源码:

https://github.com/midasklr/yolov5prune/tree/v6.0

本文为 上面GitHub上取6.0的版本做剪枝

3 原理

【根据一些博客/文章对yolov5剪枝的介绍,简单总结一下yolov5模型剪枝的原理】

3.1 原理

原理论文:Learning Efficient Convolutional Networks through Network Slimming

ref: Pruning Filters for Efficient ConvNets( https://arxiv.org/abs/1608.08710 )

ref: https://blog.csdn.net/qq_42835363/article/details/129125376?spm=1001.2014.3001.5501

ref: https://blog.csdn.net/IEEE_FELLOW/article/details/117236025

ref: Yolov5_5.0上做模型剪枝

输入经过BN(Batch Normalization)层获得归一化后的分布。BN层存在两个可训练参数γ(gamma)、β(beta)。

当gamma和betaγ趋于0时,输入相当于乘以了0,此时该channel上的卷积将输出0,这是无意义的。因此,可以认为剔除这样冗余的channel对模型性能没有影响。

普通网络训练时,由于初始化,gamma一般分布在1附近。为了使gamma趋于0,可以通过添加L1正则来约束,使得系数稀疏化。论文中把添加gammaL1正则的训练称为稀疏训练。

稀疏训练后,裁剪掉稀疏很小的层,对应激活也很小,所以对后面的影响非常小,反复迭代这个过程,可以获得小型的模型,步骤如图1。

在这里插入图片描述

图1

3.2 network slimming过程

① 先初始化网络,对BN层的参数添加L1正则并对网络训练。

② 统计网络中的γ(gamma),设置剪枝率对网络进行裁剪。

③ 将裁减完的网络finetune,完成剪枝工作。

4 具体实施步骤

4.1 安装虚拟环境

解压下载的源码,进入yolov5prune_6.0目录下,依次执行下面的操作

# 1 创建虚拟环境
conda create -n yolov5prune
# 2 激活虚拟环境
conda activate yolov5prune
# 3 安装虚拟环境(根据yolov5prune_6.0根目录下的requirements.txt安装)
pip install -r requirements.txt

4.2 配置参数

4.2.1 数据集参数

自己的数据集结构如下

--datasTrain
------images
----------train     	# 存放训练数据集的图片(.jpg)
----------val
----------test
------labels
----------train			# 存放训练图片对应的标签文件(.txt)
----------val
----------tes

在/yolov5prune_6.0/data/目录下,仿照coco128.yaml中的结构创建my_yolov5.yaml文件。其中内容如下

# Train/val/test sets as 
# 1) dir: path/to/imgs, 
# 2) file: path/to/imgs.txt, or 
# 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: /home/user/hlj/MyTrain/datasTrain3_More/  # dataset root dir
train: images/train/  # train images (relative to 'path') 128 images
val: images/val/      # val images (relative to 'path') 128 images
test:  images/test/   # test images (optional)


nc: 11  # number of classes
names: ['pedes', 'car', 'bus', 'truck', 'bike', 'elec', 'tricycle', 'coni', 'warm', 'tralight', 'specVehi']

4.2.2 模型结构参数

修改yolov5prune_6.0/models/yolov5s.yaml中的目标检测类型,使其适配自己数据集的目标检测类型数量。如下

nc: 11

4.2.3 train.py中的参数

设置train.py中的参数,主要包括如下:

'--weights', default='./yolov5s.pt'  # 由于我要从头训练,所以注释了此参数
'--cfg', default='./models/yolov5s.yaml'
'--data', default='./data/my_yolov5.yaml'
'--epochs', default=300 		# 由于从头训练,所以epochs值设的比较大
'--batch-size', default=-1
'--imgsz', default=640			# 考虑部署

4.3 正常训练

4.3.1 准备

由于我是SSH链接,所以先创建/打开tmux会话

tmux new -s prunesession

若【先按下ctrl+b,然后再单独按d】退出会话的话,下次再进入会话,需要使用命令

tmux a -t prunesession

进入会话,先进入项目目录下,并激活虚拟环境(若已激活,可忽略)

cd ../yolov5prune_6.0/
source activate yolov5prune

训练结束之后要删除会话

tmux kill-session -t prunesession

4.3.2 训练及问题解决

执行如下命令,进行训练

python3 train.py

【问题1】

运行train.py文件后,报了如下错误

ModuleNotFoundError: No module named 'utils.loggers.wandb'

提示缺包,根据别人的攻略,下载U神对应yolov5_6.0版本的代码,然后把yolov5_6.0\utils\loggers\目录下的整个wandb文件夹拷贝到yolov5prune_6.0\utils\loggers目录下。

【问题2】

重新输入 python3 train.py 后,报如下问题,由此可见,设置train.py中的参数的时候,'–weights’参数不可以被注释掉。

AttributeError: 'Namespace' object has no attribute 'weights'

故将’weights’参数设置如下,表示不使用预训练权重,模型将从头开始训练。

'--weights', default=''

【问题3】

不知道为什么,ubuntu上又报了一个numpy的问题如下,本地运行是没有这个问题的

raise AttributeError(__former_attrs__[attr])
AttributeError: module 'numpy' has no attribute 'int'.

原来是因为 新版本的numpy里面没有np.int,可以修改源码解决。

修改yolov5prune_6.0/utils/ 目录下datasets.py中所有的…astype(np.int) 为 …astype(int),如下所示:

441  bi = np.floor(np.arange(n) / batch_size).astype(int)  # batch index
483  self.batch_shapes = np.ceil(np.array(shapes) * img_size / stride + pad).astype(int) * stride
854  b = xywh2xyxy(b.reshape(-1, 4)).ravel().astype(int)

修改yolov5prune_6.0/utils/ 目录下general.py中所有的…astype(np.int) 为 …astype(int),如下所示:

510  classes = labels[:, 0].astype(int)  # labels = [class xywh]
525  class_counts = np.array([np.bincount(x[:, 0].astype(int), minlength=nc) for x in labels])

【问题4】

File "/home/user/hlj/MyTrain/yolov5prune_6.0/utils/loss.py", line 217, in build_targets
indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1))) 
RuntimeError: result type Float can't be cast to the desired output type long int

参考 ref: https://blog.csdn.net/Thebest_jack/article/details/125649451 执行如下操作:

修改yolov5prune_6.0/utils/ 目录下loss.py源码,

#(1) 183行左右
for i in range(self.nl):
    anchors, shape = self.anchors[i], p[i].shape   # anchors = self.anchors[i]
    gain[2:6] = torch.tensor(p[i].shape)[[3, 2, 3, 2]]  # xyxy gain
#(2)218行后
# indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1)))  
上一行代码改为如下
indices.append((b, a, gj.clamp_(0, shape[2] - 1), gi.clamp_(0, shape[3] - 1)))  # image, anchor, grid indices            

【问题5】

epoch的时候,报如下问题

File "..../yolov5prune_6.0/utils/plots.py", line 116, in text
w, h = self.font.getsize(text)  # text width, height
AttributeError: 'FreeTypeFont' object has no attribute 'getsize'

这是因为安装了新版本的 Pillow,pip install tf-models-official删除了该getsize功能
,降级到 Pillow 9.5 解决了该问题。可以尝试以下方法进行解决,参见【问题8】:

pip install Pillow==9.5

【问题6】

epoch 0 结束,val结束后,报如下问题

File ".....\yolov5prune_6.0\utils\callbacks.py", line 77, in run
    logger['callback'](*args, **kwargs)
TypeError: on_fit_epoch_end() missing 1 required positional argument: 'fi'

找一下官方源码,把yolov5_6.0/utils/下的整个loggers文件复制进去,应该就行了,可能是版本不一致导致的。

【问题7】

yolov5prune_6.0/utils/general.py line471
return re.sub(pattern="[|@#!?·$€%&()=??^*;:,¨′><+]", repl="_", string=s)
SyntaxError:(unicoda error)'utf-8' code can't decode byte 0xal in position 6: invalid start byte。 

应该是’utf-8’ code不支持的问题,添加了下面的编码格式,但最后也没解决。看了一下对应函数的功能,只是为了清理字符串(用下划线替代特殊字符),所以就直接改了那一行的代码,对整个程序是没有影响的。

# -*- coding: utf-8 -*-

【总结】

虽然各种问题不断,而且【问题5】我也没管它 但是,最后总算是python3 train.py正常跑起来了。

4.4 稀疏化训练

4.4.1 参数设置

对train_sparity.py的参数进行设置

'--st', action='store_true',default=True,
'--sr', type=float, default=0.0001,
'--weights', type=str, default=ROOT / '',
'--cfg', type=str, default='./models/yolov5s.yaml',
'--data', type=str, default='./data/my_yolov5.yaml',
'--epochs', type=int, default=300
'--batch-size', type=int, default=-1,   # 注意【问题8】的发生
'--imgsz', '--img', '--img-size', type=int, default=640,
'--adam', action='store_true', default=True, 

4.4.2 稀疏化训练与问题

执行如下命令,进行稀疏化训练

python train_sparity.py

在这里插入图片描述

【问题8】

loggers.on_params_update({"batch_size": batch_size})
AttributeError: 'Loggers' object has no attribute 'on_params_update'

貌似是autobatch的原因,所以把参数’–batch-size’, type=int, default=-1, 先改为固定值 default=2,此后,可以正常epoch0。但是仍然存在【问题5】的问题,虽然不影响训练,但是觉的还是应该把它解决,毕竟是AttributeError的问题。解决办法如下:

# pillow版本太新的原因,新版的getsize属性被删除掉了。
pip3 uninstall pillow
pip3 nstall pillow==9.5

【问题9】

Epoch0的val结束之后,报了如下问题

File "/home/user/hlj/MyTrain/yolov5prune_6.0/utils/callbacks.py", line 77, in run
logger['callback'](*args, **kwargs)
TypeError: Loggers.on_fit_epoch_end() takes 5 positional arguments but 6 were given

这个问题是由于自己为了解决【问题6】,把项目中的utils/loggers/init .py文件换成了官方的文件了,发现init.py文件中def on_fit_epoch_end(self, vals, bn_weights, epoch, best_fitness, fi)少bn_weights,在这个项目中把prune项目下这个文件重新拷贝一下好了。

4.5 剪枝

4.5.1 参数设置

​ 设置裁剪比例参数,可以从小到大试。注意cfg的模型文件需要和weights对应上,否则会出现运行prune 过程中出现键值不对应的问题,裁剪完成会保存对应的模型pruned_model.pt。

在prune.py文件中,修改如下参数

'--data', type=str, default=ROOT / 'data/my_yolov5.yaml',
'--weights', nargs='+', type=str, default=ROOT / 'runs/train/spaweight/last.pt'
'--cfg', type=str, default='./models/yolov5s.yaml',
'--percent', type=float, default=0.1,
'--batch-size', type=int, default=16, 
'--imgsz', '--img', '--img-size', type=int, default=640,

运行

python prune.py

【问题10】

SyntaxError: Non-UTF-8 code starting with '\xe5' in file /home/user/hlj/MyTrain/yolov5prune_6.0/prune.py on line 400, but no encoding declared; see https://peps.python.org/pep-0263/ for details

解决方法:找到对应的行,发现是注释的内容code的格式的问题,把它删掉或者把中文改成英文即可。

【问题11】

return func(*args, **kwargs)
TypeError: run() got an unexpected keyword argument 'cfg'

解决方式在prune.py的源码run()函数中,增加参数如下

cfg = './model/yolov5s.yaml'

4.5.2 剪枝

对稀疏化训练后的模型best.pt进行剪枝。

若参数已设置好了,直接执行python prune.py

python prune.py

否则,传入的weight为稀疏化训练得到的权重。

python prune.py --weights runs/train/exp_sparity/weights/best.pt --percent 0.5 --cfg models/yolov5s.yaml

裁剪完成会在根目录下保存对应的模型pruned_model.pt。

4.6 finetune剪枝的网络

4.6.1 参数设置

更改finetune_pruned.py的相关参数如下

'--weights', type=str, default=ROOT / 'pruned_model.pt',
'--cfg', type=str, default='./models/yolov5s.yaml',
'--data', type=str, default=ROOT / 'data/my_yolov5.yaml', 
'--epochs', type=int, default=100
'--batch-size', type=int, default=16, 
'--imgsz', '--img', '--img-size', type=int, default=640,
'--adam', action='store_true', default=True, 
'--workers', type=int, default=8, 
'--project', default=ROOT / 'runs/finetune',

4.6.2 finetune

若没有修改finetune_pruned.py中的参数,如下执行。

python finetune_pruned.py --weights pruned_model.pt --adam --epochs 100

由于直接修改了finetune_pruned.py中的参数,直接执行

python finetune_pruned.py

执行时,报了【问题9】,按照相关解决方法可fine_tune正常开始。

4.7 循环稀疏训练->剪枝->finetune网络

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

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

相关文章

kali 2023.3新增工具

在终端模拟器中运行 sudo apt update && sudo apt full-upgrade 命令来更新其安装 Kali Linux 2023.3 发布中包含了九个新工具&#xff0c;分别是&#xff1a; Calico&#xff1a;云原生网络和网络安全。 cri-tools&#xff1a;用于Kubelet容器运行时接口的命令行界面…

【无标题】AI在开发工具中的应用:自动代码生成

AI辅助开发工具的概述 随着人工智能&#xff08;AI&#xff09;技术的发展&#xff0c;越来越多的开发工具开始利用AI来辅助程序员的工作。其中一项重要的应用是自动代码生成。AI辅助开发工具能够通过学习大量的代码库和规范&#xff0c;分析程序员的需求&#xff0c;并自动生成…

论文阅读_模型结构_LoRA

name_en: LoRA: Low-Rank Adaptation of Large Language Models name_ch: LORA&#xff1a;大语言模型的低阶自适应 paper_addr: http://arxiv.org/abs/2106.09685 date_read: 2023-08-17 date_publish: 2021-10-16 tags: [‘深度学习’,‘大模型’] author: Edward J. Hu cita…

leetcode76. 最小覆盖子串(滑动窗口-java)

滑动窗口 最小覆盖子串滑动窗口代码 上期经典 最小覆盖子串 难度 - 困难 原题链接 - 最小覆盖字串 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 “” 。 注意&#xff1a; 对于 t…

【TypeScript】never 类型

在 TypeScript 中&#xff0c;never 是一种特殊的类型&#xff0c;表示永远不会发生的值或类型。它通常用于表示一些绝对不可能出现的情况&#xff0c;例如永远不会返回的函数类型或在某些条件下绝对不会发生的值。 以下是一些关于 never 类型的情况&#xff1a; 函数返回值…

大红喜庆版UI猜灯谜小程序源码/猜字谜微信小程序源码

今天给大家带来一款UI比较喜庆的猜灯谜小程序&#xff0c;大家看演示图的时候当然也是可以看得到那界面是多么的喜庆&#xff0c;而且新的一年也很快就来了,所以种种的界面可能都比较往喜庆方面去变吧。 这款小程序搭建是免服务器和域名的&#xff0c;只需要使用微信开发者工具…

243:vue+Openlayers 更改鼠标滚轮缩放地图大小,每次缩放小一点

第243个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayers项目中设置鼠标滚轮缩放地图大小,每次滑动一格滚轮,设定的值非默认值1。具体的设置方法,参考源代码。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源…

Java快速入门体验

Java快速入门体验 一、环境信息1.1 硬件信息1.2 软件信息 二、Maven安装2.1 Maven介绍2.2 Maven安装包下载2.3 Maven安装2.4 Maven初始化 三、Java安装3.1 JDK下载3.2 JDK安装3.3 JDK初始化 四、开发环境搭建4.1 安装开发工具4.2 关联Maven环境4.2.1 新建JAVA项目4.2.2 Maven与…

5G网关如何提升智慧乡村农业生产效率

得益于我国持续推进5G建设&#xff0c;截至今年5月&#xff0c;我国5G基站总数已达284.4万个&#xff0c;覆盖全国所有地级市、县城城区和9成以上的乡镇镇区&#xff0c;实现“镇镇通5G”&#xff0c;全面覆盖了从城市到农村的延伸。 依托5G网络的技术优势&#xff0c;智慧乡村…

有没有好用的微信管理软件?解决企业营销管理痛点

企业营销管理痛点&#xff1a; 1、如何提高员工跟进客户的能力和效率&#xff1f; 2、怎么杜绝飞单私单工作怠慢等问题&#xff1f; 3、微信好友太多无法实现精准营销&#xff1f; 4、如何第一时间知道员工的违规行为&#xff1f; 多微信聚合聊天 多个微信号聚合在一个界面…

Linux 打开U盘硬盘等报错 file type exfat not configured in kernel

目录 原因&#xff1a; 查看系统文件系统和当前系统版本 回归正题&#xff0c;如何解决报错 在centons 7中打开U盘&#xff0c;报错file type exfat not configured in kernel。 原因&#xff1a; 这是因为Linux采用的文件系统和我U盘的文件系统不一致引起。如下图&#xf…

在线ppt转pdf如何转换?用这一个方法就够了

在线PPT转PDF是一种将PPT文件转换为PDF格式的便捷且常用的工具。随着科技的发展&#xff0c;PPT已经成为了商务、教育等领域中最常用的演示工具之一。PDF格式具有较好的稳定性和兼容性。PPT文件可能因为不同的操作系统、软件版本或字体缺失等原因而导致显示不一致或乱码等问题&…

【数据结构练习】单链表OJ题(二)

目录 一、相交链表二、环形链表1三、环形链表2四、链表分割五、复制带随机指针的链表 一、相交链表 题目&#xff1a; 示例&#xff1a; 注意&#xff1a;不能根据节点的值来比较是否相交&#xff0c;而是根据节点在内存中是否指向相同的位置。 例如以上图&#xff1a; 链表…

ATFX汇市:美元指数疯狂上涨,英镑单日贬值近1%

环球汇市行情摘要—— 昨日&#xff0c;美元指数上涨0.55%&#xff0c;收盘在103.95点&#xff0c; 欧元贬值0.50%&#xff0c;收盘价1.0810点&#xff1b; 日元贬值0.69%&#xff0c;收盘价145.84点&#xff1b; 英镑贬值0.98%&#xff0c;收盘价1.2600点&#xff1b; 瑞…

火山引擎边缘云,助你沉浸式回忆童年

发现了吗&#xff1f;在抖音、西瓜视频上能观看4K修复的经典港片了&#xff01;得益于抖音、中国电影资料馆、火山引擎共同发起的“经典香港电影修复计划”&#xff0c;我们童年时期看过的《大话西游之大圣娶亲》《武状元苏乞儿》等22部港片以更清晰、流畅、颜色饱满的状态回归…

基于Java+SpringBoot+vue前后端分离可盈保险合同管理系统设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【数据库】使用ShardingSphere+Mybatis-Plus实现读写分离

书接上回&#xff1a;数据库调优方案中数据库主从复制&#xff0c;如何实现读写分离 ShardingSphere 实现读写分离的方式是通过配置数据源的方式&#xff0c;使得应用程序可以在执行读操作和写操作时分别访问不同的数据库实例。这样可以将读取操作分发到多个从库&#xff08;从…

十二、pikachu之URL重定向

文章目录 1、URL重定向概述2、实战3、URL跳转的几种方式:3.1 META标签内跳转3.2 javascript跳转3.3 header头跳转 1、URL重定向概述 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。如果后端采用了前端传进来的&#xff08;可能是用户传参&#xff0c;或者之前预埋…

Allegro平台如何利用测评打造爆款产品,优化listing提升曝光度!

Allegro是波兰本土最大的电商平台&#xff0c;1999年由波兰人自己创造成立&#xff0c;75%的波兰人都知道该网站&#xff0c;Allegro的品牌认知度在波兰高达98%。也是东欧“最大”拍卖网站。 波兰的消费者非常熟悉Allegro平台&#xff0c;大部分波兰人如果想要购买商品&#x…

[uniapp] scroll-view 简单实现 u-tabbar效果

文章目录 方案踩坑1.scroll-view 横向失败2.点击item不滚动?3. scrollLeft从哪里来? 效果图 方案 官方scroll-view 进行封装 配合属性 scroll-left Number/String 设置横向滚动条位置 即可 scroll-into-view 属性尝试过,方案较难实现 踩坑 1.scroll-view 横向失败 安装…