Ultralytics YOLO27 :

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

L’affinage adapte un modèle préentraîné à la reconnaissance de nouvelles classes en partant de poids appris plutôt que d’une initialisation aléatoire. Au lieu d’entraîner un modèle de zéro pendant des centaines d’époques, l’affinage exploite les caractéristiques COCO préentraînées et converge sur des données personnalisées en beaucoup moins de temps.

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

Affinage ou entraînement 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, compréhension des formes — à partir de millions d’images. L’apprentissage par transfert au moyen de l’affinage réutilise ces connaissances et apprend uniquement au modèle à quoi ressemblent les nouvelles classes, ce qui explique sa convergence plus rapide et ses besoins en données moindres. L’entraînement de zéro écarte toutes ces connaissances et oblige le modèle à tout apprendre à partir des motifs au niveau des pixels, ce qui demande beaucoup plus de ressources. Consulte le Guide de configuration des fichiers YAML du modèle pour découvrir en quoi les fichiers .yaml qui ne contiennent que l’architecture diffèrent des points de contrôle.

Réglage finEntraînement 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éesMoindres : les caractéristiques préentraînées compensent le manque de donnéesPlus importants : le modèle doit apprendre toutes les caractéristiques à partir du seul jeu de données
Quand l’utiliserClasses personnalisées avec des images naturellesDomaines fondamentalement différents de COCO (médical, satellite, radar)
L’affinage 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") ensuite transfère automatiquement tous les poids compatibles vers la nouvelle architecture du modèle, réinitialise les couches incompatibles (comme la tête de détection lorsque le nombre de classes diffère) et lance l’entraînement. Aucun chargement manuel des poids, aucune manipulation des couches ni aucun code personnalisé d’apprentissage par transfert ne sont nécessaires.

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

Lorsqu’un modèle préentraîné est affiné sur un jeu de données avec 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. Le backbone et le neck sont entièrement transférés : ces couches extraient des caractéristiques visuelles générales, et leurs dimensions ne dépendent pas du nombre de classes.
  2. La tête de détection est partiellement réinitialisée : 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 classe correspondent sont réaffecté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 ; elles sont donc transférées normalement.
  3. La grande majorité des poids est transférée lorsque le nombre de classes change. Par exemple, l’affinage de YOLO26n depuis COCO (80 classes) sur un jeu de données de 5 classes transfère 606 des 708 tenseurs de poids, ainsi que toutes les lignes de classification compatibles dont les noms correspondent.

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

Transférer les classes à l’aide d’alias de noms#

Ultralytics transfère les lignes correspondantes de la tête de classification d’un jeu de données à l’autre en faisant correspondre les noms de classe, sans tenir compte de la casse ni des espaces environnants. Lorsque des classes équivalentes ont des noms différents, renomme les classes du point de contrôle source en mémoire avant le chargement. Cela conserve les poids de classification préentraînés pour les concepts communs qui seraient autrement considérés comme sans correspondance et initialisés de façon aléatoire.

Cet exemple de conversion d’Objects365 v2 vers COCO renomme les classes sources dans le point de contrôle chargé, que train() transmet ensuite comme poids préentraînés :

from ultralytics import YOLO

# Nom de la classe source Objects365 v2 (en minuscules) -> nom de la classe cible COCO
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")
# Les noms de classe Objects365 sont en majuscules initiales ; la correspondance se fait donc sur le nom en minuscules
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 par défaut ce transfert basé sur les noms. 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 désactiver cette fonctionnalité.

Exemple d’affinage de base#

Exemple
from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # charger le modèle préentraîné
model.train(data="custom.yaml", epochs=50, imgsz=640)

Choisir la taille du modèle#

Les modèles plus grands ont une capacité supérieure, mais 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 passer à une taille supérieure uniquement 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 complète du modèle YOLO26 pour connaître les tailles disponibles et les performances de référence.

Choisir l’optimiseur et le taux d’apprentissage#

Le paramètre optimizer=auto sélectionne par défaut 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 d’affinage, le paramètre par défaut convient sans réglage manuel. Envisage de définir explicitement l’optimiseur lorsque :

  • L’entraînement est instable (la loss fait des pics ou diverge) : 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 remplace lr0 défini manuellement

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 des couches#

Le gel empêche certaines couches de se mettre à jour pendant l’entraînement. Il 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), qui couvrent la majeure partie du backbone YOLO26. Le backbone comprend les couches 0 à 10 ; freeze=10 laisse donc le dernier bloc C2PSA (couche 10) entraînable. Utilise freeze=11 pour geler tout le backbone. Une liste peut contenir des indices de couche comme freeze=[0, 3, 5] pour geler partiellement le backbone, ou des chaînes de nom de module comme freeze=["23.cv2", "23.one2one_cv2"] pour contrôler précisément certaines branches 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)

Le niveau de gel approprié dépend de la similarité entre le domaine cible et les données de préentraînement, 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)Assez 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 minimise le risque de surapprentissage
Domaine très différent de COCOfreeze=NoneLes caractéristiques du backbone risquent de mal se transférer et nécessitent un réentraînement

