Potatura e sparsità del modello in YOLOv5
📚 Questa guida spiega come applicare la potatura (pruning) ai modelli YOLOv5 🚀 per creare reti più efficienti mantenendo le prestazioni.
Cos'è la potatura del modello?
La potatura del modello è una tecnica utilizzata per ridurre le dimensioni e la complessità delle reti neurali rimuovendo i parametri meno importanti (pesi e connessioni). Questo processo crea un modello più efficiente con diversi vantaggi:
- Dimensioni del modello ridotte per un deployment più semplice su dispositivi con risorse limitate
- Velocità di inferenza più elevate con un impatto minimo sull'accuratezza
- Minore utilizzo di memoria e consumo energetico
- Maggiore efficienza complessiva per applicazioni in tempo reale
La potatura funziona identificando e rimuovendo i parametri che contribuiscono minimamente alle prestazioni del modello, ottenendo un modello più leggero con un'accuratezza simile.
Prima di iniziare
Clona il repository e installa requirements.txt in un ambiente Python>=3.8.0, incluso PyTorch>=1.8. Modelli e dataset si scaricano automaticamente dall'ultima release di YOLOv5.
git clone https://github.com/ultralytics/yolov5 # clone
cd yolov5
pip install -r requirements.txt # installTesta le prestazioni di base
Prima della potatura, stabilisci una linea di base delle prestazioni per fare un confronto. Questo comando testa YOLOv5x su COCO val2017 a una dimensione dell'immagine di 640 pixel. yolov5x.pt è il modello più grande e accurato disponibile. Altre opzioni sono yolov5s.pt, yolov5m.pt e yolov5l.pt, oppure il tuo checkpoint derivante dall'addestramento di un dataset personalizzato ./weights/best.pt. Per i dettagli su tutti i modelli disponibili, consulta la tabella nel README.
python val.py --weights yolov5x.pt --data coco.yaml --img 640 --halfOutput:
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/expApplica la potatura a YOLOv5x (30% di sparsità)
Possiamo applicare la potatura al modello utilizzando il comando torch_utils.prune() definito in utils/torch_utils.py. Per testare un modello potato, aggiorniamo val.py per ridurre YOLOv5x a una sparsità di 0,3 (30% dei pesi impostati a zero):
Output potato al 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-3Analisi dei risultati
Dai risultati possiamo osservare:
- Raggiunta una sparsità del 30%: il 30% dei parametri dei pesi del modello nei layer
nn.Conv2dsono ora zero - Il tempo di inferenza rimane invariato: nonostante la potatura, la velocità di elaborazione è sostanzialmente la stessa
- Impatto minimo sulle prestazioni: l'mAP è sceso leggermente da 0,507 a 0,489 (solo il 3,6% di riduzione)
- Riduzione delle dimensioni del modello: il modello potato richiede meno memoria per l'archiviazione
Ciò dimostra che la potatura può ridurre significativamente la complessità del modello con solo un impatto minore sulle prestazioni, rendendola una tecnica di ottimizzazione efficace per il deployment in ambienti con risorse limitate.
Fine-tuning dei modelli potati
Per ottenere i migliori risultati, i modelli potati dovrebbero essere sottoposti a fine-tuning dopo la potatura per recuperare l'accuratezza. Questo può essere fatto:
- Applicando la potatura con un livello di sparsità desiderato
- Addestrando il modello potato per alcune epoche con un tasso di apprendimento inferiore
- Valutando il modello potato sottoposto a fine-tuning rispetto alla linea di base
Questo processo aiuta i parametri rimanenti ad adattarsi per compensare le connessioni rimosse, recuperando spesso la maggior parte o tutta l'accuratezza originale.
Ambienti supportati
Ultralytics fornisce una serie di ambienti pronti all'uso, ciascuno preinstallato con dipendenze essenziali come CUDA, CUDNN, Python e PyTorch, per avviare rapidamente i tuoi progetti.
- Notebook GPU gratuiti:
- Google Cloud: Guida rapida GCP
- Amazon: Guida rapida AWS
- Azure: Guida rapida AzureML
- Docker: Guida rapida Docker
Stato del progetto
Questo badge indica che tutti i test di Continuous Integration (CI) di YOLOv5 GitHub Actions vengono superati con successo. Questi test CI verificano rigorosamente la funzionalità e le prestazioni di YOLOv5 su vari aspetti chiave: training, validation, inference, export e benchmarks. Garantiscono un funzionamento coerente e affidabile su macOS, Windows e Ubuntu, con test condotti ogni 24 ore e ad ogni nuovo commit.