YOLO Vision 2026 :

Comment affiner YOLO sur un jeu de données personnalisé#

Le fine-tuning adapte un modèle préentraîné afin qu'il reconnaisse de nouvelles classes, en partant de poids appris plutôt que d'une initialisation aléatoire. Au lieu d'entraîner le modèle à partir de zéro pendant des centaines d'époques, le fine-tuning exploite les caractéristiques préentraînées de COCO et converge sur les données personnalisées en une fraction du temps.

Ce guide explique comment effectuer le fine-tuning de YOLO26 sur des jeux de données personnalisés, de l'utilisation de base aux techniques avancées comme le gel des couches et l'entraînement en deux étapes.

Fine-tuning ou entraînement à partir de zéro#

Un modèle préentraîné a déjà appris des caractéristiques visuelles générales — détection des contours, reconnaissance des textures et compréhension des formes — à partir de millions d'images. L'apprentissage par transfert via le fine-tuning réutilise ces connaissances et apprend uniquement au modèle à quoi ressemblent les nouvelles classes, ce qui explique pourquoi il converge plus rapidement et nécessite moins de données. L'entraînement à partir de zéro élimine toutes ces connaissances et force le modèle à tout apprendre à partir de motifs au niveau des pixels, ce qui exige beaucoup plus de ressources. Consulte le guide de configuration YAML des modèles pour découvrir en quoi les fichiers .yaml contenant uniquement l'architecture diffèrent des checkpoints.

AffinageEntraînement à partir de zéro
Poids de départPréentraîné sur COCO (80 classes)Initialisation aléatoire
CommandeYOLO("yolo26n.pt")YOLO("yolo26n.yaml")
ConvergencePlus rapide — le backbone est déjà entraînéPlus lente — toutes les couches apprennent à partir de zéro
Besoins en donnéesMoins élevés — les caractéristiques préentraînées compensent le manque de donnéesPlus élevés — le modèle doit apprendre toutes les caractéristiques uniquement à partir du jeu de données
Quand l'utiliserClasses personnalisées avec des images naturellesDomaines fondamentalement différents de COCO (médical, satellite, radar)
Le fine-tuning ne nécessite aucun code supplémentaire

Lorsqu'un fichier .pt est chargé avec YOLO("yolo26n.pt"), les poids préentraînés sont stockés dans le modèle. L'appel à .train(data="custom.yaml") transfère ensuite automatiquement tous les poids compatibles vers la nouvelle architecture du modèle, réinitialise les couches qui ne correspondent pas (comme la tête de détection lorsque le nombre de classes diffère) et commence l'entraînement. Aucun chargement manuel des poids, aucune manipulation des couches ni aucun code personnalisé d'apprentissage par transfert n'est requis.

Fonctionnement du transfert des poids préentraînés#

Lorsqu'un modèle préentraîné est affiné sur un jeu de données comportant un nombre de classes différent (par exemple, les 80 classes de COCO vers 5 classes personnalisées), Ultralytics effectue un transfert des poids tenant compte des dimensions :

  1. Transfert complet du backbone et du neck — ces couches extraient les caractéristiques visuelles générales et leurs dimensions sont indépendantes du nombre de classes.
  2. Réinitialisation partielle de la tête de détection — les couches de sortie de classification (cv3, one2one_cv3) ont des dimensions liées au nombre de classes (80 contre 5). Les lignes compatibles dont les noms de classes correspondent sont remappées avant l'initialisation des lignes sans correspondance. Les couches de régression des boîtes (cv2, one2one_cv2) de la tête ont des dimensions fixes quel que soit le nombre de classes et sont donc transférées normalement.
  3. L'immense majorité des poids est transférée lorsque le nombre de classes change. Par exemple, le fine-tuning de YOLO26n de COCO (80 classes) vers un jeu de données à 5 classes transfère 606 des 708 tenseurs de poids, ainsi que toutes les lignes de classification compatibles associées par leur nom.

Pour les jeux de données comportant le même nombre de classes que le modèle préentraîné (par exemple, le fine-tuning de poids préentraînés sur COCO avec un autre jeu de données à 80 classes), 100 % des poids sont transférés, y compris ceux de la tête de détection.

Transférer les classes avec des alias de noms#

Ultralytics transfère les lignes correspondantes de la tête de classification en fonction du nom de classe entre les jeux de données, sans tenir compte de la casse ni des espaces environnants. Lorsque des classes équivalentes portent des noms différents, renomme les classes du checkpoint source en mémoire avant le chargement. Cela préserve les poids de classification préentraînés pour les concepts communs qui seraient autrement considérés comme sans correspondance et initialisés aléatoirement.

Cet exemple Objects365 v2 vers COCO renomme les classes sources dans le checkpoint chargé, que train() transmet ensuite en tant que poids préentraînés :

from ultralytics import YOLO

# Source Objects365 v2 name (lowercased) -> target COCO name
ALIASES = {
    "wild bird": "bird",
    "handbag/satchel": "handbag",
    "luggage": "suitcase",
    "bowl/basin": "bowl",
    "orange/tangerine": "orange",
    "monitor/tv": "tv",
    "stuffed toy": "teddy bear",
    "hair dryer": "hair drier",
}

model = YOLO("path/to/yolo26s-objects365.pt")
# Objects365 class names are Title-Cased, so match on the lowercased name
model.model.names = {i: ALIASES.get(name.lower(), name) for i, name in model.model.names.items()}
model.train(data="coco.yaml", epochs=100, imgsz=640)

Le paramètre cls_remap active ce transfert fondé sur les noms par défaut. L'entraînement affiche Remapped N/M cls head rows from pretrained weights by class name lorsque des lignes compatibles sont copiées ; définis cls_remap=False pour le désactiver.

Exemple de fine-tuning de base#

Exemple
from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # load pretrained model
model.train(data="custom.yaml", epochs=50, imgsz=640)

Choisir la taille du modèle#

Les modèles plus grands offrent davantage de capacité, mais comportent aussi plus de paramètres à mettre à jour, ce qui peut accroître le risque de surapprentissage lorsque les données d'entraînement sont limitées. Commencer par un modèle plus petit (YOLO26n ou YOLO26s) et n'augmenter la taille que si les métriques de validation plafonnent est une approche pratique. La taille optimale du modèle dépend de la complexité de la tâche, du nombre de classes, de la diversité du jeu de données et du matériel disponible pour le déploiement. Consulte la page consacrée au modèle YOLO26 pour connaître les tailles disponibles et les benchmarks de performances.

Choisir l'optimiseur et le taux d'apprentissage#

Le paramètre optimizer=auto par défaut sélectionne l'optimiseur et le taux d'apprentissage en fonction du nombre total d'itérations d'entraînement :

  • 10 000 itérations ou moins (petits jeux de données ou peu d'époques) : AdamW avec un faible taux d'apprentissage calculé automatiquement
  • Plus de 10 000 itérations (grands jeux de données) : MuSGD (un optimiseur hybride Muon+SGD) avec lr=0.01

Pour la plupart des tâches de fine-tuning, le paramètre par défaut fonctionne bien sans réglage manuel. Envisage de définir explicitement l'optimiseur lorsque :

  • L'entraînement est instable (pics de perte ou divergence) : essaie optimizer=AdamW, lr0=0.001 pour obtenir une convergence plus stable
  • Tu affines un grand modèle sur un petit jeu de données : un optimiseur explicite avec un taux d'apprentissage plus faible, comme optimizer=AdamW, lr0=0.001, peut aider à préserver les caractéristiques préentraînées
L'optimiseur automatique ignore lr0 manuel

Lorsque optimizer=auto, les valeurs lr0 et momentum sont ignorées. Pour contrôler manuellement le taux d'apprentissage, définis explicitement l'optimiseur : optimizer=SGD, lr0=0.005.

Geler les couches#

Le gel empêche certaines couches de se mettre à jour pendant l'entraînement. Cela accélère l'entraînement et réduit le surapprentissage lorsque le jeu de données est petit par rapport à la capacité du modèle.

Le paramètre freeze accepte un entier ou une liste. Un entier freeze=10 gèle les 10 premières couches (indices 0 à 9), ce qui couvre la majeure partie du backbone de YOLO26. Le backbone s'étend sur les couches 0 à 10 ; freeze=10 laisse donc le bloc C2PSA final (couche 10) entraînable. Utilise freeze=11 pour geler l'intégralité du backbone. Une liste peut contenir des indices de couches comme freeze=[0, 3, 5] pour un gel partiel du backbone, ou des chaînes correspondant aux noms de modules comme freeze=["23.cv2", "23.one2one_cv2"] pour contrôler précisément certaines branches au sein d'une couche (ici, les deux branches de régression des boîtes de la tête de détection).

Exemple
from ultralytics import YOLO

model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=50, freeze=10)