Le niveau de gel peut aussi être traité comme un hyperparamètre : essayer quelques valeurs (0, 5, 10) et comparer la mAP de validation est une méthode pratique pour trouver le meilleur réglage pour un jeu de données donné.

Principaux hyperparamètres pour l’affinage#

L’affinage nécessite généralement moins d’ajustements des hyperparamètres que l’entraînement de zéro. Les paramètres les plus importants sont :

  • epochs : l’affinage converge plus vite que l’entraînement 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. Réduis-la à 10-20 pour éviter de perdre du temps sur des entraînements qui ont déjà convergé.
  • warmup_epochs : le warmup amène progressivement le taux d’apprentissage à sa valeur prévue au cours des premières époques, ce qui réduit le risque que les premiers lots perturbent les caractéristiques préentraînées. Garde une valeur différente de zéro pour l’affinage, mais la valeur par défaut de 3 époques n’est pas indispensable : la recherche évolutionnaire qui a mené à l’affinage officiel de YOLO26 sur COCO — une continuation sur plusieurs époques à partir des poids Objects365 — a retenu environ une époque pour chaque taille de modèle.

Pour consulter la liste complète des paramètres d’entraînement, reporte-toi à la référence de configuration de l’entraînement. Pour les comportements que les paramètres ne permettent pas de contrôler — taux d’apprentissage par couche, écrêtage du gradient ou métriques de validation personnalisées — sous-classe l’entraîneur.

Affinage en deux étapes#

L’affinage en deux étapes divise l’entraînement en deux phases. La première gèle le backbone et n’entraîne que 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 deuxième dégèle 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 qu’entraîner toutes les couches simultanément entraîne de l’instabilité. Pour dégeler automatiquement les couches au moyen d’une approche basée sur des callbacks, consulte Geler et dégeler le backbone.

Affinage en deux étapes
from ultralytics import YOLO

# Étape 1 : geler le backbone, entraîner la tête et le neck
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)

# Étape 2 : tout dégeler, affiner avec un lr plus faible
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’échantillons est la cause la plus fréquente ; le modèle ne peut ni apprendre ni généraliser à partir de données trop limitées. Assure-toi d’avoir suffisamment d’exemples variés pour chaque classe avant d’examiner d’autres causes.

  • Vérifie les chemins du jeu de données : des chemins d’image non valides déclenchent une erreur liée au jeu de données. Les fichiers d’étiquettes individuels manquants ou vides sont considérés comme des images d’arrière-plan et signalés pendant l’analyse ; une division d’entraînement sans étiquettes 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 pendant 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’étiquettes.

La mAP de validation plafonne rapidement#

  • Ajoute des données : l’affinage bénéficie grandement de données d’entraînement supplémentaires, en particulier d’exemples variés présentant différents angles, éclairages et arrière-plans.
  • Vérifie l’équilibre des classes : les classes sous-représentées auront une AP faible. Ajoute des exemples ou ajuste cls_pw sur le jeu de validation.
  • Réduis l’augmentation de données : sur les très petits jeux de données, une augmentation importante peut être plus néfaste qu’utile. Essaie mosaic=0.5 ou mosaic=0.0.
  • Augmente la résolution : pour les jeux de données qui contiennent de petits objets, essaie imgsz=1280 pour préserver les détails.

Les performances se dégradent sur les classes d’origine après l’affinage#

Ce phénomène est appelé oubli catastrophique : le modèle perd les connaissances acquises auparavant lorsqu’il est affiné uniquement sur de nouvelles données. Cet oubli est presque inévitable si les images du jeu de données d’origine ne sont pas incluses avec les nouvelles données. Pour l’atténuer :

  • Fusionne les jeux de données : inclus des exemples des classes d’origine avec ceux des nouvelles classes pendant l’affinage. C’est le seul moyen fiable d’éviter l’oubli.
  • Gèle le backbone et le neck : geler à la fois le backbone et le neck pour que seule la tête de détection soit entraînée peut aider lors de courtes sessions d’affinage avec un taux d’apprentissage très faible.
  • Réduis le nombre d’époques d’entraînement : plus le modèle s’entraîne longtemps uniquement 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. La diversité des images (différents éclairages, angles et arrière-plans) compte davantage que leur nombre brut. 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() en lui indiquant le chemin d’un fichier data.yaml personnalisé. Ultralytics gère automatiquement le transfert des poids, la réinitialisation de la tête de détection et le choix de l’optimiseur. Consulte la section Affinage de base pour voir l’exemple de code complet.

  • Les causes les plus fréquentes sont des chemins d’image non valides, des fichiers d’étiquettes manquants ou vides, une différence entre nc dans le fichier YAML et les fichiers d’étiquettes réels, ou un seuil de confiance trop élevé. Consulte la section Pièges courants pour une liste complète des points à vérifier.

  • Cela dépend de la taille du jeu de données et de la similarité des domaines. Pour les petits jeux de données dont le domaine est similaire à COCO, geler le backbone (freeze=10) évite 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 Gel des couches pour obtenir des recommandations détaillées.

  • Inclue des exemples des classes d’origine dans les données d’entraînement, en plus des 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 en savoir plus.

Commentaires