Poda e esparsidade de modelos em YOLOv5#
📚 Este guia explica como aplicar poda a modelos YOLOv5 🚀 para criar redes mais eficientes, mantendo o desempenho.
O que é a poda de modelos?#
A poda de modelos é uma técnica utilizada para reduzir o tamanho e a complexidade das redes neuronais, removendo parâmetros menos importantes (pesos e conexões). Este processo cria um modelo mais eficiente com várias vantagens:
- Tamanho reduzido do modelo para facilitar a implementação em dispositivos com recursos limitados
- Inferência mais rápida com impacto mínimo na precisão
- Menor utilização de memória e consumo de energia
- Maior eficiência geral para aplicações em tempo real
A poda funciona identificando e removendo parâmetros que contribuem minimamente para o desempenho do modelo, resultando num modelo mais leve com precisão semelhante.
Antes de Começares#
Clona o repositório e instala o requirements.txt num ambiente Python>=3.8.0, incluindo PyTorch>=1.8. Os modelos e os conjuntos de dados são transferidos automaticamente a partir da versão mais recente do YOLOv5.
git clone https://github.com/ultralytics/yolov5 # clone
cd yolov5
pip install -r requirements.txt # installTestar o desempenho de referência#
Antes da poda, estabelece um desempenho de referência para comparação. Este comando testa o YOLOv5x no COCO val2017 com um tamanho de imagem de 640 píxeis. yolov5x.pt é o maior e mais preciso modelo disponível. Outras opções são yolov5s.pt, yolov5m.pt e yolov5l.pt, ou o teu próprio checkpoint do treino de um conjunto de dados personalizado ./weights/best.pt. Para obter detalhes sobre todos os modelos disponíveis, consulta a tabela do README.
python val.py --weights yolov5x.pt --data coco.yaml --img 640 --halfSaída:
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/exp2Aplicar poda ao YOLOv5x (30% de esparsidade)#
Podemos aplicar a poda ao modelo utilizando o comando torch_utils.prune() definido em utils/torch_utils.py. Para testar um modelo podado, atualizamos val.py para podar o YOLOv5x até uma esparsidade de 0,3 (30% dos pesos definidos como zero):
Saída com 30% de poda:
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/exp3Análise dos resultados#
A partir dos resultados, podemos observar:
- Esparsidade de 30% alcançada: 30% dos parâmetros de peso do modelo nas camadas
nn.Conv2dsão agora zero - O tempo de inferência permanece inalterado: apesar da poda, a velocidade de processamento é essencialmente a mesma
- Impacto mínimo no desempenho: o mAP diminuiu ligeiramente de 0.507 para 0.489 (apenas uma redução de 3.6%)
- Redução do tamanho do modelo: o modelo podado requer menos memória para armazenamento
Isto demonstra que a poda pode reduzir significativamente a complexidade do modelo com apenas um impacto ligeiro no desempenho, tornando-a uma técnica de otimização eficaz para a implementação em ambientes com recursos limitados.
Ajuste fino de modelos podados#
Para obter os melhores resultados, os modelos podados devem ser ajustados após a poda para recuperar a precisão. Isto pode ser feito através de:
- Aplicar a poda com o nível de esparsidade pretendido
- Treinar o modelo podado durante algumas épocas com uma taxa de aprendizagem mais baixa
- Avaliar o modelo podado ajustado em comparação com o modelo de referência
Este processo ajuda os parâmetros restantes a adaptarem-se para compensar as conexões removidas, recuperando frequentemente a maior parte ou toda a precisão original.
Ambientes suportados#
A Ultralytics disponibiliza vários ambientes prontos a utilizar, cada um com dependências essenciais pré-instaladas, como CUDA, CUDNN, Python e PyTorch, para iniciares os teus projetos.
- Notebooks GPU gratuitos:
- Google Cloud: Guia de início rápido do GCP
- Amazon: Guia de início rápido da AWS
- Azure: Guia de início rápido do AzureML
- Docker: Guia de início rápido do Docker
Estado do projeto#
Este selo indica que todos os testes de Integração Contínua (CI) das GitHub Actions do YOLOv5 estão a passar com sucesso. Estes testes de CI verificam rigorosamente a funcionalidade e o desempenho do YOLOv5 em vários aspetos importantes: treino, validação, inferência, exportação e benchmarks. Garantem um funcionamento consistente e fiável no macOS, Windows e Ubuntu, com testes realizados a cada 24 horas e após cada novo commit.