La profondeur de gel appropriée dépend de la similarité entre le domaine cible et les données préentraînées, ainsi que de la quantité de données d'entraînement disponible :

ScénarioRecommandationJustification
Grand jeu de données, domaine similairefreeze=None (par défaut)Suffisamment de données pour adapter toutes les couches sans surapprentissage
Petit jeu de données, domaine similairefreeze=10Préserve les caractéristiques du backbone et réduit le nombre de paramètres entraînables
Très petit jeu de donnéesfreeze=23Seule la tête de détection est entraînée, ce qui réduit au minimum le risque de surapprentissage
Domaine très éloigné de COCOfreeze=NoneLes caractéristiques du backbone peuvent mal se transférer et nécessiter un réentraînement

La profondeur de gel peut également être traitée comme un hyperparamètre : essayer quelques valeurs (0, 5, 10) et comparer le mAP de validation est une méthode pratique pour trouver le meilleur paramètre pour un jeu de données donné.

Hyperparamètres clés du fine-tuning#

Le fine-tuning nécessite généralement moins d'ajustements d'hyperparamètres qu'un entraînement à partir de zéro. Les paramètres les plus importants sont :

  • epochs : le fine-tuning converge plus rapidement qu'un entraînement à partir de zéro. Commence par une valeur modérée et utilise patience pour arrêter l'entraînement lorsque les métriques de validation plafonnent.
  • patience : la valeur par défaut de 100 est conçue pour les entraînements longs. La réduire à 10-20 évite de perdre du temps sur des exécutions qui ont déjà convergé.
  • warmup_epochs : le warmup amène progressivement le taux d'apprentissage à sa valeur planifiée au cours des premières époques, afin que les premiers lots perturbent moins les caractéristiques préentraînées. Garde-le différent de zéro lors du fine-tuning, mais les 3 époques complètes par défaut ne sont pas nécessaires : la recherche évolutionnaire derrière le fine-tuning officiel de YOLO26 sur COCO — une continuation sur plusieurs époques à partir des poids Objects365 — s'est fixée à environ une époque pour chaque taille de modèle.

Pour obtenir la liste complète des paramètres d'entraînement, consulte la référence de configuration de l'entraînement. Pour les comportements que les paramètres n'exposent pas — taux d'apprentissage par couche, écrêtage des gradients ou métriques de validation personnalisées — sous-classe le trainer.

Fine-tuning en deux étapes#

Le fine-tuning en deux étapes divise l'entraînement en deux phases. La première gèle le backbone et entraîne uniquement le neck et la tête, ce qui permet aux couches de détection de s'adapter aux nouvelles classes sans perturber les caractéristiques préentraînées. La seconde défige toutes les couches et entraîne le modèle complet avec un taux d'apprentissage plus faible afin d'affiner le backbone pour le domaine cible.

Cette approche est particulièrement utile lorsque le domaine cible diffère fortement de COCO (images médicales, images aériennes, microscopie), car le backbone peut nécessiter une adaptation, tandis que l'entraînement de toutes les couches en une seule fois provoque une instabilité. Pour un dégel automatique basé sur un callback, consulte Geler et dégeler le backbone.

Fine-tuning en deux étapes
from ultralytics import YOLO

# Stage 1: freeze backbone, train head and neck
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)

# Stage 2: unfreeze all, fine-tune with lower lr
model = YOLO("runs/detect/stage1/weights/best.pt")
model.train(data="custom.yaml", epochs=30, optimizer="AdamW", lr0=0.001, name="stage2", exist_ok=True)

Pièges courants#

