本项目基于tanluren/yolov3-channel-and-layer-pruning实现,将项目扩展到yolov5上。
项目的基本流程是,使用ultralytics/yolov5训练自己的数据集,在模型性能达到要求但速度未达到要求时,对模型进行剪枝。首先是稀疏化训练,稀疏化训练很重要,如果模型稀疏度不够,剪枝比例过大会导致剪枝后的模型map接近0。剪枝完成后对模型进行微调回复精度。
yolov5_prune:GitHub - ZJU-lishuang/yolov5_prune: yolov5 prune,Support V2, V3, V4 and V6 versions of yolov5
yolov3-channel-and-layer-pruning:GitHub - tanluren/yolov3-channel-and-layer-pruning: yolov3 yolov4 channel and layer pruning, Knowledge Distillation 层剪枝,通道剪枝,知识蒸馏
yolov5-v6:https://github.com/ZJU-lishuang/yolov5-v6
看起来还不错的博客:YOLOv5s 剪枝_m0_53608998的博客-CSDN博客_yolov5s剪枝
(1)作者是根据yolov3-pruning改的,详细的介绍在yolov3-prune的readme里面有,作者把前面基础训练和稀疏训练的代码放在另一个yolov5-v5的仓库里面
(2)基础训练是根据coco_hand数据集训练50个epoch
数据集的构建
-------------这部分是我的操作,不太正确但能行,正确的结构在“实际的数据集位置结构”中-----------
要单独下载数据集,然后用提供的脚本converter.py转换成可训练格式
把脚本放在yolov5-v6文件夹下,把路径指向data,把里面复制进去的hand_dataset文件夹转换成yolov5-v6文件夹下的images和labels.
把脚本生成的train.txt和valid.txt放到文件夹hand_data下
--------------------------------------------------------------------------------------------------------------------------------
实际的数据集位置结构:
然后报错找不到权重文件weights/yolov5s_v6.pt,懒得操作了,直接复制了比较近的yolov5的权重yolov5s.pt来训练
error:Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.
用下面的方法解决了
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
成功开始训练:
训练集中4096张图片,一个epoch 2min左右
训练50epoch结果;
跑一下推理:
每张图片在 0.005到0.007之间波动(这个应该是推理我感觉),全过程取7.5ms一张图片,大概是130-145帧左右。
报错:error: ambiguous option: --s could match --sparsity-regularization, --scale, --single-cls, --sync-bn, --save-period
解决:应该是没有 -- s这个参数,在train_sparsity.py里面找到比较对应的参数应该是scale了,默认设置是0.001和参数配置的要求一样,所以把 --s 0.001去掉就可以跑了
另外,在这里同样也出现了上面训练一样的Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.问题,用一样的方法解决
训练命令:
python train_sparsity.py --img 640 --batch 32 --epochs 50 --data data/coco_hand.yaml --cfg models/yolov5s.yaml --weights runs/train/s_hand13/weights/last.pt --name s_hand_sparsity -sr --prune 1
稀疏化训练,有一点掉点:
ps:
scale参数默认0.001,根据数据集,mAP,BN分布调整,数据分布广类别多的,或者稀疏时掉点厉害的适当调小s;-sr用于开启稀疏训练;--prune 0适用于prune.py,--prune 1 适用于其他剪枝策略。稀疏训练就是精度和稀疏度的博弈过程,如何寻找好的策略让稀疏后的模型保持高精度同时实现高稀疏度是值得研究的问题,大的s一般稀疏较快但精度掉的快,小的s一般稀疏较慢但精度掉的慢;配合大学习率会稀疏加快,后期小学习率有助于精度回升。
接下来的关键任务:
1、查看--prune 1稀疏训练结果
2、熟悉查看各种剪枝策略,不同稀疏化方法对应不同剪枝方法
3、能不能或者需不需要像yolov3-prune一样采用不同的s进行稀疏化训练,如果需要的话s的衰减怎么设置
4、Tensorboard中bn层的图像怎么看,看不懂
5、看train_sparsity.py中的稀疏化训练的部分
6、查看剪枝部分代码,看看yolov5这种BN层和卷积层没有一环套一环的结构怎么进行剪枝。
7、查看不同剪枝策略的实现,比如有shortcut和无shortcut分别怎么操作
8、像yolov3-prune中说的那样.py文件中含有epoch信息,在yolov5中有没有这种情况,什么时候是恢复训练,什么时候是从头开始训练。如果想要恢复训练可不可以先停下来调整一下s再继续训练,这能不能实现
整体效果还可以:
附上yolov5的结构图:
prune 1,50epoch结果:(s_hand_sparsity4)
prune 0,50epoch的结果:(s_hand_sparsity5)
(红色是prune 1的结果,蓝色是prune 0,灰白色是原训练)
prune 1+100epoch+s=0.001:(s_hand_sparsity11)
prune 1+120epoch+s=0.001:
parameter:lr0=0.01, lrf=0.1, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=0.05, cls=0.5, cls_pw=1.0, obj=1.0, obj_pw=1.0, iou_t=0.2, anchor_t=4.0, fl_gamma=0.0, hsv_h=0.015, hsv_s=0.7, hsv
_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0
命令:
python train_sparsity.py --img 640 --batch 32 --epochs 200 --data data/coco_hand.yaml --cfg models/yolov5s.yaml --weights runs/train/s_hand13/weights/last.pt --name s_hand_sparsity -sr --prune 1
结果:s_hand_sparsity13,跑到120左右的时候停电了
train.py+epoch 140:
s_hand14: 140epoch手动停掉了,跟50epoch的时候基本一致,而且精度上升的速度还比50epoch的时候慢了一点,猜测是训练schedule的原因
(3)尝试进行剪枝: