Cắt tỉa mô hình và độ thưa thớt trong YOLOv5

📚 Hướng dẫn này giải thích cách áp dụng pruning (cắt tỉa) cho các mô hình YOLOv5 🚀 để tạo ra các mạng hiệu quả hơn trong khi vẫn duy trì hiệu suất.

Cắt tỉa mô hình (Model Pruning) là gì?

Model pruning là một kỹ thuật được sử dụng để giảm kích thước và độ phức tạp của mạng thần kinh bằng cách loại bỏ các tham số (trọng số và kết nối) ít quan trọng hơn. Quá trình này tạo ra một mô hình hiệu quả hơn với một số lợi ích:

  • Giảm kích thước mô hình để triển khai dễ dàng hơn trên các thiết bị hạn chế về tài nguyên
  • Tốc độ inference nhanh hơn với tác động tối thiểu đến độ chính xác
  • Giảm mức sử dụng bộ nhớ và tiêu thụ năng lượng
  • Cải thiện hiệu quả tổng thể cho các ứng dụng thời gian thực

Pruning hoạt động bằng cách xác định và loại bỏ các tham số đóng góp ít nhất vào hiệu suất của mô hình, dẫn đến một mô hình nhẹ hơn với độ chính xác tương đương.

Trước khi Bạn Bắt đầu

Sao chép repo và cài đặt requirements.txt trong môi trường Python>=3.8.0, bao gồm PyTorch>=1.8. Modelsdatasets sẽ tự động tải xuống từ bản YOLOv5 release mới nhất.

git clone https://github.com/ultralytics/yolov5 # clone
cd yolov5
pip install -r requirements.txt # install

Kiểm tra hiệu suất cơ sở

Trước khi pruning, hãy thiết lập một hiệu suất cơ sở để so sánh. Lệnh này kiểm tra YOLOv5x trên COCO val2017 với kích thước ảnh 640 pixel. yolov5x.pt là mô hình lớn nhất và chính xác nhất hiện có. Các tùy chọn khác bao gồm yolov5s.pt, yolov5m.ptyolov5l.pt, hoặc checkpoint của riêng bạn từ việc huấn luyện trên tập dữ liệu tùy chỉnh ./weights/best.pt. Để biết chi tiết về tất cả các mô hình có sẵn, hãy xem bảng trong README.

python val.py --weights yolov5x.pt --data coco.yaml --img 640 --half

Đầu ra:

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/exp-2/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

Áp dụng Pruning cho YOLOv5x (Độ thưa thớt 30%)

Chúng ta có thể áp dụng pruning cho mô hình bằng lệnh torch_utils.prune() được định nghĩa trong utils/torch_utils.py. Để kiểm tra một mô hình đã được prune, chúng ta cập nhật val.py để prune YOLOv5x tới độ thưa thớt 0.3 (30% trọng số được đặt bằng 0):

YOLOv5 model pruning to 30% sparsity code

Đầu ra sau khi prune 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/exp-3/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/exp-3

Phân tích kết quả

Từ các kết quả, chúng ta có thể quan sát thấy:

  • Đạt độ thưa thớt 30%: 30% các tham số trọng số của mô hình trong các lớp nn.Conv2d hiện bằng 0
  • Thời gian inference không đổi: Mặc dù đã prune, tốc độ xử lý về cơ bản vẫn như cũ
  • Tác động hiệu suất tối thiểu: mAP giảm nhẹ từ 0.507 xuống 0.489 (chỉ giảm 3.6%)
  • Giảm kích thước mô hình: Mô hình đã prune yêu cầu ít bộ nhớ hơn để lưu trữ

Điều này chứng minh rằng pruning có thể giảm đáng kể độ phức tạp của mô hình với tác động nhỏ đến hiệu suất, khiến nó trở thành một kỹ thuật tối ưu hóa hiệu quả cho việc triển khai trong các môi trường hạn chế về tài nguyên.

Fine-tuning các mô hình đã Prune

Để có kết quả tốt nhất, các mô hình đã prune nên được fine-tune sau khi prune để phục hồi độ chính xác. Điều này có thể được thực hiện bằng cách:

  1. Áp dụng pruning với mức độ thưa thớt mong muốn
  2. Huấn luyện mô hình đã prune trong một vài epoch với tốc độ học (learning rate) thấp hơn
  3. Đánh giá mô hình đã fine-tune và prune so với mức cơ sở

Quá trình này giúp các tham số còn lại thích nghi để bù đắp cho các kết nối đã bị loại bỏ, thường phục hồi hầu hết hoặc toàn bộ độ chính xác ban đầu.

Môi trường được hỗ trợ

Ultralytics cung cấp nhiều môi trường sẵn sàng sử dụng, mỗi môi trường đều được cài đặt sẵn các phụ thuộc thiết yếu như CUDA, CUDNN, Python, và PyTorch để giúp bạn bắt đầu dự án của mình.

Trạng thái dự án

YOLOv5 CI

Huy hiệu này cho biết tất cả các bài kiểm thử Tích hợp liên tục (CI) của YOLOv5 GitHub Actions đều đã vượt qua thành công. Các bài kiểm thử CI này kiểm tra nghiêm ngặt chức năng và hiệu suất của YOLOv5 trên nhiều khía cạnh quan trọng: huấn luyện, xác thực, suy luận, xuất mô hình, và điểm chuẩn. Chúng đảm bảo hoạt động nhất quán và tin cậy trên macOS, Windows và Ubuntu, với các bài kiểm thử được tiến hành mỗi 24 giờ và sau mỗi lần commit mới.

Bình luận