Le modèle ne produit aucune prédiction#

  • Données d'entraînement insuffisantes : l'entraînement avec très peu d'exemples est la cause la plus courante ; le modèle ne peut ni apprendre ni généraliser à partir d'une quantité de données trop faible. Vérifie que tu disposes de suffisamment d'exemples variés par classe avant d'examiner d'autres causes.

  • Vérifie les chemins du jeu de données : des chemins d'image invalides déclenchent une erreur de jeu de données. Les fichiers d'annotations individuels manquants ou vides sont traités comme des images d'arrière-plan et signalés lors de l'analyse ; une partition d'entraînement sans annotations déclenche une erreur. Valide le jeu de données avant l'entraînement :

    yolo detect val model=yolo26n.pt data=custom.yaml
  • Réduis le seuil de confiance : si des prédictions existent mais sont filtrées, essaie conf=0.1 lors de l'inférence.

  • Vérifie le nombre de classes : assure-toi que nc dans data.yaml correspond au nombre réel de classes dans les fichiers d'annotations.

Le mAP de validation plafonne rapidement#

  • Ajoute davantage de données : le fine-tuning bénéficie considérablement de données d'entraînement supplémentaires, en particulier d'exemples variés avec différents angles, éclairages et arrière-plans.
  • Vérifie l'équilibre des classes : les classes sous-représentées auront un AP faible. Ajoute davantage d'exemples ou ajuste cls_pw sur l'ensemble de validation.
  • Réduis l'augmentation : pour les très petits jeux de données, une augmentation intensive peut être plus nuisible qu'utile. Essaie mosaic=0.5 ou mosaic=0.0.
  • Augmente la résolution : pour les jeux de données contenant de petits objets, essaie imgsz=1280 afin de préserver les détails.

Les performances diminuent sur les classes d'origine après le fine-tuning#

Ce phénomène est appelé oubli catastrophique : le modèle perd les connaissances acquises précédemment lorsqu'il est affiné exclusivement sur de nouvelles données. L'oubli est en grande partie inévitable si tu n'inclus pas d'images du jeu de données d'origine avec les nouvelles données. Pour l'atténuer :

  • Fusionne les jeux de données : inclus des exemples des classes d'origine avec les nouvelles classes pendant le fine-tuning. C'est la seule méthode fiable pour éviter l'oubli.
  • Gèle le backbone et le neck : geler à la fois le backbone et le neck afin que seule la tête de détection soit entraînée peut être utile pour les courtes phases de fine-tuning avec un taux d'apprentissage très faible.
  • Entraîne pendant moins d'époques : plus le modèle est entraîné exclusivement sur de nouvelles données, plus l'oubli s'accentue.

FAQ#

  • Il n'existe pas de minimum fixe : les résultats dépendent de la complexité de la tâche, du nombre de classes et de la similarité du domaine avec COCO. Des images plus variées (éclairages, angles et arrière-plans différents) comptent davantage que la quantité brute. Commence avec les données dont tu disposes et augmente-les si les métriques de validation sont insuffisantes.

  • Charge un fichier .pt préentraîné et appelle .train() avec le chemin vers un fichier data.yaml personnalisé. Ultralytics gère automatiquement le transfert des poids, la réinitialisation de la tête de détection et la sélection de l'optimiseur. Consulte la section Fine-tuning de base pour voir l'exemple de code complet.

  • Les causes les plus courantes sont des chemins d'image invalides, des fichiers d'annotations manquants ou vides, une incohérence entre nc dans le YAML et les fichiers d'annotations réels, ou un seuil de confiance trop élevé. Consulte Pièges courants pour une liste complète des vérifications de dépannage.

  • Cela dépend de la taille du jeu de données et de la similarité du domaine. Pour les petits jeux de données dont le domaine est similaire à COCO, geler le backbone (freeze=10) empêche le surapprentissage. Pour les domaines très différents de COCO, laisser toutes les couches dégelées (freeze=None) permet au backbone de s'adapter. Consulte Geler les couches pour des recommandations détaillées.

  • Inclus des exemples des classes d'origine dans les données d'entraînement avec les nouvelles classes. Si ce n'est pas possible, geler davantage de couches (freeze=10 ou plus) et utiliser un taux d'apprentissage plus faible aide à préserver les connaissances préentraînées. Consulte Les performances diminuent sur les classes d'origine pour plus de détails.

Commentaires