Evolução de hiperparâmetros para o YOLOv5

📚 Este guia explica a evolução de hiperparâmetros para o YOLOv5 🚀. A evolução de hiperparâmetros é um método de Otimização de Hiperparâmetros que utiliza um Algoritmo Genético (GA) para otimização.

Hiperparâmetros em aprendizado de máquina controlam vários aspectos do treinamento, e encontrar valores ideais para eles pode ser um desafio. Métodos tradicionais, como buscas em grade (grid searches), podem rapidamente se tornar inviáveis devido a:

  1. Ao alto espaço de busca dimensional
  2. Às correlações desconhecidas entre as dimensões
  3. À natureza dispendiosa de avaliar a aptidão em cada ponto

Isso torna os algoritmos genéticos candidatos adequados para buscas de hiperparâmetros.

Antes de começares

Clone o repositório e instale os requirements.txt em um ambiente Python>=3.8.0, incluindo PyTorch>=1.8. Modelos e datasets são baixados automaticamente a partir da última release do YOLOv5.

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

1. Inicializar Hiperparâmetros

O YOLOv5 possui cerca de 30 hiperparâmetros usados para diversas configurações de treinamento. Eles são definidos em arquivos *.yaml no diretório /data/hyps. Estimativas iniciais melhores produzirão resultados finais melhores, por isso é importante inicializar esses valores corretamente antes de evoluir. Em caso de dúvida, simplesmente use os valores padrão, que são otimizados para o treinamento do YOLOv5 no COCO a partir do zero.

# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license
# Hyperparameters for low-augmentation COCO training from scratch
# python train.py --batch 64 --cfg yolov5n6.yaml --weights '' --data coco.yaml --img 640 --epochs 300 --linear
# See tutorials for hyperparameter evolution https://github.com/ultralytics/yolov5#tutorials

lr0: 0.01 # initial learning rate (SGD=1E-2, Adam=1E-3)
lrf: 0.01 # final OneCycleLR learning rate (lr0 * lrf)
momentum: 0.937 # SGD momentum/Adam beta1
weight_decay: 0.0005 # optimizer weight decay 5e-4
warmup_epochs: 3.0 # warmup epochs (fractions ok)
warmup_momentum: 0.8 # warmup initial momentum
warmup_bias_lr: 0.1 # warmup initial bias lr
box: 0.05 # box loss gain
cls: 0.5 # cls loss gain
cls_pw: 1.0 # cls BCELoss positive_weight
obj: 1.0 # obj loss gain (scale with pixels)
obj_pw: 1.0 # obj BCELoss positive_weight
iou_t: 0.20 # IoU training threshold
anchor_t: 4.0 # anchor-multiple threshold
# anchors: 3  # anchors per output layer (0 to ignore)
fl_gamma: 0.0 # focal loss gamma (efficientDet default gamma=1.5)
hsv_h: 0.015 # image HSV-Hue augmentation (fraction)
hsv_s: 0.7 # image HSV-Saturation augmentation (fraction)
hsv_v: 0.4 # image HSV-Value augmentation (fraction)
degrees: 0.0 # image rotation (+/- deg)
translate: 0.1 # image translation (+/- fraction)
scale: 0.5 # image scale (+/- gain)
shear: 0.0 # image shear (+/- deg)
perspective: 0.0 # image perspective (+/- fraction), range 0-0.001
flipud: 0.0 # image flip up-down (probability)
fliplr: 0.5 # image flip left-right (probability)
mosaic: 1.0 # image mosaic (probability)
mixup: 0.0 # image mixup (probability)
copy_paste: 0.0 # segment copy-paste (probability)

2. Definir Aptidão (Fitness)

Aptidão é o valor que buscamos maximizar. No YOLOv5, definimos uma função de aptidão padrão como uma combinação ponderada de métricas: mAP@0.5 contribui com 10% do peso e mAP@0.5:0.95 contribui com os 90% restantes, com precisão (P) e revocação (R) ausentes. Você pode ajustá-los como achar melhor ou usar a definição de aptidão padrão em utils/metrics.py (recomendado).

def fitness(x):
    """Return model fitness as the sum of weighted metrics [P, R, mAP@0.5, mAP@0.5:0.95]."""
    w = [0.0, 0.0, 0.1, 0.9]  # weights for [P, R, mAP@0.5, mAP@0.5:0.95]
    return (x[:, :4] * w).sum(1)

3. Evoluir

A evolução é realizada sobre um cenário base que buscamos melhorar. O cenário base neste exemplo é o ajuste fino do COCO128 por 10 épocas usando o YOLOv5s pré-treinado. O comando de treinamento do cenário base é:

python train.py --epochs 10 --data coco128.yaml --weights yolov5s.pt --cache

Para evoluir hiperparâmetros específicos para este cenário, começando a partir de nossos valores iniciais definidos na Seção 1., e maximizando a aptidão definida na Seção 2., adicione --evolve:

# Single-GPU
python train.py --epochs 10 --data coco128.yaml --weights yolov5s.pt --cache --evolve

