YOLO Vision 2026 :

Architecture de YOLO expliquée : de YOLOv3 à YOLO26#

Chaque modèle Ultralytics YOLO est constitué de trois étapes : un backbone qui extrait les caractéristiques, un neck qui les fusionne entre les échelles, et une head qui prédit les boîtes et les classes. Ce guide documente les modules qui composent chaque étape et leur évolution de YOLOv3 à YOLO26, en reliant chaque composant à sa définition dans les fichiers de configuration sous ultralytics/cfg/models/ et aux classes de modules dans ultralytics/nn/modules/.

Chaque modèle est défini de manière déclarative dans un fichier YAML sous forme de liste ordonnée de couches, où chaque couche suit le format [from, repeats, module, args] : quelles couches l'alimentent, combien de fois le module est répété, la classe de couche (Conv, C3k2, SPPF, Detect, …) et ses arguments de constructeur. Le Guide de configuration YAML des modèles documente ce format — notamment la manière dont repeats et args évoluent avec les multiples de profondeur et de largeur de la variante — ainsi que l'intégralité du système de résolution des modules. Ce guide se concentre sur les modules eux-mêmes et sur leur évolution d'une version à l'autre.

Les trois étapes#

Chaque modèle Ultralytics YOLO fait passer l'image par trois étapes séquentielles, chacune ayant un rôle distinct :

ÉtapeRôleSortie
BackboneExtraire les caractéristiques de l'image d'entrée à plusieurs résolutionsCartes de caractéristiques aux strides 8, 16 et 32 (P3, P4, P5)
NeckFusionner les caractéristiques entre les échelles afin que les objets petits comme grands disposent d'un contexteCartes de caractéristiques fusionnées multi-échelles
HeadPrédire les boîtes englobantes et les scores de classe à partir des caractéristiques fusionnéesDétections par point d'ancrage

L'unité fondamentale est le bloc Conv (défini dans conv.py) : une convolution 2D, une normalisation par lot et une activation SiLU, appliquées successivement. Chaque module plus grand ci-dessous est construit en composant des blocs Conv.

Schémas d'architecture#

Chaque version conserve le même squelette backbone → neck → head et modifie certaines étapes. Les onglets ci-dessous présentent la structure de chaque version : les étapes du backbone et du neck suivent les configurations de ultralytics/cfg/models/, tandis que les heads de YOLOv3 et YOLOv5 sont représentées dans leur forme originale fondée sur des ancres, plutôt que sous la forme anchor-free de la head de variante u effectivement fournie par leurs configurations de package. Parcourir les onglets montre ce que chaque génération a ajouté. En bref, la progression est la suivante : YOLOv3 est un détecteur fondé sur FPN uniquement et sur des ancres ; YOLOv5 ajoute le chemin PAN ascendant et SPPF ; YOLOv8 adopte le bloc C2f avec une head anchor-free et DFL ; YOLO11 insère l'attention C2PSA et le bloc C3k2 ; et YOLO26 ajoute un résiduel SPPF et rend la head sans NMS et sans DFL. Les couleurs des nœuds suivent la convention des schémas de la documentation : entrée verte, backbone bleu, pooling spatial et attention ardoise, neck orange, head et sortie violets.

flowchart TD
    IN[Input 640x640]:::start --> ST[Conv stem<br/>5x stride-2 down to P1-P5]:::proc
    ST --> BB[Darknet-53 backbone<br/>stacked Bottleneck]:::proc
    BB --> FPN[Neck FPN only<br/>top-down Upsample + Concat]:::decide
    FPN --> HD[Detect head<br/>3 scales, anchor-based]:::out
    HD --> O[Predictions + NMS]:::out
    classDef start fill:#4CAF50,color:#fff
    classDef proc fill:#2196F3,color:#fff
    classDef decide fill:#FF9800,color:#fff
    classDef out fill:#9C27B0,color:#fff

Les schémas de YOLOv3 et YOLOv5 montrent la head originale fondée sur des ancres. Le package ultralytics fournit les configurations anchor-free YOLOv3u et YOLOv5u — les mêmes backbones Darknet-53 et C3, avec la head Detect de YOLOv8 — décrites dans Head de détection.

