Ultralytics YOLO27 :
Get Started

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

Chaque modèle Ultralytics YOLO se compose de trois étapes : un backbone qui extrait les caractéristiques, un neck qui les fusionne à différentes échelles et une tête qui prédit les boîtes et les classes. Ce guide décrit les modules de 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 respecte le format [from, repeats, module, args] : la ou les couches qui l'alimentent, le nombre de répétitions du module, la classe de la couche (Conv, C3k2, SPPF, Detect, …) et ses arguments de constructeur. Le guide de configuration YAML des modèles décrit ce format — notamment la façon dont repeats et args évoluent selon les multiplicateurs de profondeur et de largeur de la variante — ainsi que le système de résolution des modules dans son intégralité. Ce guide porte sur les modules eux-mêmes et leur évolution d'une version à l'autre.

Les trois étapes#

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

ÉtapeRôleSortie
BackboneExtraire les caractéristiques de l'image d'entrée à plusieurs résolutionsCartes de caractéristiques avec des strides de 8, 16 et 32 (P3, P4, P5)
NeckFusionner les caractéristiques à différentes échelles afin que les petits et les grands objets disposent tous du contexte nécessaireCartes de caractéristiques fusionnées à plusieurs échelles
TêtePré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 dans cet ordre. Chaque module plus complexe ci-dessous est construit en combinant des blocs Conv.

Schémas d'architecture#

Chaque version conserve le même squelette backbone → neck → head et modifie des étapes spécifiques. 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 têtes YOLOv3 et YOLOv5 sont représentées dans leur forme originale à ancres plutôt qu’avec la tête sans ancres de type u réellement fournie par leurs configurations de package. Le parcours des onglets montre les ajouts de chaque génération. En bref, l’évolution est la suivante : YOLOv3 est un détecteur à ancres doté uniquement d’un FPN ; YOLOv5 ajoute le chemin PAN ascendant et SPPF ; YOLOv8 adopte le bloc C2f avec une tête sans ancres DFL ; YOLO11 ajoute l’attention C2PSA et le bloc C3k2 ; et YOLO26 ajoute un résiduel SPPF, supprime DFL et propose une tête sans NMS en option.

Les schémas de YOLOv3 et YOLOv5 montrent la tête d'origine basée sur des ancres. Le package ultralytics fournit les configurations sans ancres YOLOv3u et YOLOv5u — avec les mêmes backbones Darknet-53 et C3, mais avec la tête Detect de YOLOv8 — décrites dans la section Tête de détection.

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

Le backbone empile un bloc CSP (Cross-Stage Partial) répétitif entre des couches de sous-échantillonnage Conv de stride 2. Ce bloc répétitif est celui qui a le plus évolué d'une version à l'autre. 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 empile directement ces unités, sans séparation CSP, et détecte à trois échelles (strides 8, 16 et 32).

C3 (YOLOv5)#

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

def forward(self, x):
    # C3 : chemin bottleneck m(cv1(x)) concaténé au chemin de contournement cv2(x), puis fusionné par cv3
    return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))

Seule la sortie du dernier bottleneck atteint la convolution de fusion ; cv3 voit donc 2 cartes de caractéristiques.

C2f (YOLOv8)#

Le bloc 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) sépare 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).