# Multi-GPU with delay
for i in {0..7}; do
  sleep $((30 * i)) # 30-second delay (optional)
  echo "Starting GPU $i..."
  nohup python train.py --epochs 10 --data coco128.yaml --weights yolov5s.pt --cache --device $i --evolve > "evolve_gpu_$i.log" &
done

# Continuous training (use with caution)
# for i in {0..7}; do
#   sleep $((30 * i))  # 30-second delay (optional)
#   echo "Starting continuous training on GPU $i..."
#   (
#     while true; do
#       python train.py --epochs 10 --data coco128.yaml --weights yolov5s.pt --cache --device $i --evolve > "evolve_gpu_$i.log"
#     done
#   ) &
# done

As configurações de evolução padrão executarão o cenário base 300 vezes, ou seja, por 300 gerações. Você pode modificar as gerações através do argumento --evolve, por exemplo python train.py --evolve 1000.

Os principais operadores genéticos são cruzamento e mutação. Neste trabalho, a mutação é usada, com uma probabilidade de 80% e uma variância de 0,04 para criar novos descendentes baseados em uma combinação dos melhores pais de todas as gerações anteriores. Os resultados são registrados em runs/evolve/exp/evolve.csv, e o descendente com maior aptidão é salvo a cada geração como runs/evolve/hyp_evolved.yaml:

# YOLOv5 Hyperparameter Evolution Results
# Best generation: 287
# Last generation: 300
#    metrics/precision,       metrics/recall,      metrics/mAP_0.5, metrics/mAP_0.5:0.95,         val/box_loss,         val/obj_loss,         val/cls_loss
#              0.54634,              0.55625,              0.58201,              0.33665,             0.056451,             0.042892,             0.013441

lr0: 0.01 # initial learning rate (SGD=1E-2, Adam=1E-3)
lrf: 0.2 # final OneCycleLR learning rate (lr0 * lrf)
momentum: 0.937 # SGD momentum/Adam beta1
weight_decay: 0.0005 # optimizer weight decay 5e-4
warmup_epochs: 3.0 # warmup epochs (fractions ok)
warmup_momentum: 0.8 # warmup initial momentum
warmup_bias_lr: 0.1 # warmup initial bias lr
box: 0.05 # box loss gain
cls: 0.5 # cls loss gain
cls_pw: 1.0 # cls BCELoss positive_weight
obj: 1.0 # obj loss gain (scale with pixels)
obj_pw: 1.0 # obj BCELoss positive_weight
iou_t: 0.20 # IoU training threshold
anchor_t: 4.0 # anchor-multiple threshold
# anchors: 3  # anchors per output layer (0 to ignore)
fl_gamma: 0.0 # focal loss gamma (efficientDet default gamma=1.5)
hsv_h: 0.015 # image HSV-Hue augmentation (fraction)
hsv_s: 0.7 # image HSV-Saturation augmentation (fraction)
hsv_v: 0.4 # image HSV-Value augmentation (fraction)
degrees: 0.0 # image rotation (+/- deg)
translate: 0.1 # image translation (+/- fraction)
scale: 0.5 # image scale (+/- gain)
shear: 0.0 # image shear (+/- deg)
perspective: 0.0 # image perspective (+/- fraction), range 0-0.001
flipud: 0.0 # image flip up-down (probability)
fliplr: 0.5 # image flip left-right (probability)
mosaic: 1.0 # image mosaic (probability)
mixup: 0.0 # image mixup (probability)
copy_paste: 0.0 # segment copy-paste (probability)

Recomendamos um mínimo de 300 gerações de evolução para melhores resultados. Observe que a evolução é geralmente cara e consome muito tempo, pois o cenário base é treinado centenas de vezes, podendo exigir centenas ou milhares de horas de GPU.

Quando a evolução terminar, reutilize as configurações descobertas apontando o treinamento para o arquivo salvo, por exemplo python train.py --hyp runs/evolve/hyp_evolved.yaml --data your.yaml --weights yolov5s.pt.

4. Visualiza

evolve.csv é plotado como evolve.png pela função utils.plots.plot_evolve() após a conclusão da evolução, com um subgráfico por hiperparâmetro mostrando a aptidão (eixo y) versus valores do hiperparâmetro (eixo x). Amarelo indica maiores concentrações. Distribuições verticais indicam que um parâmetro foi desativado e não sofre mutação. Isso é selecionável pelo usuário no dicionário meta em train.py, e é útil para fixar parâmetros e evitar que eles evoluam.

Resultados de aptidão da evolução de hiperparâmetros do YOLOv5

Ambientes Suportados

A Ultralytics fornece uma gama de ambientes prontos a usar, cada um pré-instalado com dependências essenciais como CUDA, CUDNN, Python e PyTorch, para dar início aos teus projetos.

Status do Projeto

YOLOv5 CI

Este selo indica que todos os testes de Integração Contínua (CI) do GitHub Actions do YOLOv5 estão passando com sucesso. Esses testes de CI verificam rigorosamente a funcionalidade e o desempenho do YOLOv5 em vários aspectos fundamentais: treinamento, validação, inferência, exportação e benchmarks. Eles garantem uma operação consistente e confiável no macOS, Windows e Ubuntu, com testes realizados a cada 24 horas e a cada novo commit.

Comentários