赞
踩
学习参考链接:(转发)深度学习模型压缩与加速理论与实战(一):模型剪枝 - AHU-WangXiao - 博客园 (cnblogs.com)
剪枝顾名思义,就是通过一些算法或规则删去一些不重要的部分,来使模型变得更加紧凑,减小计算或者搜索的复杂度。
它包括四个迭代步骤:
1. 评估一个预先训练的深度模型中每个组件的重要性;
2. 剔除对模型推理不重要的成分;
3. 微调修剪模型,以弥补潜在的暂时性能下降;
4. 对微调后的模型进行评估,确定修剪后的模型是否适合部署。为了防止过度剪枝,最好采用增量剪枝策略。
对一个深度卷积系的模型而言,剪枝操作之前需要对模型进行稀疏化训练,从而根据稀疏情况进行模型组件的选择,通常来说,稀疏化有四个粒度的稀疏方式,分别是weight-level,kernel-level,channel-level,layer-level。weight-level具有最高的灵活性和泛化性能,也能获得更高的压缩比率,但是它通常需要特殊的软硬件加速器才能在稀疏模型上快速推理。相反,layer-level稀疏化不需要特殊的包做推理加速,而channel-level稀疏化在灵活性和实现上做了一个平衡,它可以被应用到任何典型的CNN或者全连接层(将每个神经元看作一个通道)。模型变短(layer-level)和模型变窄(channel-level)
层剪枝:
层剪枝是在之前的通道剪枝策略基础上衍生出来的,在通道剪枝后进行层剪枝操作。若针对每一个Darknet的shortcut层前一个CBL进行评价,对各层的γ均值进行排序,取最小的N层(N是实验中可调的超参数)进行层剪枝。为保证Darknet结构完整,这里每剪一个shortcut结构,会同时剪掉一个shortcut层和它前面的两个卷积层。Darknet中有23处shortcut,剪掉8个shortcut就是剪掉了24个层,剪掉16个shortcut就是剪掉了48个层,总共有69个层的剪层空间。
微调精度恢复训练:
在进行通道剪枝和层剪枝之后,一般精度都会有不同程度的下降,这取决于剪枝的力度,但一般都可以通过微调剪枝之后的模型后再训练进行精度恢复,由于剪枝后的模型更加简单,所以往往在任务目标不那么复杂的情况下,具有更好的泛化性能(即剪枝前的模型可能过拟合于任务的数据集,而剪枝并且微调训练后的模型精度可能表现的更好,这在我们的实验中是有体现的)。即使是微调训练精度恢复不上去,依然可以采用知识蒸馏技术,将剪枝前的模型作为教师模型,引导剪枝后的学生模型进行蒸馏训练。需要强调的是,蒸馏在这里只是辅助微调,如果注重精度优先,剪枝时尽量剪不掉点的比例,这时蒸馏的作用也不大;如果注重速度,剪枝比例较大,导致模型精度下降较多,可以结合蒸馏提升精度。或者如果微调后精度能很好的恢复上去,也不要采用蒸馏策略,因为蒸馏策略会限制学生网络的精度上限,且蒸馏训练会需要更大的GPU内存来实现,增加了实验的成本。
项目yolov5
训练数据集:Dogs_and_People
预训练权重:yolov5s.pt
训练模型:yolov5s.yaml
示例代码
python train.py --img 640 --batch 32 --epochs 200 --weights yolov5s.pt --data data/peranddog.yaml --cfg models/yolov5s.yaml --name run exp
训练结果:
–prune 0 适用于通道剪枝策略一,–prune 1 适用于其他剪枝策略。
项目yolov5
训练数据集:Dogs_and_People
训练权重:runs/train/exp/weights/best.pt
训练模型:yolov5s.yaml
示例代码
python train_sparsity.py --img 640 --batch 32 --epochs 100 --data data/peranddog.yaml --cfg models/yolov5s.yaml --weights runs/train/exp/weights/best.pt --name s_dog_sparsity -sr --scale 0.001 --prune 0
训练结果:
不对shortcut直连的层进行剪枝,避免维度处理。
python prune_yolov5s.py --cfg cfg/yolov5s_v6.cfg --data data/peranddog.data --weights weights/sparsity.pt --percent 0.8
训练结果:
对shortcut层也进行了剪枝,剪枝采用每组shortcut中第一个卷积层的mask。
python shortcut_prune_yolov5s.py --cfg cfg/yolov5s_v6.cfg --data data/peranddog.data --weights weights/sparsity.pt --percent 0.3
训练结果:
先以全局阈值找出各卷积层的mask,然后对于每组shortcut,它将相连的各卷积层的剪枝mask取并集,用merge后的mask进行剪枝。
python slim_prune_yolov5s.py --cfg cfg/yolov5s_v6.cfg --data data/peranddog.data --weights weights/sparsity.pt --global_percent 0.8 --layer_keep 0.01
训练结果:
在硬件部署上发现,模型剪枝率相同时,通道数为8的倍数速度最快。(采坑:需要将硬件性能开启到最大)
示例代码
python slim_prune_yolov5s_8x.py --cfg cfg/yolov5s_v6.cfg --data data/peranddog.data --weights weights/sparsity.pt --global_percent 0.5 --layer_keep 0.01 --img_size 640
训练结果:
项目yolov5
示例代码
python prune_finetune.py --img 640 --batch 32 --epochs 10 --data data/peranddog.yaml --cfg ./cfg/prune_0.5_keep_0.01_8x_yolov5s_v6.cfg --weights ./weights/prune_0.5_keep_0.01_8x_sparsity.pt --name s_dog_finetune
训练结果:
项目yolov5
示例代码
python prune_finetune.py --img 640 --batch 32 --epochs 10 --data data/peranddog.yaml --cfg ./cfg/prune_0.5_keep_0.01_8x_yolov5s_v6.cfg --weights ./weights/prune_0.5_keep_0.01_8x_sparsity.pt --name s_dog_finetune_distill --distill --t_weight yolov5s.pt
训练结果:
项目yolov5
示例代码
python detect.py --weights weights/distall.pt --img 640 --conf 0.7 --source data/images
训练结果:
遇见问题:
跑通道剪枝策略时出现以下类似错误
AttributeError: 'collections.OrderedDict' object has no attribute 'float'
错误原因:
(1)使用自己 的数据集时,数据集与源代码的数据集的类别数不同,没有修改成对应的类别数
解决办法:修改cfg文件,把classes和filters进行修改(filters=(classes+5)*3),对应自己的数据集类别数,注意yolo层有三层,直接把cfg文件拉到最后,从最后开始往上改三层
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CwTD6eiI-1678257178406)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230308142336791.png)]
(2)权重文件即pt文件路径太深
解决办法:把得到的权重文件,复制到路径浅的地方
解决办法:修改cfg文件,把classes和filters进行修改(filters=(classes+5)*3),对应自己的数据集类别数,注意yolo层有三层,直接把cfg文件拉到最后,从最后开始往上改三层
(2)权重文件即pt文件路径太深
解决办法:把得到的权重文件,复制到路径浅的地方
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。