YOLOv5의 모델 프루닝 및 희소성#
📚 이 가이드에서는 성능을 유지하면서 더 효율적인 네트워크를 생성하기 위해 YOLOv5 🚀 모델에 프루닝을 적용하는 방법을 설명합니다.
모델 프루닝이란 무엇인가요?#
모델 프루닝은 중요도가 낮은 파라미터(가중치 및 연결)를 제거하여 신경망의 크기와 복잡성을 줄이는 기술입니다. 이 프로세스를 통해 다음과 같은 여러 이점을 제공하는 더욱 효율적인 모델을 생성할 수 있습니다:
- 리소스가 제한된 디바이스에 더욱 쉽게 배포할 수 있도록 모델 크기 감소
- 정확도에 미치는 영향은 최소화하면서 추론 속도 향상
- 메모리 사용량 및 에너지 소비 감소
- 실시간 애플리케이션의 전반적인 효율성 향상
프루닝은 모델 성능에 미치는 영향이 적은 파라미터를 식별하고 제거하여, 유사한 정확도를 유지하면서 더욱 경량화된 모델을 생성하는 방식으로 작동합니다.
시작하기 전에#
Python>=3.8.0 환경에서 requirements.txt를 사용하여 리포지토리를 클론하고 설치합니다. 여기에는 PyTorch>=1.8도 포함됩니다. 모델과 데이터셋은 최신 YOLOv5 릴리스에서 자동으로 다운로드됩니다.
git clone https://github.com/ultralytics/yolov5 # clone
cd yolov5
pip install -r requirements.txt # install기준 성능 테스트#
프루닝하기 전에 비교 기준으로 사용할 기준 성능을 설정합니다. 이 명령은 이미지 크기 640픽셀에서 COCO val2017에 대해 YOLOv5x를 테스트합니다. yolov5x.pt은 사용 가능한 모델 중 가장 크고 정확한 모델입니다. 다른 옵션으로는 yolov5s.pt, yolov5m.pt 및 yolov5l.pt이 있으며, 사용자 지정 데이터 세트 학습에서 생성한 자체 체크포인트 ./weights/best.pt를 사용할 수도 있습니다. 사용 가능한 모든 모델에 대한 자세한 내용은 README의 표를 참조하세요.
python val.py --weights yolov5x.pt --data coco.yaml --img 640 --half출력:
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_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/exp2YOLOv5x에 프루닝 적용(희소성 30%)#
utils/torch_utils.py에 정의된 torch_utils.prune() 명령을 사용하여 모델에 프루닝을 적용할 수 있습니다. 프루닝된 모델을 테스트하려면 val.py를 업데이트하여 YOLOv5x를 희소성 0.3(가중치의 30%를 0으로 설정)으로 프루닝합니다:
프루닝 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_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 speed
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결과 분석#
결과에서 다음을 확인할 수 있습니다:
- 희소성 30% 달성: 이제
nn.Conv2d레이어에 있는 모델 가중치 파라미터의 30%가 0입니다. - 추론 시간 변화 없음: 프루닝에도 불구하고 처리 속도는 사실상 동일하게 유지됩니다.
- 성능에 미치는 영향 최소화: mAP가 0.507에서 0.489로 소폭 감소했습니다(감소폭은 3.6%에 불과).
- 모델 크기 감소: 프루닝된 모델은 저장에 더 적은 메모리를 필요로 합니다.
이는 프루닝이 성능에는 약간의 영향만 미치면서 모델 복잡성을 크게 줄일 수 있음을 보여주며, 리소스가 제한된 환경에 배포하기 위한 효과적인 최적화 기법입니다.
프루닝된 모델의 파인 튜닝#
최상의 결과를 얻으려면 프루닝 후 프루닝된 모델을 파인 튜닝하여 정확도를 회복해야 합니다. 다음과 같은 방식으로 수행할 수 있습니다:
- 원하는 희소성 수준으로 프루닝 적용
- 더 낮은 학습률로 프루닝된 모델을 몇 개의 epoch 동안 학습
- 기준 모델과 비교하여 파인 튜닝된 프루닝 모델 평가
이 프로세스를 통해 남아 있는 파라미터가 제거된 연결을 보완하도록 조정되며, 원래 정확도의 대부분 또는 전부를 회복하는 경우가 많습니다.
지원 환경#
Ultralytics는 프로젝트를 바로 시작할 수 있도록 CUDA, CUDNN, Python, PyTorch와 같은 필수 종속성이 사전 설치된 다양한 즉시 사용 가능한 환경을 제공합니다.
- 무료 GPU 노트북:
- Google Cloud: GCP 빠른 시작 가이드
- Amazon: AWS 빠른 시작 가이드
- Azure: AzureML 빠른 시작 가이드
- Docker: Docker 빠른 시작 가이드
프로젝트 상태#
이 배지는 모든 YOLOv5 GitHub Actions 지속적 통합 (CI) 테스트가 성공적으로 통과했음을 나타냅니다. 이러한 CI 테스트는 학습, 검증, 추론, 내보내기, 벤치마크 등 여러 주요 측면에서 YOLOv5의 기능과 성능을 엄격하게 점검합니다. 또한 macOS, Windows, Ubuntu에서 일관되고 안정적으로 작동하는지 확인하며, 24시간마다 그리고 새 커밋이 생성될 때마다 테스트를 수행합니다.
FAQ#
비구조적 가지치기는 가중치를 0으로 설정하지만 텐서 모양은 그대로 유지하므로, 밀집 PyTorch 커널이 동일한 양의 연산을 수행합니다. 속도를 높이려면 DeepSparse와 같은 희소성 인식 런타임이나 전체 채널을 제거하는 구조적 가지치기가 필요합니다.
검증이나 내보내기 전에
utils/torch_utils.py에서 헬퍼를 호출하세요.from utils.torch_utils import prune prune(model, amount=0.3) # 30% global sparsity on nn.Conv2d weights0.3에서 시작하여 mAP를 측정하세요. YOLOv5x는 미세 조정 없이 30% 희소성에서 약 3.6%의 mAP를 잃었습니다. 더 높은 희소성 수준에서는 일반적으로 정확도를 회복하기 위해 낮은 학습률로 몇 에폭 동안 재학습이 필요합니다.
네. 0으로 설정된 가중치는 다른 가중치와 마찬가지로 저장되므로
export.py이 변경 없이 작동합니다. 파일 크기는 대상 형식이나 런타임이 희소 텐서를 압축하는 경우에만 줄어듭니다.