YOLO Vision 2026 :

Guide de configuration YAML des modèles#

Le fichier de configuration YAML du modèle sert de plan architectural pour les réseaux neuronaux Ultralytics. Il définit la manière dont les couches sont connectées, les paramètres utilisés par chaque module et la façon dont l’ensemble du réseau évolue selon les différentes tailles de modèle.

Model YAML configuration workflow.

Structure de la configuration#

Les fichiers YAML des modèles sont organisés en trois sections principales qui définissent ensemble 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 only
  • nc définit le nombre de classes prédites par le modèle.
  • scales définit des facteurs de mise à l’échelle composés qui ajustent la profondeur, la largeur et le nombre maximal de canaux du modèle afin de produire différentes variantes de taille (de nano à très grande).
  • kpt_shape s’applique aux modèles de pose. Il peut s’agir de [N, 2] pour les points clés (x, y) ou de [N, 3] pour (x, y, visibility).
Réduire la redondance avec `scales`

Le paramètre scales te permet de générer plusieurs tailles de modèle à partir d’un seul YAML de base. Par exemple, lorsque tu charges yolo26n.yaml, Ultralytics lit le fichier de base yolo26.yaml et applique les facteurs de mise à l’échelle n (depth=0.50, width=0.25) pour construire la variante nano.

`nc` et `kpt_shape` dépendent du jeu de données

Si ton jeu de données spécifie un nc ou un kpt_shape différent, Ultralytics remplacera automatiquement la configuration du modèle à l’exécution pour l’adapter au YAML du jeu de données.

Architecture du backbone et de la tête#

L’architecture du modèle se compose des sections du backbone (extraction des caractéristiques) et de la tête (spécifique à la tâche) :

nc: 80

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]] # 3: Upsample
    - [[-1, 0], 1, Concat, [1]] # 4: Spatially compatible skip connection
    - [-1, 3, C2f, [256]] # 5: Process features
    - [[5], 1, Detect, [nc]] # 6: Detection layer

Les indices des couches se poursuivent du backbone à la tête, et les cartes de caractéristiques concaténées doivent avoir des dimensions spatiales correspondantes.

Format de spécification des couches#

Chaque couche suit le modèle cohérent suivant : [from, repeats, module, args]

ComposantObjectifExemples
fromConnexions d’entrée-1 (précédente), 6 (couche 6), [4, 6, 8] (entrées multiples)
repeatsNombre de répétitions1 (unique), 3 (répétée 3 fois)
moduleType de moduleConv, C2f, TorchVision, Detect
argsArguments du module[64, 3, 2] (canaux, noyau, stride)

Schémas de connexion#

Le champ from crée des schémas flexibles de flux de données dans tout ton réseau :

- [-1, 1, Conv, [64, 3, 2]]    # Takes input from previous layer
Indexation des couches

Les 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 précises selon leur position.

Répétition des modules#

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 layer

Le nombre réel de répétitions est multiplié par le facteur de mise à l’échelle de la profondeur défini par 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, sachant que le code source en contient bien d’autres :

Opérations de base#

ModuleObjectifSourceArguments
ConvConvolution + BatchNorm + activationconv.py[out_ch, kernel, stride, pad, groups]
nn.UpsampleSuréchantillonnage spatialPyTorch[size, scale_factor, mode]
nn.IdentityOpération de transmission directePyTorch[]

Blocs composites#

ModuleObjectifSourceArguments
C2fGoulot d’étranglement CSP avec 2 convolutionsblock.py[out_ch, shortcut, groups, expansion]
SPPFSpatial Pyramid Pooling (rapide)block.py[out_ch, kernel_size]
ConcatConcaténation par canalconv.py[dimension]

Modules spécialisés#

ModuleObjectifSourceArguments
TorchVisionCharger n’importe quel modèle torchvisionblock.py[out_ch, model_name, weights, unwrap, truncate, split]
IndexExtraire un tenseur spécifique d’une listeconv.py[out_ch, index]
DetectTête de détection YOLOhead.py[nc]
Liste complète des modules

Cette liste représente un sous-ensemble des modules disponibles. Pour consulter la liste complète des modules et de leurs paramètres, explore le répertoire des modules.

Fonctionnalités avancées#

Intégration de TorchVision#

Le module TorchVision permet d’intégrer facilement n’importe quel modèle TorchVision comme backbone :

from ultralytics import YOLO

