Comment affiner YOLO sur un jeu de données personnalisé
Affinage adapte un modèle pré-entraîné pour reconnaître de nouvelles classes en partant de poids appris plutôt qu'une initialisation aléatoire. Au lieu d'entraîner à partir de zéro pendant des centaines d'époques, l'affinage exploite des COCO caractéristiques pré-entraînées et converge sur des données personnalisées en une fraction du temps.
Ce guide couvre l'affinage de YOLO26 sur des jeux de données personnalisés, de l'utilisation basique aux techniques avancées comme le gel des couches et en entraînement en deux étapes.
Affinage vs 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 de bords, reconnaissance de textures, compréhension des formes - à partir de millions d'images. Apprentissage par transfert (Transfer learning) via l'affinage réutilise ces connaissances et enseigne 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 à partir de zéro écarte tout cela et force le modèle à tout apprendre à partir des motifs au niveau des pixels, ce qui demande beaucoup plus de ressources.
| Fine-tuning | Entraînement à partir de zéro | |
|---|---|---|
| Poids de départ | 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 lent - toutes les couches apprennent à partir de zéro |
| Besoins en données | Plus faibles - 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 uniquement à partir du jeu de données |
| Quand utiliser | Classes personnalisées avec des images naturelles | Domaines fondamentalement différents de COCO (médical, satellite, radar) |
Quand un .pt fichier est chargé avec YOLO("yolo26n.pt"), les poids pré-entraînés sont stockés dans le modèle. Appeler .train(data="custom.yaml") après cela transfère automatiquement tous les poids compatibles vers la nouvelle architecture de modèle, réinitialise toutes 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 de poids, manipulation de couches ou code de transfert d'apprentissage personnalisé n'est requis.
Comment fonctionne le transfert de poids pré-entraîné
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 de poids conscient de la forme :
- Le backbone et le neck sont transférés intégralement - ces couches extraient des caractéristiques visuelles générales et leurs formes sont indépendantes du nombre de classes.
- La tête de détection est partiellement réinitialisée - les couches de sortie de classification (
cv3,one2one_cv3) ont des formes liées au nombre de classes (80 vs 5), donc elles ne peuvent pas être transférées et sont initialisées de manière aléatoire. Les couches de régression des boîtes (cv2,one2one_cv2) dans la tête ont des formes fixes indépendamment du nombre de classes, donc elles sont transférées normalement. - La grande majorité des poids sont transférés lors du changement du nombre de classes. Seules les couches spécifiques à la classification dans la tête de détection sont réinitialisées - le backbone, le neck et les branches de régression des boîtes restent intacts.
Pour les jeux de données avec 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 sur un autre jeu de données de 80 classes), 100 % des poids sont transférés, y compris la tête de détection.
Exemple d'affinage de base
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # load pretrained model
model.train(data="path/to/data.yaml", epochs=50, imgsz=640)Choisir une taille de modèle
Les modèles plus grands ont plus de capacité mais aussi plus de paramètres à mettre à jour, ce qui peut augmenter le risque de surapprentissage lorsque les données d'entraînement sont limitées. Commencer avec un modèle plus petit (YOLO26n ou YOLO26s) et augmenter la taille seulement si les métriques de validation plafonnent est une approche pratique. La taille de modèle optimale 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. Voir la page complète du modèle YOLO26 pour les tailles disponibles et les benchmarks de performance.
Sélection de l'optimiseur et du taux d'apprentissage
Le paramètre par défaut optimizer=auto sélectionne l'optimiseur et le taux d'apprentissage en fonction du nombre total d'itérations d'entraînement :
- < 10 000 itérations (petits jeux de données ou peu d'époques) : AdamW avec un taux d'apprentissage faible calculé automatiquement
- > 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 réglage par défaut fonctionne bien sans aucun réglage manuel. Envisage d'expliciter l'optimiseur lorsque :
- L'entraînement est instable (pics de perte ou divergence) : essaie
optimizer=AdamW, lr0=0.001pour une convergence plus stable - Affinage d'un grand modèle sur un petit jeu de données: un taux d'apprentissage plus bas comme
lr0=0.001aide à préserver les caractéristiques pré-entraînées
Lorsque optimizer=auto, la fonction lr0 et en momentum les valeurs sont ignorées. Pour contrôler le taux d'apprentissage manuellement, définis l'optimiseur explicitement : optimizer=SGD, lr0=0.005.
Gel des couches
Le gel empêche des couches spécifiques d'être mises à jour pendant l'entraînement. Cela accélère l'entraînement et réduit overfitting lorsque le jeu de données est petit par rapport à la capacité du modèle.
La méthode freeze le paramètre accepte soit un entier, soit une liste. Un entier freeze=10 gèle les 10 premières couches (0 à 9, ce qui correspond au backbone dans YOLO26). 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"] pour un contrôle fin sur des branches spécifiques au sein d'une couche.
model.train(data="custom.yaml", epochs=50, freeze=10)La bonne profondeur de gel dépend de la similitude du domaine cible avec les données pré-entraînées et de la quantité de données d'entraînement disponibles :
| 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, réduit les paramètres entraînables |
| Très petit jeu de données | freeze=23 | Seule la tête de détection est entraînée, minimisant le risque de surapprentissage |
| Domaine éloigné de COCO | freeze=None | Les caractéristiques du backbone peuvent ne pas bien se transférer et nécessitent 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 un moyen pratique de trouver le meilleur réglage pour un jeu de données spécifique.
Hyperparamètres clés pour l'affinage
L'affinage nécessite généralement moins d'ajustements d'hyperparamètres que l'entraînement à partir de zéro. Les paramètres les plus importants sont :
epochs: L'affinage converge plus rapidement que l'entraînement à partir de zéro. Commence avec une valeur modérée et utilisepatiencepour arrêter prématurément lorsque les métriques de validation plafonnent.patience: La valeur par défaut de 100 est conçue pour de longs entraînements. La réduire à 10-20 évite de perdre du temps sur des exécutions qui ont déjà convergé.warmup_epochs: L'échauffement par défaut (3 époques) augmente progressivement le taux d'apprentissage à partir de zéro, ce qui évite que des mises à jour de gradient importantes n'endommagent les caractéristiques pré-entraînées lors des premières itérations. Garder le défaut est recommandé même pour l'affinage.
Pour la liste complète des paramètres d'entraînement, voir la référence de configuration d'entraînement.
Affinage en deux étapes
L'affinage en deux étapes divise l'entraînement en deux phases. La première étape gèle le backbone et n'entraîne que le neck et la tête, permettant aux couches de détection de s'adapter aux nouvelles classes sans perturber les caractéristiques pré-entraînées. La deuxième étape dégèle toutes les couches et entraîne le modèle complet avec un taux d'apprentissage plus bas pour affiner le backbone pour le domaine cible.
Cette approche est particulièrement utile lorsque le domaine cible diffère significativement de COCO (images médicales, imagerie aérienne, microscopie), où le backbone peut avoir besoin d'une adaptation mais où tout entraîner à la fois provoque de l'instabilité. Pour un dégèlement automatique avec une approche basée sur des rappels, voir Geler et dégeler la dorsale (backbone).
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, 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 pas apprendre ou généraliser à partir de trop peu de données. Assure-toi d'avoir suffisamment d'exemples variés par classe avant d'examiner d'autres causes.
- Vérifie les chemins du jeu de données: des chemins incorrects dans
data.yamlproduisent silencieusement zéro étiquette. Exécuteyolo detect val model=yolo26n.pt data=your_data.yamlavant l'entraînement pour confirmer que les étiquettes se chargent correctement. - Abaisse 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 prématurément
- Ajoute plus de données: le fine-tuning bénéficie grandement de données d'entraînement supplémentaires, surtout d'exemples variés avec des angles, des éclairages et des arrière-plans différents.
- Vérifie l'équilibre des classes: les classes sous-représentées auront un AP faible. Utilise
cls_pwpour appliquer une pondération des classes par fréquence inverse (commence aveccls_pw=0.25pour un déséquilibre modéré, augmente à1.0pour un déséquilibre sévère). - Réduis l'augmentation: pour de très petits jeux de données, une augmentation trop lourde peut être plus nuisible qu'utile. Essaie
mosaic=0.5oumosaic=0.0. - Augmente la résolution: pour les jeux de données avec de petits objets, essaie
imgsz=1280pour préserver les détails.
Les performances se dégradent sur les classes d'origine après le fine-tuning
Ceci est connu sous le nom d'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 pratiquement inévitable sans inclure des images du jeu de données original aux côtés des nouvelles données. Pour atténuer cela :
- Fusionne les jeux de données: inclus des exemples des classes originales aux côtés des nouvelles classes pendant le fine-tuning. C'est le seul moyen fiable d'empêcher 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 aide pour les cycles de fine-tuning courts avec un taux d'apprentissage très faible.
- Entraîne sur moins d'époques: plus le modèle s'entraîne exclusivement sur de nouvelles données, plus l'oubli augmente.
FAQ
De combien d'images ai-je besoin pour faire le fine-tuning de YOLO ?
Il n'y a 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 diverses (éclairages, angles, arrière-plans variés) comptent plus que la quantité brute. Commence avec ce que tu as et augmente si les métriques de validation sont insuffisantes.
Comment puis-je faire le fine-tuning de YOLO26 sur un jeu de données personnalisé ?
Charge un fichier .pt pré-entraîné et appelle .train() avec le chemin vers un data.yaml personnalisé. Ultralytics gère automatiquement le transfert de 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 l'exemple de code complet.
Pourquoi mon modèle YOLO affiné ne détecte-t-il rien ?
Les causes les plus courantes sont des chemins incorrects dans data.yaml (qui produit silencieusement zéro étiquette), une inadéquation entre nc dans le YAML et les fichiers d'étiquettes réels, ou un seuil de confiance trop élevé. Consulte Pièges courants pour une liste de contrôle de dépannage complète.
Quelles couches YOLO dois-je geler pour le fine-tuning ?
Cela dépend de la taille du jeu de données et de la similarité des domaines. Pour les petits jeux de données avec un domaine similaire à COCO, geler le backbone (freeze=10) empêche le surapprentissage. Pour des domaines très différents de COCO, laisser toutes les couches non gelées (freeze=None) permet au backbone de s'adapter. Consulte Gel des couches pour des recommandations détaillées.
Comment puis-je empêcher l'oubli catastrophique lors du fine-tuning de YOLO sur de nouvelles classes ?
Inclus des exemples des classes d'origine dans les données d'entraînement aux côtés des nouvelles classes. Si ce n'est pas possible, geler plus de couches (freeze=10 ou plus) et utiliser un taux d'apprentissage plus bas aide à préserver les connaissances pré-entraînées. Consulte Les performances se dégradent sur les classes d'origine pour plus de détails.