Guide de configuration YAML du modèle
Le fichier de configuration YAML du modèle sert de plan architectural pour les réseaux de neurones Ultralytics. Il définit comment les couches se connectent, quels paramètres chaque module utilise et comment l'ensemble du réseau s'adapte aux différentes tailles de modèles.
Structure de configuration
Les fichiers YAML du modèle sont organisés en trois sections principales qui fonctionnent ensemble pour définir l'architecture.
Section des paramètres
La section parameters spécifie les caractéristiques globales et le comportement de mise à l'échelle du modèle :
# Parameters
nc: 80 # number of classes
scales: # compound scaling constants [depth, width, max_channels]
n: [0.50, 0.25, 1024] # nano: shallow layers, narrow channels
s: [0.50, 0.50, 1024] # small: shallow depth, standard width
m: [0.50, 1.00, 512] # medium: moderate depth, full width
l: [1.00, 1.00, 512] # large: full depth and width
x: [1.00, 1.50, 512] # extra-large: maximum performance
kpt_shape: [17, 3] # pose models onlyncdéfinit le nombre de classes que le modèle prédit.scalesdéfinit les facteurs de mise à l'échelle composés qui ajustent la profondeur, la largeur et le nombre maximal de canaux du modèle pour produire différentes variantes de taille (de nano à extra-large).kpt_shapes'applique aux modèles de pose. Il peut être[N, 2]pour les points clés(x, y)ou[N, 3]pour(x, y, visibility).
Le paramètre scales te permet de générer plusieurs tailles de modèle à partir d'un seul fichier YAML de base. Par exemple, lorsque tu charges yolo26n.yaml, Ultralytics lit le fichier yolo26.yaml de base et applique les facteurs de mise à l'échelle n (depth=0.50, width=0.25) pour construire la variante nano.
Si ton jeu de données spécifie un nc ou un kpt_shape différent, Ultralytics remplacera automatiquement la configuration du modèle au moment de l'exécution pour correspondre au YAML du jeu de données.
Architecture du backbone et de la head
L'architecture du modèle se compose de sections backbone (extraction de caractéristiques) et head (spécifique à la tâche) :
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0: Initial convolution
- [-1, 1, Conv, [128, 3, 2]] # 1: Downsample
- [-1, 3, C2f, [128, True]] # 2: Feature processing
head:
- [-1, 1, nn.Upsample, [None, 2, nearest]] # 6: Upsample
- [[-1, 2], 1, Concat, [1]] # 7: Skip connection
- [-1, 3, C2f, [256]] # 8: Process features
- [[8], 1, Detect, [nc]] # 9: Detection layerFormat de spécification des couches
Chaque couche suit le modèle cohérent : [from, repeats, module, args]
| Composant | Objectif | Exemples |
|---|---|---|
| from | Connexions d'entrée | -1 (précédent), 6 (couche 6), [4, 6, 8] (entrées multiples) |
| repeats | Nombre de répétitions | 1 (simple), 3 (répéter 3 fois) |
| module | Type de module | Conv, C2f, TorchVision, Detect |
| args | Arguments du module | [64, 3, 2] (canaux, noyau, pas) |
Modèles de connexion
Le champ from crée des modèles de flux de données flexibles à travers ton réseau :
- [-1, 1, Conv, [64, 3, 2]] # Takes input from previous layerLes couches sont indexées à partir de 0. Les indices négatifs font référence aux couches précédentes (-1 = couche précédente), tandis que les indices positifs font référence à des couches spécifiques par leur position.
Répétition de module
Le paramètre repeats crée des sections de réseau plus profondes :
- [-1, 3, C2f, [128, True]] # Creates 3 consecutive C2f blocks
- [-1, 1, Conv, [64, 3, 2]] # Single convolution layerLe nombre réel de répétitions est multiplié par le facteur de mise à l'échelle de la profondeur de la configuration de taille de ton modèle.
Modules disponibles
Les modules sont organisés par fonctionnalité et définis dans le répertoire des modules Ultralytics. Les tableaux suivants présentent les modules couramment utilisés par catégorie, avec beaucoup d'autres disponibles dans le code source :
Opérations de base
| Module | Objectif | Source | Arguments |
|---|---|---|---|
Conv | Convolution + BatchNorm + Activation | conv.py | [out_ch, kernel, stride, pad, groups] |
nn.Upsample | Suréchantillonnage spatial | PyTorch | [size, scale_factor, mode] |
nn.Identity | Opération de passage | PyTorch | [] |
Blocs composites
| Module | Objectif | Source | Arguments |
|---|---|---|---|
C2f | Goulot d'étranglement CSP avec 2 convolutions | block.py | [out_ch, shortcut, expansion] |
SPPF | Regroupement de pyramides spatiales (rapide) | block.py | [out_ch, kernel_size] |
Concat | Concaténation par canal | conv.py | [dimension] |
Modules spécialisés
| Module | Objectif | Source | Arguments |
|---|---|---|---|
TorchVision | Charger n'importe quel modèle torchvision | block.py | [out_ch, model_name, weights, unwrap, truncate, split] |
Index | Extraire un tenseur spécifique d'une liste | block.py | [out_ch, index] |
Detect | Head de détection YOLO | head.py | [nc, anchors, ch] |
Ceci représente un sous-ensemble des modules disponibles. Pour la liste complète des modules et leurs paramètres, explore le répertoire des modules.
Fonctionnalités avancées
Intégration de TorchVision
Le module TorchVision permet une intégration transparente de n'importe quel modèle TorchVision en tant que backbone :
from ultralytics import YOLO
# Model with ConvNeXt backbone
model = YOLO("convnext_backbone.yaml")
results = model.train(data="coco8.yaml", epochs=100)Règle le dernier paramètre sur True pour obtenir des cartes de caractéristiques intermédiaires pour la détection multi-échelles.
Module Index pour la sélection de caractéristiques
Lorsque tu utilises des modèles qui produisent plusieurs cartes de caractéristiques, le module Index sélectionne des sorties spécifiques :
backbone:
- [-1, 1, TorchVision, [768, convnext_tiny, DEFAULT, True, 2, True]] # Multi-output
head:
- [0, 1, Index, [192, 4]] # Select 4th feature map (192 channels)
- [0, 1, Index, [384, 6]] # Select 6th feature map (384 channels)
- [0, 1, Index, [768, 8]] # Select 8th feature map (768 channels)
- [[1, 2, 3], 1, Detect, [nc]] # Multi-scale detectionSystème de résolution de module
Comprendre comment Ultralytics localise et importe les modules est crucial pour la personnalisation :
Processus de recherche de module
Ultralytics utilise un système à trois niveaux dans parse_model :
# Core resolution logic
m = getattr(torch.nn, m[3:]) if "nn." in m else getattr(torchvision.ops, m[4:]) if "ops." in m else globals()[m]- Modules PyTorch : Noms commençant par
'nn.'→ espace de nomstorch.nn - Opérations TorchVision : Noms commençant par
'ops.'→ espace de nomstorchvision.ops - Ultralytics modules : Tous les autres noms → espace de noms global via des imports
Chaîne d'importation de modules
Les modules standard deviennent disponibles via des imports dans tasks.py :
from ultralytics.nn.modules import ( # noqa: F401
SPPF,
C2f,
Conv,
Detect,
# ... many more modules
Index,
TorchVision,
)Intégration de modules personnalisés
Modification du code source
La modification du code source est le moyen le plus polyvalent d'intégrer tes propres modules, mais cela peut être délicat. Pour définir et utiliser un module personnalisé, suis ces étapes :
-
Installe Ultralytics en mode développement en utilisant la méthode de clonage Git du guide de démarrage rapide.
-
Définis ton module dans
ultralytics/nn/modules/block.py:class CustomBlock(nn.Module): """Custom block with Conv-BatchNorm-ReLU sequence.""" def __init__(self, c1, c2): """Initialize CustomBlock with input and output channels.""" super().__init__() self.layers = nn.Sequential(nn.Conv2d(c1, c2, 3, 1, 1), nn.BatchNorm2d(c2), nn.ReLU()) def forward(self, x): """Forward pass through the block.""" return self.layers(x) -
Expose ton module au niveau du package dans
ultralytics/nn/modules/__init__.py:from .block import CustomBlock # noqa makes CustomBlock available as ultralytics.nn.modules.CustomBlock -
Add to imports in
ultralytics/nn/tasks.py:from ultralytics.nn.modules import CustomBlock # noqa -
Gère les arguments spéciaux (si nécessaire) dans
parse_model()dansultralytics/nn/tasks.py:# Add this condition in the parse_model() function if m is CustomBlock: c1, c2 = ch[f], args[0] # input channels, output channels args = [c1, c2, *args[1:]] -
Utilise le module dans ton YAML de modèle :
# custom_model.yaml nc: 1 backbone: - [-1, 1, CustomBlock, [64]] head: - [-1, 1, Classify, [nc]] -
Vérifie les FLOPs pour t'assurer que la passe avant (forward pass) fonctionne :
from ultralytics import YOLO model = YOLO("custom_model.yaml", task="classify") model.info() # should print non-zero FLOPs if working
Exemples de configurations
Modèle de détection basique
# Simple YOLO detection model
nc: 80
scales:
n: [0.33, 0.25, 1024]
backbone:
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]] # 2
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]] # 4
- [-1, 1, SPPF, [256, 5]] # 5
head:
- [-1, 1, Conv, [256, 3, 1]] # 6
- [[6], 1, Detect, [nc]] # 7Modèle de backbone TorchVision
# ConvNeXt backbone with YOLO head
nc: 80
backbone:
- [-1, 1, TorchVision, [768, convnext_tiny, DEFAULT, True, 2, True]]
head:
- [0, 1, Index, [192, 4]] # P3 features
- [0, 1, Index, [384, 6]] # P4 features
- [0, 1, Index, [768, 8]] # P5 features
- [[1, 2, 3], 1, Detect, [nc]] # Multi-scale detectionModèle de classification
# Simple classification model
nc: 1000
backbone:
- [-1, 1, Conv, [64, 7, 2, 3]]
- [-1, 1, nn.MaxPool2d, [3, 2, 1]]
- [-1, 4, C2f, [64, True]]
- [-1, 1, Conv, [128, 3, 2]]
- [-1, 8, C2f, [128, True]]
- [-1, 1, nn.AdaptiveAvgPool2d, [1]]
head:
- [-1, 1, Classify, [nc]]Bonnes pratiques
Conseils de conception d'architecture
Commence simple : Débute avec des architectures éprouvées avant de personnaliser. Utilise les configurations YOLO existantes comme modèles et modifie-les progressivement plutôt que de construire à partir de zéro.
Teste progressivement : Valide chaque modification étape par étape. Ajoute un module personnalisé à la fois et vérifie qu'il fonctionne avant de passer au changement suivant.
Surveille les canaux : Assure-toi que les dimensions des canaux correspondent entre les couches connectées. Les canaux de sortie (c2) d'une couche doivent correspondre aux canaux d'entrée (c1) de la couche suivante dans la séquence.
Utilise les connexions de saut (skip connections) : Tire parti de la réutilisation des fonctionnalités avec les modèles [[-1, N], 1, Concat, [1]]. Ces connexions aident au flux de gradient et permettent au modèle de combiner des fonctionnalités de différentes échelles.
Adapte l'échelle : Choisis les échelles de modèle en fonction de tes contraintes de calcul. Utilise nano (n) pour les appareils en périphérie (edge), small (s) pour une performance équilibrée, et des échelles plus grandes (m, l, x) pour une précision maximale.
Considérations de performance
Profondeur vs largeur : Les réseaux profonds capturent des fonctionnalités hiérarchiques complexes via plusieurs couches de transformation, tandis que les réseaux larges traitent plus d'informations en parallèle à chaque couche. Équilibre ces éléments selon la complexité de ta tâche.
Connexions de saut (skip connections) : Améliorent le flux de gradient pendant l'entraînement et permettent la réutilisation des fonctionnalités à travers le réseau. Elles sont particulièrement importantes dans les architectures plus profondes pour éviter la disparition des gradients.
Blocs goulots d'étranglement (bottleneck) : Réduisent le coût de calcul tout en maintenant l'expressivité du modèle. Les modules comme C2f utilisent moins de paramètres que les convolutions standard tout en préservant la capacité d'apprentissage des fonctionnalités.
Fonctionnalités multi-échelles : Essentielles pour détecter des objets de différentes tailles dans la même image. Utilise des modèles FPN (Feature Pyramid Network) avec plusieurs têtes de détection à différentes échelles.
Dépannage
Problèmes courants
| Problème | Cause | Solution |
|---|---|---|
KeyError: 'ModuleName' | Module non importé | Ajoute aux imports de tasks.py |
| Inadéquation de la dimension des canaux | Spécification d'args incorrecte | Vérifie la compatibilité des canaux d'entrée/sortie |
AttributeError: 'int' object has no attribute | Type d'argument erroné | Consulte la documentation du module pour les types d'arguments corrects |
| Le modèle ne parvient pas à se construire | Référence from invalide | Assure-toi que les couches référencées existent |
Conseils de débogage
Lors du développement d'architectures personnalisées, un débogage systématique aide à identifier les problèmes tôt :
Utilise une tête d'identité pour les tests
Remplace les têtes complexes par nn.Identity pour isoler les problèmes de backbone :
nc: 1
backbone:
- [-1, 1, CustomBlock, [64]]
head:
- [-1, 1, nn.Identity, []] # Pass-through for debuggingCela permet une inspection directe des sorties du backbone :
import torch
from ultralytics import YOLO
model = YOLO("debug_model.yaml")
output = model.model(torch.randn(1, 3, 640, 640))
print(f"Output shape: {output.shape}") # Should match expected dimensionsInspection de l'architecture du modèle
Vérifier le nombre de FLOPs et afficher chaque couche peut aussi aider à déboguer les problèmes avec ta configuration de modèle personnalisée. Le nombre de FLOPs doit être non nul pour un modèle valide. S'il est nul, il y a probablement un problème avec la passe avant. Exécuter une simple passe avant devrait montrer l'erreur exacte rencontrée.
from ultralytics import YOLO
# Build model with verbose output to see layer details
model = YOLO("debug_model.yaml", verbose=True)
# Check model FLOPs. Failed forward pass causes 0 FLOPs.
model.info()
# Inspect individual layers
for i, layer in enumerate(model.model.model):
print(f"Layer {i}: {layer}")Validation étape par étape
- Commence minimal : Teste d'abord avec l'architecture la plus simple possible
- Ajoute progressivement : Construis la complexité couche par couche
- Vérifie les dimensions : Vérifie la compatibilité des canaux et de la taille spatiale
- Valide la mise à l'échelle : Teste avec différentes échelles de modèle (
n,s,m)
FAQ
Comment puis-je modifier le nombre de classes dans mon modèle ?
Définit le paramètre nc en haut de ton fichier YAML pour qu'il corresponde au nombre de classes de ton jeu de données.
nc: 5 # 5 classesPuis-je utiliser un backbone personnalisé dans mon YAML de modèle ?
Oui. Tu peux utiliser n'importe quel module pris en charge, y compris les backbones TorchVision, ou définir ton propre module personnalisé et l'importer comme décrit dans Intégration de modules personnalisés.
Comment puis-je mettre à l'échelle mon modèle pour différentes tailles (nano, small, medium, etc.) ?
Utilise la section scales dans ton YAML pour définir les facteurs de mise à l'échelle pour la profondeur, la largeur et les canaux maximaux. Le modèle les appliquera automatiquement lorsque tu chargeras le fichier YAML de base avec l'échelle ajoutée au nom du fichier (par ex. yolo26n.yaml).
Que signifie le format [from, repeats, module, args] ?
Ce format spécifie comment chaque couche est construite :
from: source(s) d'entréerepeats: nombre de fois où répéter le modulemodule: type de coucheargs: arguments pour le module
Comment puis-je dépanner les erreurs d'inadéquation de canaux ?
Vérifie que les canaux de sortie d'une couche correspondent aux canaux d'entrée attendus de la suivante. Utilise print(model.model.model) pour inspecter l'architecture de ton modèle.
Où puis-je trouver une liste des modules disponibles et leurs arguments ?
Vérifie le code source dans le répertoire ultralytics/nn/modules pour tous les modules disponibles et leurs arguments.
Comment puis-je ajouter un module personnalisé à ma configuration YAML ?
Définit ton module dans le code source, importe-le comme indiqué dans Modification du code source, et référence-le par son nom dans ton fichier YAML.
Puis-je utiliser des poids pré-entraînés avec un YAML personnalisé ?
Oui, tu peux utiliser model.load("path/to/weights") pour charger des poids à partir d'un checkpoint pré-entraîné. Cependant, seuls les poids des couches correspondantes seront chargés avec succès.
Comment puis-je valider la configuration de mon modèle ?
Utilise model.info() pour vérifier si le nombre de FLOPs est non nul. Un modèle valide doit afficher un nombre de FLOPs non nul. S'il est nul, suis les suggestions dans Conseils de débogage pour trouver le problème.