# Model with ConvNeXt backbone
model = YOLO("convnext_backbone.yaml")
results = model.train(data="imagenet10", epochs=100)
Caractéristiques multi-échelles

Définis le dernier paramètre sur True pour obtenir des cartes de caractéristiques intermédiaires destinées à la détection multi-échelles.

Module Index pour la sélection des caractéristiques#

Lorsque tu utilises des modèles qui produisent plusieurs cartes de caractéristiques, le module Index sélectionne des sorties précises :

nc: 80

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 detection

Système de résolution des modules#

Comprendre comment Ultralytics localise et importe les modules est essentiel pour la personnalisation :

Processus de recherche des modules#

Ultralytics utilise un système à trois niveaux dans parse_model :

# Core resolution logic
m = (
    getattr(torch.nn, m[3:])
    if m.startswith("nn.")
    else getattr(__import__("torchvision").ops, m[16:])
    if m.startswith("torchvision.ops.")
    else globals()[m]
)  # get module
  1. Modules PyTorch : les noms commençant par 'nn.' → espace de noms torch.nn
  2. Opérations TorchVision : les noms commençant par 'torchvision.ops.' → espace de noms torchvision.ops
  3. Modules Ultralytics : tous les autres noms → espace de noms global via les importations

Chaîne d’importation des modules#

Les modules standard sont rendus disponibles par les importations 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#

Modifier le code source est la méthode la plus polyvalente pour intégrer tes modules personnalisés, mais elle peut être délicate. Pour définir et utiliser un module personnalisé, suis ces étapes :

  1. Installe Ultralytics en mode développement en utilisant la méthode de clonage Git du guide de démarrage rapide.

  2. 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)
  3. Expose ton module au niveau du paquet dans ultralytics/nn/modules/__init__.py :

    from .block import CustomBlock  # noqa makes CustomBlock available as ultralytics.nn.modules.CustomBlock
  4. Ajoute-le aux importations dans ultralytics/nn/tasks.py :

    from ultralytics.nn.modules import CustomBlock  # noqa
  5. Ajoute le module à base_modules dans parse_model(). Les modules de cet ensemble reçoivent automatiquement les canaux d’entrée et de sortie :

    base_modules = frozenset(
        {
            # Existing modules...
            CustomBlock,
        }
    )
  6. Utilise le module dans ton YAML de modèle :

    # custom_model.yaml
    nc: 1
    backbone:
        - [-1, 1, CustomBlock, [64]]
    head:
        - [-1, 1, Classify, [nc]]
  7. Vérifie les FLOPs pour t’assurer que la propagation avant fonctionne :

    from ultralytics import YOLO
    
    model = YOLO("custom_model.yaml", task="classify")
    model.info()  # should print non-zero FLOPs if working

Exemples de configuration#

Modèle de détection de base#

# 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]] # 7

Modèle avec 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 detection

Modè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]]

head:
    - [-1, 1, Classify, [nc]]

Classify effectue déjà en interne une mise en commun moyenne adaptative.

Bonnes pratiques#

Conseils de conception de l’architecture#

Commence simplement : Commence par des architectures éprouvées avant de les personnaliser. Utilise les configurations YOLO existantes comme modèles et modifie-les progressivement plutôt que de partir de zéro.

Teste progressivement : Valide chaque modification étape par étape. Ajoute un seul module personnalisé à la fois et vérifie son fonctionnement avant de passer à la modification suivante.

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 des connexions de saut : Exploite la réutilisation des caractéristiques avec les motifs [[-1, N], 1, Concat, [1]]. Ces connexions facilitent la propagation des gradients et permettent au modèle de combiner des caractéristiques provenant de différentes échelles.

Choisis une échelle adaptée : Choisis les échelles du modèle en fonction de tes contraintes de calcul. Utilise nano (n) pour les appareils edge, small (s) pour un compromis équilibré entre performances, et les échelles supérieures (m, l, x) pour une précision maximale.

Considérations relatives aux performances#

Profondeur ou largeur : Les réseaux profonds capturent des caractéristiques hiérarchiques complexes grâce à plusieurs couches de transformation, tandis que les réseaux larges traitent davantage d’informations en parallèle à chaque couche. Trouve un équilibre en fonction de la complexité de ta tâche.

Connexions de saut : Elles améliorent la propagation des gradients pendant l’entraînement et permettent la réutilisation des caractéristiques dans tout le réseau. Elles sont particulièrement importantes dans les architectures profondes pour éviter la disparition des gradients.