Blocs du backbone : Bottleneck → C3 → C2f → C3k2#

Le backbone empile un bloc CSP (partiel entre étapes) répétitif entre des couches de sous-échantillonnage Conv de stride 2. C'est ce bloc répétitif qui a le plus évolué au fil des versions. Tous les blocs ci-dessous se trouvent dans block.py ; c1/c2 correspondent aux canaux d'entrée et de sortie, et c = 0.5 * c2 à la largeur cachée.

Bottleneck (YOLOv3)#

L'unité de base est Bottleneck : deux couches Conv (noyaux par défaut (3, 3)) avec une addition résiduelle facultative lorsque shortcut=True et c1 == c2. Le backbone Darknet-53 de YOLOv3 les empile directement, sans séparation CSP, et effectue les détections à trois échelles (strides 8, 16 et 32).

C3 (YOLOv5)#

Le C3 de YOLOv5 répartit l'entrée entre deux convolutions 1x1 : cv1 alimente n blocs Bottleneck séquentiels (noyaux (1, 1), puis (3, 3)), tandis que cv2 les contourne. Les deux chemins sont concaténés et fusionnés par un troisième 1x1 Conv :

def forward(self, x):
    # C3: bottleneck path m(cv1(x)) concatenated with bypass cv2(x), then fused by cv3
    return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))

Seule la sortie du bottleneck final atteint la convolution de fusion ; cv3 reçoit donc 2 cartes de caractéristiques.

C2f (YOLOv8)#

Le C2f de YOLOv8 (« bottleneck CSP avec 2 convolutions, plus rapide ») modifie les caractéristiques qui atteignent la convolution de fusion :

  1. cv1 = Conv(c1, 2 * c, 1), puis chunk(2) répartit la sortie en deux tenseurs de c canaux.
  2. Les blocs n Bottleneck(c, c) (noyaux (3, 3), (3, 3)) s'exécutent séquentiellement, chacun recevant la sortie du bloc précédent.
  3. Tous les tenseurs intermédiaires n + 2 sont concaténés et fusionnés par cv2 = Conv((2 + n) * c, c2, 1).

Là où C3 transmet 2 cartes de caractéristiques à sa convolution de fusion, C2f en transmet n + 2 : chaque sortie intermédiaire du bottleneck est réutilisée.

C3k2 (YOLO11 et YOLO26)#

YOLO11 et YOLO26 utilisent C3k2, une sous-classe de C2f qui remplace l'unité répétitive. Chacun des blocs n devient, selon les indicateurs du constructeur :

  • un Bottleneck simple (par défaut, c3k=False),
  • un bloc C3k (c3k=True) — une variante C3 avec une taille de noyau configurable, ou
  • une paire Bottleneck + PSABlock (attn=True).

Le deuxième argument YAML définit c3k, sauf si l'échelle est m, l ou x, auquel cas elle force cette valeur à True — c'est ainsi qu'un seul yolo11.yaml prend en charge les cinq variantes. Ainsi, [-1, 2, C3k2, [512, False]] construit les éléments internes Bottleneck avec n et s, mais les éléments internes C3k avec m, l et x ; 512 est le nombre de canaux avant mise à l'échelle, que le multiple de largeur de la variante transforme en 128 à n et en 768 à x. Pour les modules CSP, le champ repeats — ici égal à 2, avant sa mise à l'échelle par le multiple de profondeur de la variante — devient le nombre de répétitions internes du bloc, plutôt que d'empiler des modules distincts.

Pooling spatial : SPP → SPPF#

À la fin du backbone, un bloc de pooling par pyramide spatiale élargit le champ réceptif. YOLOv5 a remplacé le SPP original à noyaux multiples par SPPF (Spatial Pyramid Pooling - Fast) : un seul MaxPool2d(kernel_size=5, stride=1, padding=2) appliqué n = 3 fois successivement, avec l'entrée et les trois sorties de pooling concaténées puis fusionnées par un 1x1 Conv. Cela est mathématiquement équivalent à SPP(k=(5, 9, 13)), mais moins coûteux, car les opérations de pooling 5x5 chaînées couvrent les champs réceptifs des noyaux plus grands.

