YOLOv5 模型剪枝与稀疏度实战指南:val.py 基线测试、0.3 稀疏度剪枝与精度影响解析
【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10
模型剪枝(Pruning)是提升深度模型推理效率的核心手段之一:通过将卷积层中不重要的权重置零,在几乎不改变推理速度的前提下获得稀疏模型,为进一步的稀疏推理加速与量化压缩打下基础。本指南基于 Ultralytics YOLOv5 系列的官方剪枝实践,完整讲解"先建立基线、再实施剪枝、后对比验证"的标准流程:在 COCO val2017 上先对 YOLOv5x 做 640 像素的正常验证,再通过torch_utils.prune()将其剪枝到 0.3 稀疏度并复测,最后逐项对比 mAP、AR 与推理速度的变化。读完本文,你将掌握 YOLOv5 剪枝测试的完整命令、输出解读方法,以及稀疏度对精度与速度影响的可量化评估能力。
环境准备:克隆仓库并安装依赖
在开始剪枝实验之前,需要准备一个可运行 YOLOv5 的 Python 环境。官方要求使用Python>=3.8.0,并安装requirements.txt中列出的依赖,其中包含PyTorch>=1.8。模型权重与数据集会在首次运行验证时,从最新 release 中自动下载。
git clone https://github.com/ultralytics/yolov5 # clone cd yolov5 pip install -r requirements.txt # install需要说明的是:本仓库(yolov10)基于统一的 Ultralytics 架构演进,仓库根目录的 requirements.txt 与 pyproject.toml 中定义了当前版本的运行时依赖与yolo命令行入口;而本指南所述val.py剪枝流程源自 YOLOv5 独立仓库的经典实践。本文以该经典流程为主体展开,并在后文给出其与当前仓库源码结构的对应关系。
第一步:正常运行验证,建立基线性能
剪枝前必须建立一个可供对比的基线。下面的命令使用YOLOv5x在COCO val2017上、以640 像素输入尺寸进行验证。yolov5x.pt是官方预训练权重中规模最大、精度最高的模型;如需测试其他规模,可替换为yolov5s.pt、yolov5m.pt、yolov5l.pt,也可以使用自己在自定义数据集上训练得到的检查点./weights/best.pt。
python val.py --weights yolov5x.pt --data coco.yaml --img 640 --half各参数含义如下:
| 参数 | 值 | 说明 |
|---|---|---|
--weights | yolov5x.pt | 待验证的模型权重文件,支持官方预训练权重或自训练权重 |
--data | coco.yaml | 数据集配置文件,声明图像路径、标签路径与类别数 |
--img | 640 | 输入图像尺寸(边长像素),与训练时保持一致 |
--half | - | 使用 FP16 半精度推理,可显著减少显存占用并加速 |
在 NVIDIA Tesla V100 上运行该命令的典型输出如下:
val: data=/content/yolov5/data/coco.yaml, weights=['yolov5x.pt'], batch_size=32, imgsz=640, conf_thres=0.001, iou_thres=0.65, task=val, device=, workers=8, single_cls=False, augment=False, verbose=False, save_txt=False, save_hybrid=False, save_conf=False, save_json=True, project=runs/val, name=exp, exist_ok=False, half=True, dnn=False YOLOv5 🚀 v6.0-224-g4c40933 torch 1.10.0+cu111 CUDA:0 (Tesla V100-SXM2-16GB, 16160MiB) Fusing layers... Model Summary: 444 layers, 86705005 parameters, 0 gradients val: Scanning '/content/datasets/coco/val2017.cache' images and labels... 4952 found, 48 missing, 0 empty, 0 corrupt: 100% 5000/5000 [00:00<?, ?it/s] Class Images Labels P R mAP@.5 mAP@.5:.95: 100% 157/157 [01:12<00:00, 2.16it/s] all 5000 36335 0.732 0.628 0.683 0.496 Speed: 0.1ms pre-process, 5.2ms inference, 1.7ms NMS per image at shape (32, 3, 640, 640) # <--- base speed Evaluating pycocotools mAP... saving runs/val/exp2/yolov5x_predictions.json... ... Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.507 # <--- base mAP Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.689 Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.552 Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.345 Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.559 Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.652 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.381 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.630 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.682 Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.526 Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.731 Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.829 Results saved to runs/val/exp需要记下三组基线关键数据,它们是后续对比剪枝效果的依据:
- 推理速度:约 0.1ms 预处理 + 5.2ms 推理 + 1.7ms NMS(每张图,batch 32 的 640×640 输入);
- COCO mAP@0.5:0.95:0.507;
- 模型规模:444 层,共 86,705,005 个参数。注意此时输出显示
0 gradients——这是模型处于验证(推理)模式、未计算梯度的正常表现。
第二步:剪枝测试,生成 0.30 稀疏度模型
基线建立后,重复上述验证流程,但先对模型执行剪枝。原文档的做法是修改val.py,在验证前调用torch_utils.prune(),将 YOLOv5x 剪枝到 0.3 全局稀疏度(global sparsity)。其示意实现为:遍历模型的所有nn.Conv2d模块,对权重做 L1 非结构化剪枝(将绝对值最小的 30% 权重置零),示例框架如下:
# 示意:在 val.py 验证前调用,将 YOLOv5x 剪枝到 0.3 稀疏度 def prune(model, amount=0.3): # 遍历所有卷积层,将权重中绝对值最小的 amount 比例置零 for module in model.modules(): if isinstance(module, torch.nn.Conv2d): # 以 L1 非结构化剪枝方式置零后,再移除剪枝掩码(保留零值权重) prune.l1_unstructured(module, name="weight", amount=amount) prune.remove(module, "weight") return model说明:
torch_utils.prune()是 YOLOv5 独立仓库utils/torch_utils.py中提供的剪枝工具。当前 yolov10 仓库的 ultralytics/utils/torch_utils.py 中未包含同名剪枝函数,但保留了剪枝实践所需的配套设施——例如fuse_conv_and_bn()(见 ultralytics/utils/torch_utils.py#L171-L198),它负责将Conv2d与BatchNorm2d融合为单个卷积层;剪枝通常在层融合前执行以取得最佳效果。
剪枝后运行同样的验证命令,输出中会出现一行关键日志Pruning model... 0.3 global sparsity,随后给出 30% 剪枝模型的完整指标:
val: data=/content/yolov5/data/coco.yaml, weights=['yolov5x.pt'], batch_size=32, imgsz=640, conf_thres=0.001, iou_thres=0.65, task=val, device=, workers=8, single_cls=False, augment=False, verbose=False, save_txt=False, save_hybrid=False, save_conf=False, save_json=True, project=runs/val, name=exp, exist_ok=False, half=True, dnn=False YOLOv5 🚀 v6.0-224-g4c40933 torch 1.10.0+cu111 CUDA:0 (Tesla V100-SXM2-16GB, 16160MiB) Fusing layers... Model Summary: 444 layers, 86705005 parameters, 0 gradients Pruning model... 0.3 global sparsity val: Scanning '/content/datasets/coco/val2017.cache' images and labels... 4952 found, 48 missing, 0 empty, 0 corrupt: 100% 5000/5000 [00:00<?, ?it/s] Class Images Labels P R mAP@.5 mAP@.5:.95: 100% 157/157 [01:11<00:00, 2.19it/s] all 5000 36335 0.724 0.614 0.671 0.478 Speed: 0.1ms pre-process, 5.2ms inference, 1.7ms NMS per image at shape (32, 3, 640, 640) # <--- prune mAP Evaluating pycocotools mAP... saving runs/val/exp3/yolov5x_predictions.json... ... Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.489 # <--- prune mAP Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.677 Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.537 Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.334 Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.542 Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.635 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.370 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.612 Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.664 Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.496 Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.722 Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.803 Results saved to runs/val/exp3结果解读:稀疏度的含义与精度-速度权衡
将基线结果与 0.3 稀疏度剪枝结果并排对比:
| 指标 | 基线(YOLOv5x) | 0.3 稀疏度剪枝 | 变化 |
|---|---|---|---|
| 模型稀疏度 | 0% | 30%(nn.Conv2d权重中有 30% 等于 0) | +30% |
| 推理速度 | 0.1ms + 5.2ms + 1.7ms | 0.1ms + 5.2ms + 1.7ms | 基本不变 |
| mAP@0.5:0.95 | 0.507 | 0.489 | -0.018 |
| mAP@0.5 | 0.689 | 0.677 | -0.012 |
| AR@maxDets=100 | 0.682 | 0.664 | -0.018 |
| P(all) | 0.732 | 0.724 | -0.008 |
| R(all) | 0.628 | 0.614 | -0.014 |
从结果可以得出两个关键结论:
"30% 稀疏度"的确切含义:剪枝后模型中
nn.Conv2d层的权重参数有30% 被置为 0。日志中的0.3 global sparsity表示这是对整个模型全局的稀疏度目标,而非逐层固定比例——各层被剪掉的比例由权重自身的绝对值分布决定,绝对值越小的权重越先被剪掉。推理时间几乎不变,精度轻微下降:在常规(稠密)推理引擎上,剪枝后模型的总参数数量没有变化(模型结构未变,只是部分权重归零),因此前向计算时间基本一致;而 AP、AR 均有小幅下降(mAP@0.5:0.95 从 0.507 降至 0.489)。这正是非结构化剪枝的典型特征:权重置零本身不直接带来稠密引擎的速度收益,其价值在于为后续稀疏感知(sparsity-aware)推理、量化压缩和模型瘦身留出空间。要想把 30% 的稀疏度真正转化为推理加速,需要配合专门针对稀疏模型优化的运行时,或在此基础上做结构化剪枝、层剪枝。
从源码结构看剪枝的配套基础
剪枝实践不是孤立的一个函数,它与模型的卷积层组织、层融合和验证流程紧密相关。从当前仓库源码结构可以印证以下几点:
- 验证流程:本仓库中与
val.py等价的目标检测验证逻辑位于 ultralytics/models/yolo/detect/val.py,其继承自 ultralytics/engine/validator.py 中的BaseValidator,负责数据加载、前向推理、指标统计与结果保存;分类、分割、姿态、旋转框等任务各有对应的val.py(见 ultralytics/models/yolo/ 目录)。 - 层融合:fuse_conv_and_bn() 是剪枝与导出实践中的常见前置步骤,它将
Conv2d与BatchNorm2d的权重、偏置按 BatchNorm 的均值/方差折算进卷积核,得到无 BatchNorm 的等效单层卷积——剪枝时优先关注的就是这类可融合、可稀疏化的卷积层。 - 模型结构:剪枝操作的直接对象是各 YAML 配置展开后的
nn.Conv2d模块。本仓库的 YOLO 系列模型结构配置见 ultralytics/cfg/models/,其中 YOLOv10 的模型配置位于 ultralytics/cfg/models/v10/;而 YOLOv5 的经典结构配置(如 ultralytics/cfg/models/v5/yolov5.yaml)也在本仓库中保留,可作为理解剪枝作用对象的参考。
进阶阅读:从剪枝到稀疏推理
剪枝只是稀疏化路线图的第一步。想要让稀疏度真正转化为端到端收益,业界常见的进阶路线是把**剪枝(Pruning)与量化(Quantization)**结合,再配合稀疏感知的推理引擎。本仓库的 docs/en/yolov5/tutorials/neural_magic_pruning_quantization.md 详细介绍了利用 Neural Magic 的 DeepSparse 部署经过剪枝+量化的 YOLOv5 稀疏模型:DeepSparse 是稀疏感知运行时,前向传播时会跳过被置零的参数,从而把稀疏度直接换算成计算量的缩减。该教程还提供了deepsparse.benchmark对比 ONNX Runtime 的完整基准测试方法,可与本指南的精度对比实验配套使用,形成"剪枝→稀疏化→推理加速"的完整闭环。更多 YOLOv5 系列教程的目录见 docs/en/yolov5/index.md。
支持的运行环境
Ultralytics 为剪枝实验提供了多种开箱即用的环境,均预装了 CUDA、CUDNN、Python 与 PyTorch 等核心依赖,可按需选择:
- 免费 GPU Notebook:Paperspace Gradient、Google Colab、Kaggle 等平台可直接运行本教程对应的 notebook;
- Google Cloud:GCP 快速入门指南;
- Amazon:AWS 快速入门指南;
- Azure:AzureML 快速入门指南;
- Docker:Docker 快速入门指南。
项目状态与持续集成验证
YOLOv5 系列项目通过持续集成(CI)测试保障功能的稳定性,每 24 小时以及每次新提交都会在 macOS、Windows 和 Ubuntu 上运行测试,覆盖训练、验证、推理、导出与基准测试五个关键环节,确保剪枝这类实验流程建立在可靠可复现的基础之上。本仓库对应地维护了自动化测试套件,例如 tests/test_engine.py、tests/test_cli.py 与 tests/test_python.py,可用于回归验证模型加载、命令行入口与 Python API 在改动后的行为一致性。
结语
通过本指南,你已经掌握了 YOLOv5 模型剪枝的完整实验方法:先在 COCO val2017 上跑通基线验证并记录速度与精度数据,再调用剪枝工具将模型稀疏化到 0.3 并复测对比。实验数据清楚地展示了非结构化剪枝的特性——30% 的权重被置零,推理时间几乎不变,mAP 仅有轻微下降。这套"基线 → 剪枝 → 对比"的评估流程是后续一切稀疏化优化工作的基础:当你希望把稀疏度转化为实际速度时,即可沿着本仓库中 Neural Magic 稀疏推理的进阶路线继续推进。
【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考