Alors que C3 transmet 2 cartes de caractéristiques à sa convolution de fusion, C2f en transmet n + 2 — chaque sortie intermédiaire de 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. Selon les indicateurs du constructeur, chacun des blocs n devient :

  • un simple Bottleneck (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 il est forcé à True — c'est ainsi qu'un seul yolo11.yaml sert les cinq variantes. Ainsi, [-1, 2, C3k2, [512, False]] construit les couches internes Bottleneck à n et s, mais les couches internes C3k à m, l et x ; la valeur 512 correspond au nombre de canaux avant mise à l'échelle, que le multiplicateur de largeur de la variante transforme en 128 à n et en 768 à x. Pour les modules CSP, le champ repeats — ici égal à 2 avant application du multiplicateur de profondeur de la variante — devient le nombre de répétitions internes du bloc, au lieu d'empiler des modules distincts.

Pooling spatial : SPP → SPPF#

À la fin du backbone, un bloc de pooling à 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 de suite, puis concaténé avec l'entrée et les trois sorties du pooling, avant la fusion par un 1x1 Conv. Cette opération est mathématiquement équivalente à SPP(k=(5, 9, 13)), mais moins coûteuse, car les opérations de pooling 5x5 enchaînées couvrent les champs réceptifs des noyaux plus grands.

YOLO26 transmet un indicateur de connexion raccourcie (SPPF, [1024, 5, 3, True]) ; comme c1 == c2 == 1024 se trouve au niveau le plus profond, SPPF ajoute une connexion résiduelle (return y + x).

Attention spatiale : C2PSA (YOLO11 et versions ultérieures)#

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 (Position-Sensitive Attention) : cv1 = Conv(c1, 2 * c, 1) sépare les caractéristiques, 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ête, suivie d'un réseau à propagation avant à 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 à l'aide d'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, le FPN correspond à nn.Upsample + Concat (qui transmettent les informations sémantiques vers les résolutions supérieures) et le PAN à Conv + Concat de stride 2 (qui ramènent les informations de localisation vers les niveaux supérieurs) :

# 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 de backbone de sa génération — C3 dans YOLOv5, C2f dans YOLOv8, C3k2 dans YOLO11 et YOLO26 — de sorte que chaque point de fusion utilise le même module que le backbone. Les trois sorties fusionnées alimentent la tête. YOLOv3 fait exception : son neck utilise uniquement un FPN descendant (la section head de son YAML ne contient pas de sous-échantillonnage de stride 2) et ne comporte pas le chemin PAN ascendant introduit par YOLOv5.

Tête de détection : basée sur des ancres → sans ancres → sans NMS#

La tête 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 : d'abord basée sur des ancres, puis sans ancres et enfin sans NMS.

Detect sans ancres et à branches découplées#

Les versions originales de YOLOv3 et YOLOv5 utilisaient une tête couplée basée sur des ancres : des boîtes d'ancrage prédéfinies et une branche commune aux prédictions de boîtes et de classes. Les dépôts autonomes ultralytics/yolov3 et ultralytics/yolov5 conservent cette conception basée sur des ancres. En revanche, le package principal ultralytics fournit les variantes sans ancres YOLOv3u et YOLOv5u — avec les mêmes backbones Darknet-53 et C3, mais avec la tête Detect sans ancres de YOLOv8 — et les configurations yolov3.yaml et yolov5.yaml décrites ici sont ces variantes u, et non les conceptions historiques.

La tête Detect (head.py) est sans ancres et à branches découplées : à chaque niveau de la pyramide, elle exécute deux branches parallèles et prédit directement aux 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, avec deux couches 3x3 Conv → Conv2d(c3, nc, 1).

Chaque point d'ancrage émet 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 de distribution (DFL)#

YOLOv8 et YOLO11 modélisent chacune des 4 coordonnées de boîte sous forme de distribution sur reg_max = 16 bins plutôt que comme un scalaire unique (la forme intégrale de la perte focale généralisée). Le module DFL remodèle les canaux de boîte 4 * reg_max en (4, reg_max), applique un softmax sur les reg_max bins et calcule l'indice moyen des bins attendus — chaque indice étant pondéré par sa probabilité softmax, puis les valeurs étant additionnées — comme coordonnée prédite. Cette opération est implémentée avec une convolution fixe 1x1 dont les poids sont les indices des bins arange(reg_max), de sorte que la somme pondérée se réduit à un produit scalaire.

YOLO26 : sans NMS et sans DFL#

YOLO26 définit deux paramètres YAML que la tête lit directement :

  • end2end: True — Detect copie en profondeur ses branches dans une tête un-à-un (one2one_cv2/one2one_cv3) qui apprend une prédiction unique par objet. Ce paramètre YAML crée les deux têtes d'entraînement ; à l'exécution, nms=False sélectionne la tête un-à-un et supprime l'étape de post-traitement par suppression non maximale (NMS). Consulte le guide de détection de bout en bout pour en savoir plus sur l'inférence et l'exportation.
  • reg_max: 1 — avec un seul bin, self.dfl devient nn.Identity() et no = nc + 4 ; la tête régresse directement les coordonnées et aucune opération DFL n'apparaît dans le graphe ONNX exporté.

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

Résumé des versions#

VersionBloc du backbonePooling spatialAttentionTête de détectionDFL
YOLOv3Darknet-53 (Bottleneck)aucun dans la configuration de baseaucuneOriginale : basée sur des ancres ; variante u : sans ancresnon / oui (u)
YOLOv5C3 (CSP)SPPFaucuneOriginale : basée sur des ancres ; variante u : sans ancresnon / oui (u)
YOLOv8C2fSPPFaucuneSans ancres, à branches découpléesoui (reg_max=16)
YOLO11C3k2SPPFC2PSASans ancres, à branches découpléesoui (reg_max=16)
YOLO26C3k2SPPF + connexion raccourcieC2PSASans ancres, à deux têtes ; éventuellement sans NMSsupprimé (reg_max=1)

Pour les détails propres à chaque modèle, les tableaux de performances et des exemples d'utilisation, consulte les pages consacrées à YOLOv3, YOLOv5, YOLOv8, YOLO11 et YOLO26.

Inspecte l'architecture toi-même#

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 accessible dans model.model.model.

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

# Charger un modèle préentraîné
model = YOLO("yolo11n.pt")

# Fusionner les couches Conv + BatchNorm pour que les décomptes correspondent aux spécifications publiées
model.fuse()

# Afficher un résumé : couches, paramètres, gradients, GFLOPs
model.info()

# Inspecter la tête de détection (le dernier module du réseau)
head = model.model.model[-1]
print(type(head).__name__, "| reg_max:", head.reg_max, "| DFL layer:", type(head.dfl).__name__)

L'exécution de cet extrait sur trois générations met en évidence les évolutions en chiffres. Il s'agit de sorties réelles de modèles fusionnés du package ultralytics, qui correspondent aux nombres de paramètres et de FLOPs publiés sur chaque page de modèle :

ModèleCouchesParamètresGFLOPsreg_maxCouche DFL
YOLOv8n723,151,9048.716DFL
YOLO11n1002,616,2486.516DFL
YOLO26n1202,408,9325.51Identity

YOLO26n indique reg_max=1 et une couche DFL Identity. Par défaut, la prédiction et la validation utilisent le mode un-à-plusieurs avec NMS ; définis nms=False pour une inférence sans NMS. Les deux têtes sont entraînées.

Nombre de paramètres avec et sans fusion

Les valeurs des paramètres et des FLOPs sont indiquées pour le modèle avec fusion (model.fuse()), qui fusionne chaque Conv avec sa couche de normalisation par lots. Cela correspond aux spécifications publiées ; un point de contrôle fraîchement chargé affiche des valeurs légèrement plus élevées avant la fusion.

Conclusion#

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

Pour définir des architectures personnalisées, consulte le guide de configuration YAML des modèles ou compare les modèles sur les pages des modèles. Pour poser tes questions, contacte-nous sur GitHub ou Discord.

FAQ#

  • Un modèle YOLO comprend un backbone qui extrait les caractéristiques de l’image aux strides 8, 16 et 32, un neck qui fusionne ces caractéristiques à différentes échelles avec FPN et PAN, et une tête qui prédit les boîtes englobantes et les scores de classe. Tous les modèles Ultralytics YOLO, de YOLOv3 à YOLO26, suivent cette architecture en trois étapes.

  • C2f (YOLOv8) est un bloc CSP qui concatène les sorties de chaque Bottleneck — les cartes de caractéristiques n + 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 activé. Les deux sont définis dans block.py.

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

  • Les modèles Ultralytics YOLO modernes 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 versions d’origine de YOLOv3 et YOLOv5 reposaient sur des ancres, mais Ultralytics les distribue sous les variantes YOLOv3u et YOLOv5u, dont les configurations utilisent la même tête sans ancres que YOLOv8.

  • Oui — YOLO26 comprend une tête un-à-un qui prend en charge l’inférence sans NMS avec nms=False. Son parcours d’inférence un-à-plusieurs par défaut utilise NMS, et les deux têtes sont supervisées pendant l’entraînement. Consulte le guide de détection de bout en bout pour en savoir plus.

  • La DFL modélise chaque coordonnée de boîte comme une distribution softmax sur reg_max intervalles (16 par défaut dans YOLOv8 et YOLO11), puis utilise l’espérance comme coordonnée, au lieu de prédire une valeur scalaire unique. YOLO26 définit reg_max=1 ; la couche DFL devient donc une opération identité, la tête régresse directement les coordonnées et 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] correspond à la tête Detect et expose des attributs comme reg_max et dfl. L’architecture complète est définie dans le fichier de configuration YAML du modèle.

Commentaires