YOLO26 transmet un indicateur de raccourci (SPPF, [1024, 5, 3, True]) ; comme c1 == c2 == 1024 se trouve sur la couche la plus profonde, SPPF ajoute une connexion résiduelle (return y + x).

Attention spatiale : C2PSA (YOLO11+)#

YOLO11 a ajouté C2PSA après SPPF. Il s'agit d'un bloc CSP dont la branche active est une pile de modules n PSABlock (attention sensible à la position) : cv1 = Conv(c1, 2 * c, 1) répartit les caractéristiques, dont une moitié passe par la pile PSABlock, puis cv2 = Conv(2 * c, c1, 1) fusionne la concaténation. Chaque PSABlock applique une attention multi-têtes, suivie d'un réseau feed-forward à deux couches (Conv(c, 2 * c, 1)Conv(2 * c, c, 1)), chacune avec une connexion résiduelle. YOLO26 conserve le même backbone C3k2 + C2PSA.

Neck : FPN + PAN#

Le neck fusionne les cartes de caractéristiques P3/P4/P5 du backbone avec un réseau pyramidal de caractéristiques (FPN) descendant, suivi d'un réseau d'agrégation de chemins (PAN) ascendant. Dans la section head du YAML, FPN correspond à nn.Upsample + Concat (qui transmet les informations sémantiques vers les résolutions supérieures) et PAN à Conv + Concat de stride 2 (qui retransmet les informations de localisation vers le haut) :

# YOLO11 head (FPN top-down, then PAN bottom-up)
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 2, C3k2, [512, False]] # 13
# ... second upsample + concat to P3 ...
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4 (PAN)
- [-1, 2, C3k2, [512, False]] # 19

Le neck réutilise le bloc du backbone de sa génération — C3 dans YOLOv5, C2f dans YOLOv8, C3k2 dans YOLO11 et YOLO26 — de sorte que chaque point de fusion exécute le même module que le backbone. Les trois sorties fusionnées alimentent la head. YOLOv3 fait exception : son neck est uniquement un FPN descendant (sa head YAML ne contient aucun sous-échantillonnage de stride 2), sans le chemin PAN ascendant introduit par YOLOv5.

Head de détection : fondée sur des ancres → anchor-free → sans NMS#

La head transforme les trois cartes de caractéristiques fusionnées en prédictions pour la tâche de détection. Sa conception a évolué au fil des versions, passant d'une approche fondée sur des ancres à une approche anchor-free, puis sans NMS.

Detect anchor-free et découplée#

Les YOLOv3 et YOLOv5 d'origine utilisaient une head fondée sur des ancres et couplée : des boîtes d'ancrage prédéfinies et une branche partagée pour les prédictions de boîtes et de classes. Les dépôts autonomes ultralytics/yolov3 et ultralytics/yolov5 conservent cette conception fondée sur des ancres. Le package principal ultralytics fournit à la place les variantes anchor-free YOLOv3u et YOLOv5u — les mêmes backbones Darknet-53 et C3, avec la head anchor-free Detect de YOLOv8 — et les configurations yolov3.yaml et yolov5.yaml documentées ici sont ces variantes u, et non la conception historique.

La head Detect (head.py) est anchor-free et découplée : pour chaque niveau de la pyramide, elle exécute deux branches parallèles et effectue les prédictions directement sur les points de la grille plutôt que par rapport à des boîtes d'ancrage.

  • Branche des boîtes (cv2) : Conv(x, c2, 3)Conv(c2, c2, 3)Conv2d(c2, 4 * reg_max, 1).
  • Branche des classes (cv3) : dans YOLO11 et YOLO26, deux blocs séparables en profondeur (DWConv + 1x1 Conv) → Conv2d(c3, nc, 1) ; YOLOv8 utilise la variante historique, deux couches 3x3 ConvConv2d(c3, nc, 1).