Blocs goulot d’étranglement : Ils réduisent le coût de calcul tout en préservant la capacité d’expression du modèle. Des modules comme C2f utilisent moins de paramètres que les convolutions standard tout en préservant la capacité d’apprentissage des caractéristiques.

Caractéristiques multi-échelles : Elles sont essentielles pour détecter des objets de différentes tailles dans une même image. Utilise des motifs de Réseau pyramidal de caractéristiques (FPN) avec plusieurs têtes de détection à différentes échelles.

Dépannage#

Problèmes courants#

ProblèmeCauseSolution
KeyError: 'ModuleName'Module non importéAjoute-le aux imports de tasks.py
Incompatibilité des dimensions des canauxSpécification incorrecte de argsVérifie la compatibilité des canaux d’entrée et de sortie
AttributeError: 'int' object has no attributeType d’argument incorrectConsulte la documentation du module pour connaître les types d’arguments corrects
Échec de la construction du modèleRéférence from non valideVérifie 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 rapidement les problèmes :

Utilise une tête d’identité pour les tests

Remplace les têtes complexes par nn.Identity afin d’isoler les problèmes du backbone :

nc: 1
backbone:
    - [-1, 1, CustomBlock, [64]]
head:
    - [-1, 1, nn.Identity, []] # Pass-through for debugging

Cela permet d’inspecter directement les sorties du backbone :

import torch

from ultralytics import YOLO

model = YOLO("debug_model.yaml", task="detect")
output = model.model(torch.randn(1, 3, 640, 640))
print(f"Output shape: {output.shape}")  # Should match expected dimensions

Inspection de l’architecture du modèle

La vérification du nombre de FLOPs et l’affichage de chaque couche peuvent également aider à déboguer les problèmes de ta configuration de modèle personnalisée. Le nombre de FLOPs doit être différent de zéro pour qu’un modèle soit valide. S’il est nul, il y a probablement un problème au niveau de la passe avant. L’exécution d’une passe avant simple doit révéler l’erreur exacte rencontrée.

from ultralytics import YOLO

# Build model with verbose output to see layer details
model = YOLO("debug_model.yaml", task="detect", 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

  1. Commence au minimum : Commence par tester l’architecture la plus simple possible
  2. Ajoute progressivement : Construis la complexité couche par couche
  3. Vérifie les dimensions : Vérifie la compatibilité des canaux et des dimensions spatiales
  4. Valide la mise à l’échelle : Teste différentes échelles de modèle (n, s, m)

FAQ#

  • Définis le paramètre nc en haut de ton fichier YAML afin qu’il corresponde au nombre de classes de ton jeu de données.

    nc: 5 # 5 classes
  • Oui. Tu peux utiliser n’importe quel module pris en charge, notamment les backbones TorchVision, ou définir ton propre module personnalisé et l’importer comme indiqué dans Intégration d’un module personnalisé.

  • Utilise la section scales dans ton fichier YAML pour définir les facteurs de mise à l’échelle de la profondeur, de la largeur et du nombre maximal de canaux. Le modèle les appliquera automatiquement lorsque tu chargeras le fichier YAML de base avec l’échelle ajoutée au nom de fichier (par exemple, yolo26n.yaml).

  • Ce format indique comment chaque couche est construite :

    • from : source(s) d’entrée
    • repeats : nombre de répétitions du module
    • module : type de couche
    • args : arguments du module
  • Vérifie que les canaux de sortie d’une couche correspondent aux canaux d’entrée attendus par la suivante. Utilise print(model.model.model) pour inspecter l’architecture de ton modèle.

  • Consulte le code source dans le répertoire ultralytics/nn/modules pour voir tous les modules disponibles et leurs arguments.

  • Définis ton module dans le code source, importe-le comme indiqué dans Modification du code source, puis référence-le par son nom dans ton fichier YAML.

  • Oui, tu peux utiliser model.load("path/to/weights") pour charger les poids d’un point de contrôle préentraîné. Cependant, seuls les poids des couches correspondantes seront chargés correctement.

  • Utilise model.info() pour vérifier que le nombre de FLOPs est différent de zéro. Un modèle valide doit afficher un nombre de FLOPs différent de zéro. S’il est nul, suis les suggestions des Conseils de débogage pour trouver le problème.

Commentaires