Explication de l'architecture YOLO : de YOLOv3 à YOLO26#
Chaque modèle Ultralytics YOLO est construit à partir de trois étapes : une backbone qui extrait les caractéristiques, un neck qui les fusionne à travers les échelles, et un head qui prédit les boîtes et les classes. Ce guide documente les modules qui composent chaque étape et la manière dont ils ont évolué de YOLOv3 à YOLO26, en retraçant chaque composant jusqu'à sa définition dans les fichiers de configuration sous ultralytics/cfg/models/ et les 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] : la ou les couches sources dont elle dépend, le nombre de répétitions du module, la classe de couche (Conv, C3k2, SPPF, Detect, …) et ses arguments de constructeur. Le guide de configuration YAML du modèle documente ce format — y compris la manière dont repeats et args s'adaptent aux multiples de profondeur et de largeur de la variante — ainsi que le système de résolution des modules en détail. 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 achemine l'image à travers trois étapes séquentielles, chacune ayant une fonction distincte :
| Étape | Fonction | Sortie |
|---|---|---|
| Backbone | Extraire les caractéristiques de l'image d'entrée à plusieurs résolutions | Cartes de caractéristiques aux strides 8, 16 et 32 (P3, P4, P5) |
| Neck | Fusionner les caractéristiques à travers les échelles pour que les petits et grands objets bénéficient tous d'un contexte | Cartes de caractéristiques fusionnées multi-échelles |
| Head | Prédire les boîtes englobantes et les scores de classe à partir des caractéristiques fusionnées | Détections par point d'ancrage |
L'unité fondamentale est le bloc Conv (défini dans conv.py) : une convolution 2D, une normalisation par lots et une activation SiLU, appliquées en séquence. Chaque module plus grand ci-dessous est construit en composant des blocs Conv.
Diagrammes 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 par version : les étapes de la backbone et du neck suivent les configurations de ultralytics/cfg/models/, tandis que les heads de YOLOv3 et YOLOv5 sont dessinés dans leur forme originale basée sur des ancres plutôt que dans le head de variante u sans ancres que leurs configurations de paquets embarquent réellement. Parcourir les onglets montre ce que chaque génération a ajouté. En bref, la progression est la suivante : YOLOv3 est un détecteur basé sur des ancres et uniquement FPN ; YOLOv5 ajoute le chemin PAN ascendant et SPPF ; YOLOv8 bascule vers le bloc C2f avec un head sans ancres et DFL ; YOLO11 insère l'attention C2PSA et le bloc C3k2 ; et YOLO26 ajoute un résiduel SPPF et rend le head sans NMS et sans DFL. Les couleurs des nœuds suivent la convention des diagrammes de documentation : vert pour l'entrée, bleu pour la backbone, ardoise pour le pooling spatial et l'attention, orange pour le neck, violet pour le head et la sortie.
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:#fffLes diagrammes de YOLOv3 et YOLOv5 affichent le head original basé sur des ancres. Le paquet ultralytics embarque les configurations sans ancres YOLOv3u et YOLOv5u — les mêmes backbones Darknet-53 et C3 avec le head Detect de YOLOv8 — décrites sous Head de détection.
Blocs de backbone : Bottleneck → C3 → C2f → C3k2#
La backbone empile un bloc CSP (Cross-Stage Partial) répété entre des couches de sous-échantillonnage Conv de pas 2. Ce bloc répété est ce qui a le plus changé d'une version à l'autre. Tous les blocs ci-dessous se trouvent dans block.py ; c1/c2 représentent les canaux d'entrée/sortie et c = 0.5 * c2 est la largeur cachée.
Bottleneck (YOLOv3)#
L'unité de base est Bottleneck : deux couches Conv (noyaux par défaut (3, 3)) avec un ajout résiduel optionnel lorsque shortcut=True et c1 == c2. La backbone Darknet-53 de YOLOv3 empile ces éléments directement, sans division CSP, et détecte à trois échelles (pas 8, 16, 32).
C3 (YOLOv5)#
YOLOv5 divise ton C3 de l'entrée en deux convolutions 1x1 : cv1 alimente des blocs Bottleneck séquentiels de n (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 bloc bottleneck final atteint la convolution de fusion, de sorte que cv3 voit 2 cartes de caractéristiques.
C2f (YOLOv8)#
Le C2f ("CSP Bottleneck with 2 convolutions, faster") de YOLOv8 modifie les caractéristiques qui atteignent la conv de fusion :
cv1 = Conv(c1, 2 * c, 1), puischunk(2)divise la sortie en deux tenseurs de canauxc.- Des blocs
nBottleneck(c, c)(noyaux(3, 3),(3, 3)) s'exécutent séquentiellement, chacun étant alimenté par la sortie du bloc précédent. - Tous les tenseurs intermédiaires de
n + 2sont concaténés et fusionnés parcv2 = Conv((2 + n) * c, c2, 1).
Là où C3 transmet 2 cartes de caractéristiques dans sa convolution de fusion, C2f en transmet n + 2 — chaque sortie de bottleneck intermédiaire est réutilisée.
C3k2 (YOLO11 et YOLO26)#
YOLO11 et YOLO26 utilisent C3k2, une sous-classe de C2f qui échange l'unité répétitive. Chacun des blocs n devient, selon les indicateurs du constructeur :
- un
Bottlenecksimple (par défaut,c3k=False), - un bloc
C3k(c3k=True) — une variante deC3avec une taille de noyau configurable, ou - une paire
Bottleneck+PSABlock(attn=True).
Le deuxième argument YAML définit c3k ; par exemple, [-1, 2, C3k2, [512, True]] construit un module C3k2 à 512 canaux de sortie dont les blocs internes sont C3k (puisque c3k=True). Pour les modules CSP, le champ repeats — ici 2, avant d'être mis à l'échelle par le multiple de profondeur de la variante — devient le nombre de répétitions internes du bloc au lieu d'empiler des modules séparés.
Spatial Pooling : SPP → SPPF#
À la fin de la backbone, un bloc de pooling spatial en pyramide élargit le champ récepteur. YOLOv5 a remplacé le SPP multi-noyau d'origine par SPPF (Spatial Pyramid Pooling - Fast) : un seul MaxPool2d(kernel_size=5, stride=1, padding=2) appliqué n = 3 fois en séquence, l'entrée et les trois sorties mises en commun étant concaténées et fusionnées par un 1x1 Conv. C'est mathématiquement équivalent à SPP(k=(5, 9, 13)) mais moins coûteux, car les pools enchaînés de 5x5 couvrent les champs récepteurs des noyaux plus grands.
YOLO26 transmet un indicateur de raccourci (SPPF, [1024, 5, 3, True]) ; puisque c1 == c2 == 1024 se trouve à la couche la plus profonde, SPPF ajoute une connexion résiduelle (return y + x).
Spatial Attention : 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 (Position-Sensitive Attention) : cv1 = Conv(c1, 2 * c, 1) divise les caractéristiques, une moitié passe par la pile PSABlock, et cv2 = Conv(2 * c, c1, 1) fusionne la concaténation. Chaque PSABlock applique une attention multi-tête 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 la même backbone C3k2 + C2PSA.
Neck : FPN + PAN#
Le neck fusionne les cartes de caractéristiques P3/P4/P5 de la 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 YAML du head, le FPN est nn.Upsample + Concat (transportant des informations sémantiques vers les résolutions supérieures) et le PAN est Conv + Concat de pas 2 (transportant des 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]] # 19Le neck réutilise le bloc 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 celui utilisé par la backbone. Les trois sorties fusionnées alimentent le head. YOLOv3 fait exception : son neck est uniquement un FPN descendant (son head YAML n'a pas de sous-échantillonnage de pas 2), sans le chemin PAN ascendant introduit par YOLOv5.
Detection Head : Anchor-Based → Anchor-Free → NMS-Free#
Le head transforme les trois cartes de caractéristiques fusionnées en prédictions pour la tâche de détection. Sa conception a évolué à travers les versions, passant d'un modèle basé sur des ancres à un modèle sans ancres, puis sans NMS.
Detect découplé et sans ancres#
Les YOLOv3 et YOLOv5 originaux utilisaient un head couplé et basé sur des ancres : 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 basée sur des ancres. Le paquet principal ultralytics propose plutôt les variantes sans ancres YOLOv3u et YOLOv5u — les mêmes backbones Darknet-53 et C3 avec le head Detect sans ancres de YOLOv8 — et les configurations yolov3.yaml et yolov5.yaml documentées ici sont ces variantes u, et non la conception historique.
Le head Detect (head.py) est sans ancres et découplé : par niveau de pyramide, il exécute deux branches parallèles et prédit directement sur les points de la grille plutôt que par rapport à des boîtes d'ancrage.
- Branche de boîte (
cv2) :Conv(x, c2, 3)→Conv(c2, c2, 3)→Conv2d(c2, 4 * reg_max, 1). - Branche de classe (
cv3) : dans YOLO11 et YOLO26, deux blocs séparables en profondeur (DWConv+1x1 Conv) →Conv2d(c3, nc, 1); YOLOv8 utilise la variante héritée, deux couches3x3 Conv→Conv2d(c3, nc, 1).
Chaque point d'ancrage émet donc des sorties no = nc + 4 * reg_max. La suppression des ancres prédéfinies élimine les tailles et rapports d'aspect des boîtes d'ancrage des hyperparamètres devant être ajustés.
Distribution Focal Loss (DFL)#
YOLOv8 et YOLO11 régressent chacune des 4 coordonnées de boîte sous forme de distribution sur des bacs (bins) reg_max = 16 plutôt que comme un simple scalaire (la forme intégrale issue de Generalized Focal Loss). Le module DFL redimensionne les canaux de boîte 4 * reg_max à (4, reg_max), applique un softmax sur les bacs reg_max, et prend l'indice de bac attendu — chaque indice de bac étant pondéré par sa probabilité softmax, puis sommé — comme coordonnée prédite. Ceci est implémenté sous la forme d'une convolution fixe 1x1 dont les poids sont les indices de bac arange(reg_max), de sorte que la somme pondérée est un simple produit scalaire.
YOLO26 : sans NMS, sans DFL#
YOLO26 définit deux paramètres YAML que le head lit directement :
end2end: True—Detectcopie en profondeur ses branches dans un head bi-univoque (one2one_cv2/one2one_cv3) qui produit une seule prédiction par objet, supprimant l'étape de post-traitement de suppression non maximale (NMS). Consultez le guide de détection de bout en bout pour les détails d'exportation et de migration.reg_max: 1— avec un seul bac,self.dfldevientnn.Identity()etno = nc + 4; le head régressse directement les coordonnées et aucune opération DFL n'apparaît dans le graphe ONNX exporté.
À travers ses cinq tailles de modèles (n/s/m/l/x), YOLO26 atteint 40,9 à 57,5 de mAP sur COCO pour une latence T4 TensorRT de 1,7 à 11,8 ms, comme indiqué dans l'article de YOLO26.
Résumé version par version#
| Version | Bloc de backbone | Spatial pooling | Attention | Detection head | DFL |
|---|---|---|---|---|---|
| YOLOv3 | Darknet-53 (Bottleneck) | aucun dans la config de base | aucun | Original : basé sur des ancres ; variante u : sans ancres | non / oui (u) |
| YOLOv5 | C3 (CSP) | SPPF | aucun | Original : basé sur des ancres ; variante u : sans ancres | non / oui (u) |
| YOLOv8 | C2f | SPPF | aucun | Sans ancres, découplée | oui (reg_max=16) |
| YOLO11 | C3k2 | SPPF | C2PSA | Sans ancres, découplée | oui (reg_max=16) |
| YOLO26 | C3k2 | SPPF + raccourci | C2PSA | Sans ancres, sans NMS (end2end) | supprimé (reg_max=1) |
Pour des détails par modèle, des tableaux de performance et des exemples d'utilisation, consultez les pages individuelles de YOLOv3, YOLOv5, YOLOv8, YOLO11 et YOLO26.
Inspectez l'architecture par vous-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 disponible sur model.model.model.
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 à travers trois générations montre les modifications numériquement. Il s'agit de véritables sorties de modèles fusionnés provenant du paquet ultralytics, correspondant aux nombres de paramètres et de FLOPs publiés sur chaque page de modèle :
| Modèle | Couches | Paramètres | GFLOPs | reg_max | end2end | Couche DFL |
|---|---|---|---|---|---|---|
| YOLOv8n | 72 | 3,151,904 | 8.7 | 16 | False | DFL |
| YOLO11n | 100 | 2,616,248 | 6.5 | 16 | False | DFL |
| YOLO26n | 122 | 2,408,932 | 5.4 | 1 | True | Identity |
YOLO26n rapporte reg_max=1, end2end=True et une couche DFL Identity — la signature architecturale de son head sans NMS et sans DFL.
Les valeurs des paramètres et des FLOPs sont rapportées pour le modèle fusionné (model.fuse()), qui combine chaque Conv et sa couche de normalisation par lots. Cela correspond aux spécifications publiées ; un point de contrôle fraîchement chargé rapporte des totaux légèrement plus élevés avant la fusion.
Conclusion#
Au fil des versions, l'architecture YOLO a évolué une étape à la fois : la backbone est passée de Darknet-53 à des blocs CSP C3, C2f et C3k2 dotés d'une attention C2PSA ; le neck a conservé sa structure FPN + PAN tandis que SPP est devenu SPPF ; et le head est passé d'un modèle basé sur des ancres à un modèle sans ancres, puis à la conception de bout en bout sans NMS ni DFL de YOLO26.
Pour définir des architectures personnalisées, consultez le guide de configuration YAML du modèle ou comparez les modèles sur les pages de modèles. Pour toute question, contactez-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 à travers différentes é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 chaqueBottleneckinterne —n + 2cartes de caractéristiques — avant sa convolution de fusion, là où l'ancienC3n'en transmet que 2.C3k2(YOLO11 et YOLO26) est une sous-classe deC2fqui peut remplacer chaqueBottleneckpar un blocC3k(une variante deC3avec une taille de noyau configurable) lorsque son indicateurc3kest activé. Tous deux sont définis dansblock.py.YOLO11 apporte trois modifications structurelles à YOLOv8 : il remplace le bloc de backbone et de neck de
C2fparC3k2, insère un bloc d'auto-attentionC2PSAaprèsSPPF, et bascule la branche de classification du head vers des convolutions séparables en profondeur plus légères. Les deux conservent le même headDetectdécouplé et sans ancres avec la régression DFL dereg_max=16, de sorte que les modifications réduisent le nombre de paramètres et de FLOPs tout en augmentant la précision au lieu de redessiner l'interface de détection.Les modèles Ultralytics YOLO modernes sont sans ancres. YOLOv8, YOLO11 et YOLO26 utilisent un head
Detectdécouplé et sans ancres doté de branches séparées pour la régression des boîtes et la classification. Les YOLOv3 et YOLOv5 originaux étaient basés sur des ancres, mais Ultralytics les propose sous les variantes YOLOv3u et YOLOv5u, dont les configurations utilisent le même head sans ancres que YOLOv8.Oui — YOLO26 définit
end2end=True, ce qui doteDetectd'un head bi-univoque produisant une seule prédiction par objet et supprime l'étape de post-traitement de suppression non maximale requise par les modèles précédents. Consultez le guide de détection de bout en bout pour plus de détails.Le DFL régresse chaque coordonnée de boîte sous forme de distribution softmax sur des bacs
reg_max(16 par défaut dans YOLOv8 et YOLO11) et prend la valeur attendue comme coordonnée, plutôt que de prédire un scalaire unique. YOLO26 définitreg_max=1, de sorte que la couche DFL devient une opération d'identité, que le head régressse directement les coordonnées et qu'aucune opération DFL n'apparaît dans les graphes ONNX ou TensorRT exportés.
Chargez le modèle en Python et appelez
model.info()pour obtenir un résumé des couches, des paramètres et des GFLOPs. Les couches analysées se trouvent dansmodel.model.model— par exemple,model.model.model[-1]est le headDetect, exposant des attributs tels quereg_maxetend2end. L'architecture complète est définie dans le fichier de configuration YAML du modèle.