Comment affiner YOLO sur un jeu de données personnalisé#
L’ajustement fin 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 depuis zéro pendant des centaines d’époques, l’ajustement fin tire parti des caractéristiques préentraînées de COCO et converge sur des données personnalisées en une fraction du temps.
Ce guide explique comment effectuer l’ajustement fin de YOLO26 sur des jeux de données personnalisés, des bases aux techniques avancées comme le gel de couches et l’entraînement en deux étapes.
Ajustement fin ou entraînement depuis 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 au moyen de l’ajustement fin réutilise ces connaissances et apprend uniquement au modèle à quoi ressemblent les nouvelles classes ; c’est pourquoi il converge plus rapidement et nécessite moins de données. L’entraînement depuis zéro écarte tout cela et oblige le modèle à tout apprendre à partir de motifs au niveau des pixels, ce qui demande beaucoup plus de ressources. Consulte le Guide de configuration YAML des modèles pour découvrir en quoi les fichiers .yaml qui définissent uniquement l’architecture diffèrent des points de contrôle.
| Ajustement fin | Entraînement depuis zéro | |
|---|---|---|
| Poids initiaux | Préentraîné sur COCO (80 classes) | Initialisation aléatoire |
| Commande | YOLO("yolo26n.pt") | YOLO("yolo26n.yaml") |
| Convergence | Plus rapide : le backbone est déjà entraîné | Plus lente : toutes les couches apprennent à partir de zéro |
| Besoins en données | Moins élevés : les caractéristiques préentraînées compensent le manque de données | Plus élevés : le modèle doit apprendre toutes les caractéristiques à partir du seul jeu de données |
| Quand l’utiliser | Classes personnalisées avec des images naturelles | Domaines fondamentalement différents de COCO (médical, satellite, radar) |
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 de .train(data="custom.yaml") par la suite transfère automatiquement tous les poids compatibles vers la nouvelle architecture du modèle, réinitialise les couches incompatibles (comme la couche de classification finale 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é de transfert d'apprentissage ne sont nécessaires.
Fonctionnement du transfert de poids préentraînés#
Lorsqu’un modèle préentraîné est affiné sur un jeu de données dont le nombre de classes diffère (par exemple, les 80 classes de COCO vers 5 classes personnalisées), Ultralytics effectue un transfert des poids tenant compte des dimensions :
- Transfert intégral du backbone et du neck : ces couches extraient des caractéristiques visuelles générales et leurs dimensions sont indépendantes du nombre de classes.
- La tête de détection est partiellement réinitialisée - seule la convolution finale de chaque branche de classification (
cv3,one2one_cv3) a une forme liée au nombre de classes (80 contre 5) ; les couches cachées de la branche sont transférées si les deux modèles ont la même échelle. Les lignes compatibles dont les noms de classes correspondent sont remappées avant l'initialisation des lignes non correspondantes. Les couches de régression des boîtes (cv2,one2one_cv2) de la tête ont une forme fixe, quel que soit le nombre de classes, et sont donc transférées normalement. - La grande majorité des poids est transférée lorsque le nombre de classes change. Par exemple, le réglage fin de YOLO26n de COCO (80 classes) vers un jeu de données à 5 classes transfère 696 des 708 tenseurs de poids, ainsi que toutes les lignes de classification compatibles dont le nom correspond.
Pour les jeux de données qui comptent le même nombre de classes que le modèle préentraîné (par exemple, l’ajustement fin de poids préentraînés sur COCO sur 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 à l’aide d’alias de noms#
Ultralytics transfère les lignes correspondantes de la tête de classification entre les jeux de données à partir des noms de classes, sans tenir compte de la casse ni des espaces environnants. Lorsque des classes équivalentes portent des noms différents, renomme en mémoire les classes du point de contrôle source avant le chargement. Cela préserve les poids de classification préentraînés pour les concepts communs qui, autrement, seraient considérés comme sans correspondance et initialisés aléatoirement.
Cet exemple de transfert de 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 classes Objects365 utilisent des majuscules initiales ; fais donc la correspondance avec 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 réglage 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 le désactiver.
Exemple simple d’ajustement fin#
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # charger un 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 davantage 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 sa 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 complète des modèles YOLO26 pour connaître les tailles disponibles et les résultats des tests de performances.
Choisir l’optimiseur et le taux d’apprentissage#
Le réglage 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 petit nombre 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’ajustement fin, le réglage par défaut donne de bons résultats sans réglage manuel. Envisage de définir explicitement l’optimiseur lorsque :
- L’entraînement est instable (la perte présente des pics ou diverge) : essaie
optimizer=AdamW, lr0=0.001pour obtenir une convergence plus stable - Tu affines un grand modèle sur un petit jeu de données : un optimiseur explicite associé à un taux d’apprentissage plus faible, comme
optimizer=AdamW, lr0=0.001, peut aider à préserver les caractéristiques préentraînées
Avec optimizer=auto, la valeur de lr0 est ignorée. 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 la mise à jour de certaines couches 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 s’étend des 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 couches comme freeze=[0, 3, 5] pour un gel partiel du backbone, ou des chaînes de 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).
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 de préentraînement, ainsi que de la quantité de données d’entraînement disponible :
| Scénario | Recommandation | Justification |
|---|---|---|
| Grand jeu de données, domaine similaire | freeze=None (par défaut) | Assez de données pour adapter toutes les couches sans surapprentissage |
| Petit jeu de données, domaine similaire | freeze=10 | Préserve les caractéristiques du backbone et réduit le nombre de paramètres entraînables |
| Très petit jeu de données | freeze=23 | Seule la tête de détection est entraînée, ce qui réduit le risque de surapprentissage |
| Domaine très différent de COCO | freeze=None | Les caractéristiques du backbone ne se transfèrent peut-être pas bien et doivent être réentraînées |
La profondeur de gel peut aussi être traitée comme un hyperparamètre : tester quelques valeurs (0, 5, 10) et comparer le mAP de validation est une méthode pratique pour trouver le meilleur réglage pour un jeu de données donné.
Principaux hyperparamètres de l’ajustement fin#
L’ajustement fin nécessite généralement moins de modifications des hyperparamètres que l’entraînement à partir de zéro. Les paramètres les plus importants sont :
epochs: l’ajustement fin converge plus rapidement que l’entraînement à partir de zéro. Commence par une valeur modérée et utilisepatiencepour arrêter tôt 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 entraînements qui ont déjà convergé.warmup_epochs: le warmup fait progressivement atteindre au taux d’apprentissage sa valeur planifiée 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-le différent de zéro pendant l’ajustement fin, mais la valeur par défaut de 3 époques n’est pas nécessaire : la recherche évolutionnaire à l’origine de l’ajustement fin officiel de YOLO26 sur COCO — une poursuite de l’entraînement sur plusieurs époques à partir des poids Objects365 — a retenu environ une époque pour chaque taille de modèle.
Pour la liste complète des paramètres d’entraînement, consulte la référence de configuration de l’entraînement. Pour les comportements non couverts par ces paramètres — taux d’apprentissage par couche, écrêtage du gradient ou métriques de validation personnalisées — sous-classe le trainer.
Ajustement fin en deux étapes#
L’ajustement fin en deux étapes répartit l’entraînement en deux phases. Lors de la première étape, le backbone est gelé et seuls le neck et la tête sont entraînés, ce qui permet aux couches de détection de s’adapter aux nouvelles classes sans perturber les caractéristiques préentraînées. Lors de la seconde étape, toutes les couches sont dégelées et le modèle complet est entraîné 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 considérablement de COCO (images médicales, imagerie aérienne, microscopie) : le backbone peut nécessiter une adaptation, mais entraîner toutes les couches d’un coup provoque de l’instabilité. Pour dégeler automatiquement les couches à l’aide d’un callback, consulte Gel et dégel du backbone.
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, effectuer l’ajustement fin 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 : s’entraîner avec très peu d’exemples est la cause la plus courante : le modèle ne peut pas apprendre ni généraliser avec trop peu de donné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 provoquent une erreur de jeu de données. Les fichiers d’étiquettes manquants ou vides sont considérés individuellement comme des images d’arrière-plan et signalés pendant l’analyse ; une partition d’entraînement sans étiquettes provoque 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.1pendant l’inférence. -
Vérifie le nombre de classes : assure-toi que
ncdansdata.yamlcorrespond au nombre réel de classes dans les fichiers d’étiquettes.
Le mAP de validation plafonne rapidement#
- Ajoute des données : l’ajustement fin bénéficie nettement 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 un AP faible. Ajoute des exemples ou ajuste
cls_pwsur le jeu de validation. - Réduis l’augmentation : pour les très petits jeux de données, une augmentation importante peut faire plus de mal que de bien. Essaie
mosaic=0.5oumosaic=0.0. - Augmente la résolution : pour les jeux de données contenant de petits objets, essaie
imgsz=1280afin de préserver les détails.
Les performances sur les classes d’origine diminuent après l’ajustement fin#
Ce phénomène est appelé oubli catastrophique : le modèle perd les connaissances acquises précédemment lorsqu’il est ajusté exclusivement sur de nouvelles données. Il est en grande partie inévitable de l’éviter sans inclure des 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 l’ajustement fin. 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 pour que seule la tête de détection soit entraînée est utile lors d’ajustements fins courts avec un taux d’apprentissage très faible.
- Réduis le nombre d’époques : plus le modèle est entraîné longtemps 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. La diversité des images (éclairages, angles et arrière-plans variés) compte davantage que leur quantité brute. Commence avec les données dont tu disposes et augmente-les si les métriques de validation sont insuffisantes.
Charge un fichier
.ptpréentraîné et appelle.train()en lui transmettant le chemin vers undata.yamlpersonnalisé. Ultralytics gère automatiquement le transfert des poids, la réinitialisation des couches de classification et la sélection de l'optimiseur. Consulte la section Réglage fin de base pour voir l'exemple de code complet.Les causes les plus courantes sont des chemins d’image non valides, des fichiers d’étiquettes manquants ou vides, une différence entre
ncdans le YAML et les fichiers d’étiquettes 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) é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 des recommandations détaillées.Inclus dans les données d’entraînement des exemples des classes d’origine, en plus des nouvelles classes. Si ce n’est pas possible, geler davantage de couches (
freeze=10ou plus) et utiliser un taux d’apprentissage plus faible aide à préserver les connaissances préentraînées. Consulte Les performances sur les classes d’origine diminuent pour en savoir plus.