Chaque point d'ancrage produit donc no = nc + 4 * reg_max sorties. La suppression des ancres prédéfinies élimine des hyperparamètres à régler les tailles et les rapports d'aspect des boîtes d'ancrage.

Perte focale distributionnelle (DFL)#

YOLOv8 et YOLO11 régressent chacune des 4 coordonnées de boîte sous forme de distribution sur reg_max = 16 intervalles, plutôt que comme un scalaire unique (la forme intégrale issue de la perte focale généralisée). Le module DFL redimensionne les canaux de boîte 4 * reg_max en (4, reg_max), applique une softmax sur les reg_max intervalles et prend l'indice d'intervalle attendu — chaque indice d'intervalle étant pondéré par sa probabilité softmax, puis sommé — comme coordonnée prédite. Cette opération est implémentée sous forme d'une convolution 1x1 fixe dont les poids sont les indices d'intervalle arange(reg_max), de sorte que la somme pondérée correspond à un seul produit scalaire.

YOLO26 : sans NMS et sans DFL#

YOLO26 définit deux paramètres YAML que la head lit directement :

  • end2end: TrueDetect copie en profondeur ses branches dans une head one-to-one (one2one_cv2/one2one_cv3) qui produit une seule prédiction par objet, supprimant l'étape de post-traitement de suppression des non-maxima (NMS). Consulte le guide de détection end-to-end pour les détails sur l'export et la migration.
  • reg_max: 1 — avec un seul intervalle, self.dfl devient nn.Identity() et no = nc + 4 ; la head régresse directement les coordonnées et aucune opération DFL n'apparaît dans le graphe ONNX exporté.

Sur ses cinq tailles de modèles (n/s/m/l/x), YOLO26 atteint 40.9 à 57.5 mAP sur COCO, avec une latence TensorRT T4 de 1.7 à 11.8 ms, comme indiqué dans l'article YOLO26.

Résumé version par version#

VersionBloc du backbonePooling spatialAttentionHead de détectionDFL
YOLOv3Darknet-53 (Bottleneck)aucun dans la configuration de baseaucuneOriginale : fondée sur des ancres ; variante u : anchor-freenon / oui (u)
YOLOv5C3 (CSP)SPPFaucuneOriginale : fondée sur des ancres ; variante u : anchor-freenon / oui (u)
YOLOv8C2fSPPFaucuneAnchor-free, découpléeoui (reg_max=16)
YOLO11C3k2SPPFC2PSAAnchor-free, découpléeoui (reg_max=16)
YOLO26C3k2SPPF + raccourciC2PSAAnchor-free, sans NMS (end2end)supprimée (reg_max=1)

Pour les détails par modèle, les tableaux de performances et les exemples d'utilisation, consulte les pages individuelles de YOLOv3, YOLOv5, YOLOv8, YOLO11 et YOLO26.

Inspecte toi-même l'architecture#

La méthode model.info() affiche un résumé des couches, des paramètres et des FLOPs, et la liste des modules analysés est disponible sur model.model.model.

Inspecter l'architecture d'un modèle YOLO
from ultralytics import YOLO

# Load a pretrained model
model = YOLO("yolo11n.pt")

# Fuse Conv + BatchNorm layers so counts match the published specs
model.fuse()

# Print a summary: layers, parameters, gradients, GFLOPs
model.info()

# Inspect the detection head (the last module in the network)
head = model.model.model[-1]
print(type(head).__name__, "| reg_max:", head.reg_max, "| end2end:", head.end2end)

L'exécution de l'extrait sur trois générations montre numériquement les changements. Il s'agit de véritables sorties de modèles fusionnés du package ultralytics, correspondant aux nombres de paramètres et de FLOPs publiés sur chaque page de modèle :

ModèleCouchesParamètresGFLOPsreg_maxend2endCouche DFL
YOLOv8n723,151,9048.716FalseDFL
YOLO11n1002,616,2486.516FalseDFL
YOLO26n1222,408,9325.51TrueIdentity

YOLO26n indique reg_max=1, end2end=True et une couche DFL Identity — la signature architecturale de sa head sans NMS et sans DFL.

