Ultralytics YOLO27 :

Évolution des hyperparamètres pour YOLOv5#

📚 Ce guide explique l’évolution des hyperparamètres pour YOLOv5 🚀. L’évolution des hyperparamètres est une méthode d’optimisation des hyperparamètres utilisant un algorithme génétique (GA) pour l’optimisation.

Les hyperparamètres de l’apprentissage automatique contrôlent divers aspects de l’entraînement, et trouver leurs valeurs optimales peut être difficile. Les méthodes traditionnelles comme les recherches par grille peuvent rapidement devenir irréalisables en raison de :

  1. L’espace de recherche de grande dimension
  2. Corrélations inconnues entre les dimensions
  3. Le coût élevé de l’évaluation de la fonction d’adaptation à chaque point

Les algorithmes génétiques sont donc particulièrement adaptés à la recherche d’hyperparamètres.

Avant de commencer#

Clone le dépôt et installe requirements.txt dans un environnement Python>=3.8.0, notamment PyTorch>=1.8. Les modèles et les jeux de données sont téléchargés automatiquement depuis la dernière version de YOLOv5.

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

1. Initialiser les hyperparamètres#

YOLOv5 possède environ 30 hyperparamètres utilisés pour divers paramètres d’entraînement. Ceux-ci sont définis dans les fichiers *.yaml du répertoire /data/hyps. De meilleures valeurs initiales produiront de meilleurs résultats finaux ; il est donc important d’initialiser correctement ces valeurs avant l’évolution. En cas de doute, utilise simplement les valeurs par défaut, qui sont optimisées pour l’entraînement de YOLOv5 sur COCO à partir de zéro.

# 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. Définir la fonction d’adaptation#

La fonction de score (fitness) est la valeur que tu cherches à maximiser. Dans YOLOv5, nous définissons une fonction de score par défaut sous forme de combinaison pondérée de métriques : mAP@0.5 contribue à 10 % du poids et mAP@0.5:0.95 contribue aux 90 % restants, avec la précision (P) et le rappel (R) absents. Tu peux les ajuster comme tu le souhaites ou utiliser la définition de score par défaut dans utils/metrics.py (recommandé). Ce score détermine quel résultat est enregistré dans hyp_evolve.yaml ; l'algorithme génétique lui-même classe les parents et les élites par mAP@0.5 seul, de sorte que la modification de ces poids ne modifie pas la sélection des parents.

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. Faire évoluer#

L’évolution est effectuée à partir d’un scénario de base que nous cherchons à améliorer. Dans cet exemple, le scénario de base consiste à effectuer un réentraînement de COCO128 pendant 10 époques avec YOLOv5s préentraîné. La commande d’entraînement du scénario de base est la suivante :

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

Pour faire évoluer les hyperparamètres spécifiques à ce scénario, en partant de nos valeurs initiales définies dans la Section 1. et en maximisant la fonction d’adaptation définie dans la Section 2., ajoute --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

Les paramètres d'évolution par défaut s'exécutent pendant 300 générations, et chaque génération entraîne le scénario de base une fois pour chacun des 50 individus de la population. Tu peux modifier les générations via l'argument --evolve, c'est-à-dire python train.py --evolve 1000.

Les principaux opérateurs génétiques sont le croisement (crossover) et la mutation. Chaque génération entraîne chaque individu et lui attribue un score par mAP@0.5, sélectionne les parents par sélection par tournoi avec les élites les plus performantes ajoutées au pool de parents, et construit la population suivante par croisement et mutation, avec des taux qui s'adaptent au fur et à mesure que l'évolution progresse. Les résultats sont enregistrés dans runs/evolve/exp/evolve.csv, et la descendance ayant le score le plus élevé est sauvegardée à chaque génération sous le nom de runs/evolve/exp/hyp_evolve.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)

Nous recommandons un minimum de 300 générations d'évolution pour obtenir les meilleurs résultats. Note que l'évolution est généralement coûteuse et chronophage, car le scénario de base est entraîné des milliers de fois, nécessitant éventuellement des centaines ou des milliers d'heures de GPU.

Une fois l’évolution terminée, réutilise les paramètres découverts en indiquant au processus d’entraînement le fichier enregistré, par exemple python train.py --hyp runs/evolve/exp/hyp_evolve.yaml --data your.yaml --weights yolov5s.pt.

4. Visualiser#

evolve.csv est représenté sous forme de graphique dans evolve.png par utils.plots.plot_evolve() une fois l’évolution terminée, avec un sous-graphique par hyperparamètre montrant la fonction d’adaptation (axe des y) en fonction des valeurs de l’hyperparamètre (axe des x). Le jaune indique des concentrations plus élevées. Les distributions verticales indiquent qu’un paramètre a été désactivé et ne subit pas de mutation. Cette option peut être sélectionnée par l’utilisateur dans le dictionnaire meta de train.py et permet de fixer des paramètres et d’empêcher leur évolution.

Résultats de la fonction d’adaptation de l’évolution des hyperparamètres de YOLOv5

Environnements pris en charge#

Ultralytics fournit une gamme d'environnements prêts à l'emploi, chacun incluant déjà les dépendances essentielles telles que CUDA, CUDNN, Python et PyTorch, pour te permettre de démarrer rapidement tes projets.

État du projet#

YOLOv5 CI

Ce badge indique que tous les tests d’intégration continue (CI) de YOLOv5 GitHub Actions passent avec succès. Ces tests de CI vérifient rigoureusement les fonctionnalités et les performances de YOLOv5 sous plusieurs aspects essentiels : entraînement, validation, inférence, exportation et benchmarks. Ils garantissent un fonctionnement cohérent et fiable sur macOS, Windows et Ubuntu, avec des tests exécutés toutes les 24 heures et à chaque nouveau commit.

FAQ#

  • Chaque génération entraîne le scénario de base une fois par individu dans la population de 50 membres, de sorte que 300 générations d'un run COCO128 de 10 époques coûtent environ 15 000 fois plus cher qu'un tel run. Garde le scénario de base court et représentatif. La boucle multi-GPU ci-dessus lance une recherche indépendante sur chaque GPU plutôt que de partager une seule recherche, réduis donc --evolve par processus si tu travailles avec un budget fixe.

  • Oui. --evolve est défini par défaut à 300 générations ; passe un nombre tel que --evolve 1000 pour en exécuter davantage.

  • Définis la première valeur de son entrée dans le dictionnaire meta dans train.py sur False. Les paramètres exclus conservent leur valeur initiale et apparaissent sous forme de lignes verticales dans evolve.png.

  • Passe le fichier sauvegardé à un run d'entraînement normal : python train.py --hyp runs/evolve/exp/hyp_evolve.yaml --data your.yaml --weights yolov5s.pt.

Commentaires