Nombres fusionnés et non fusionnés

Les valeurs de paramètres et de FLOPs sont indiquées pour le modèle fusionné (model.fuse()), qui fusionne chaque Conv avec sa couche de normalisation par lot. Cela correspond aux spécifications publiées ; un checkpoint chargé fraîchement indique des nombres légèrement supérieurs avant la fusion.

Conclusion#

Au fil des versions, l'architecture YOLO a évolué étape par étape : le backbone est passé de Darknet-53 aux blocs C3, C2f et C3k2 fondés sur CSP, avec l'attention C2PSA ; le neck a conservé sa structure FPN + PAN tandis que SPP est devenu SPPF ; et la head est passée d'une approche fondée sur des ancres à une approche anchor-free, puis à la conception end-to-end sans NMS et sans DFL de YOLO26.

Pour définir des architectures personnalisées, consulte le Guide de configuration YAML des modèles, ou compare les modèles sur les pages de modèles. Pour toute question, contacte-nous sur GitHub ou Discord.

FAQ#

  • Un modèle YOLO possède un backbone qui extrait les caractéristiques de l'image aux strides 8, 16 et 32, un neck qui fusionne ces caractéristiques entre les échelles avec FPN et PAN, et une head qui prédit les boîtes englobantes et les scores de classe. Chaque modèle Ultralytics YOLO, de YOLOv3 à YOLO26, suit cette conception en trois étapes.

  • C2f (YOLOv8) est un bloc CSP qui concatène les sorties de chaque carte de caractéristiques interne Bottleneckn + 2 — avant sa convolution de fusion, alors que l'ancien C3 n'en transmet que 2. C3k2 (YOLO11 et YOLO26) est une sous-classe de C2f qui peut remplacer chaque Bottleneck par un bloc C3k (une variante de C3 avec une taille de noyau configurable) lorsque son indicateur c3k est défini. Les deux sont définis dans block.py.

  • YOLO11 apporte trois changements structurels à YOLOv8 : il remplace le bloc backbone et neck C2f par C3k2, insère un bloc d'auto-attention C2PSA après SPPF et remplace la branche de classification de la tête par des convolutions séparables en profondeur plus légères. Les deux conservent la même tête Detect découplée et sans ancres, avec une régression DFL reg_max=16, de sorte que ces changements réduisent le nombre de paramètres et de FLOPs tout en améliorant la précision, plutôt que de remanier l'interface de détection.

  • Les modèles YOLO modernes d'Ultralytics sont sans ancres. YOLOv8, YOLO11 et YOLO26 utilisent une tête Detect découplée et sans ancres, avec des branches distinctes pour la régression des boîtes et la classification. Les modèles YOLOv3 et YOLOv5 d'origine étaient basés sur des ancres, mais Ultralytics les fournit sous la forme des variantes YOLOv3u et YOLOv5u, dont les configurations utilisent la même tête sans ancres que YOLOv8.

  • Oui — YOLO26 définit end2end=True, ce qui dote Detect d'une tête un-à-un qui produit une seule prédiction par objet et supprime l'étape de post-traitement de suppression des non-maxima requise par les modèles précédents. Consulte le guide de détection de bout en bout pour plus de détails.

  • La DFL effectue la régression de chaque coordonnée de boîte sous forme de distribution softmax sur les cases reg_max (16 par défaut dans YOLOv8 et YOLO11) et utilise la valeur attendue comme coordonnée, plutôt que de prédire un scalaire unique. YOLO26 définit reg_max=1, de sorte que la couche DFL devient une opération identité, que la tête effectue directement la régression des coordonnées et qu'aucune opération DFL n'apparaît dans les graphes ONNX ou TensorRT exportés.

  • Charge le modèle dans Python et appelle model.info() pour obtenir un résumé des couches, des paramètres et des GFLOPs. Les couches analysées se trouvent dans model.model.model — par exemple, model.model.model[-1] est la tête Detect, qui expose des attributs tels que reg_max et end2end. L'architecture complète est définie dans le fichier de configuration YAML du modèle.

Contributeurs

Commentaires