Ultralytics YOLO27:
Get Started

Architettura YOLO spiegata: da YOLOv3 a YOLO26#

Ogni modello Ultralytics YOLO è composto da tre fasi: un backbone che estrae le caratteristiche, un neck che le fonde su diverse scale e una head che predice box e classi. Questa guida documenta i moduli che compongono ciascuna fase e come sono cambiati da YOLOv3 a YOLO26, riconducendo ogni componente alla sua definizione nei file di configurazione sotto ultralytics/cfg/models/ e alle classi dei moduli in ultralytics/nn/modules/.

Ogni modello è definito in modo dichiarativo in un file YAML come elenco ordinato di livelli, in cui ogni livello segue il formato [from, repeats, module, args]: quali livelli lo alimentano, quante volte il modulo si ripete, la classe del livello (Conv, C3k2, SPPF, Detect, …) e i relativi argomenti del costruttore. La Guida alla configurazione YAML dei modelli documenta questo formato — compreso il modo in cui repeats e args vengono scalati in base ai moltiplicatori di profondità e larghezza della variante — insieme al sistema completo di risoluzione dei moduli. Questa guida si concentra sui moduli e sulle loro modifiche da una versione all'altra.

Le tre fasi#

Ogni modello Ultralytics YOLO fa passare l'immagine attraverso tre fasi sequenziali, ciascuna con una funzione specifica:

FaseFunzioneOutput
BackboneEstrae caratteristiche dall'immagine in ingresso a più risoluzioniMappe delle caratteristiche con stride 8, 16 e 32 (P3, P4, P5)
NeckFonde le caratteristiche su diverse scale, così che gli oggetti piccoli e grandi dispongano entrambi di un contestoMappe delle caratteristiche fuse multiscala
HeadPredice box di delimitazione e punteggi di classe dalle caratteristiche fuseRilevamenti per punto di ancoraggio

L'unità fondamentale è il blocco Conv (definito in conv.py): una convoluzione 2D, normalizzazione del batch e un'attivazione SiLU, applicate in sequenza. Ogni modulo più complesso qui sotto è composto da blocchi Conv.

Diagrammi dell'architettura#

Ogni versione mantiene lo stesso scheletro backbone → neck → head e modifica fasi specifiche. Le schede qui sotto mostrano la struttura di ciascuna versione: le fasi del backbone e del neck seguono le configurazioni in ultralytics/cfg/models/, mentre le head di YOLOv3 e YOLOv5 sono rappresentate nella loro forma originale basata su anchor, anziché nella head della variante u senza anchor effettivamente inclusa nelle configurazioni dei rispettivi pacchetti. Esaminando le schede puoi vedere cosa ha aggiunto ogni generazione. In breve, l'evoluzione è la seguente: YOLOv3 è un rilevatore basato su anchor e solo FPN; YOLOv5 aggiunge il percorso PAN bottom-up e SPPF; YOLOv8 passa al blocco C2f con una head senza anchor e DFL; YOLO11 integra l'attenzione C2PSA e il blocco C3k2; YOLO26 aggiunge un residuo SPPF, rimuove DFL e aggiunge una head opzionale senza NMS.

I diagrammi di YOLOv3 e YOLOv5 mostrano la head originale basata su anchor. Il pacchetto ultralytics include le configurazioni senza anchor YOLOv3u e YOLOv5u — gli stessi backbone Darknet-53 e C3 con la head Detect di YOLOv8 — descritte nella sezione Head di rilevamento.

Blocchi del backbone: Bottleneck → C3 → C2f → C3k2#

Il backbone impila un blocco CSP (Cross-Stage Partial) ripetuto tra i livelli di downsampling Conv con stride 2. È proprio questo blocco ripetuto a essere cambiato maggiormente tra le versioni. Tutti i blocchi qui sotto si trovano in block.py; c1/c2 sono i canali di input/output e c = 0.5 * c2 è la larghezza nascosta.

Bottleneck (YOLOv3)#

L'unità di base è Bottleneck: due livelli Conv (kernel predefiniti (3, 3)) con un'addizione residua opzionale quando shortcut=True e c1 == c2. Il backbone Darknet-53 di YOLOv3 li impila direttamente, senza suddivisione CSP, ed esegue il rilevamento a tre scale (stride 8, 16, 32).

C3 (YOLOv5)#

Il C3 di YOLOv5 divide l'input tra due convoluzioni 1x1: cv1 alimenta in sequenza i blocchi Bottleneck di n (kernel (1, 1) e poi (3, 3)), mentre cv2 li bypassa. I due percorsi vengono concatenati e fusi da un terzo 1x1 Conv:

def forward(self, x):
    # C3: percorso bottleneck m(cv1(x)) concatenato con il bypass cv2(x), poi fuso da cv3
    return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))

Solo l'output del bottleneck finale raggiunge la convoluzione di fusione, quindi cv3 riceve 2 mappe delle caratteristiche.

C2f (YOLOv8)#

Il C2f di YOLOv8 ("CSP Bottleneck con 2 convoluzioni, più veloce") modifica le caratteristiche che raggiungono la convoluzione di fusione:

  1. cv1 = Conv(c1, 2 * c, 1), quindi chunk(2) divide l'output in due tensori con c canali.
  2. I blocchi Bottleneck(c, c) n (kernel (3, 3), (3, 3)) vengono eseguiti in sequenza; ciascuno riceve l'output del blocco precedente.
  3. Tutti i tensori intermedi n + 2 vengono concatenati e fusi da cv2 = Conv((2 + n) * c, c2, 1).

Mentre C3 invia 2 mappe delle caratteristiche alla propria convoluzione di fusione, C2f ne invia n + 2 — riutilizzando ogni output intermedio del bottleneck.

C3k2 (YOLO11 e YOLO26)#

YOLO11 e YOLO26 usano C3k2, una sottoclasse di C2f che sostituisce l'unità ripetuta. Ciascuno dei blocchi n diventa, a seconda dei flag del costruttore:

  • un semplice Bottleneck (predefinito, c3k=False),
  • un blocco C3k (c3k=True) — una variante C3 con dimensione del kernel configurabile, oppure
  • una coppia Bottleneck + PSABlock (attn=True).

Il secondo argomento YAML imposta c3k, a meno che la scala non sia m, l o x, casi in cui viene forzato a True — così un unico yolo11.yaml serve tutte e cinque le varianti. Quindi [-1, 2, C3k2, [512, False]] costruisce componenti interni Bottleneck con n e s, ma componenti interni C3k con m, l e x; 512 è il numero di canali prima del ridimensionamento, che il moltiplicatore di larghezza della variante porta a 128 con n e a 768 con x. Per i moduli CSP, il campo repeats — qui pari a 2, prima del ridimensionamento tramite il moltiplicatore di profondità della variante — diventa il numero di ripetizioni interne del blocco, anziché determinare l'impilamento di moduli separati.

Pooling spaziale: SPP → SPPF#

Alla fine del backbone, un blocco di pooling a piramide spaziale amplia il campo ricettivo. YOLOv5 ha sostituito SPP multi-kernel originale con SPPF (Spatial Pyramid Pooling - Fast): un singolo MaxPool2d(kernel_size=5, stride=1, padding=2) applicato n = 3 volte in sequenza, concatenando l'input e tutti e tre gli output del pooling e fondendoli con un 1x1 Conv. È matematicamente equivalente a SPP(k=(5, 9, 13)), ma più efficiente, perché i pooling concatenati 5x5 coprono i campi ricettivi dei kernel più grandi.

YOLO26 passa un flag shortcut (SPPF, [1024, 5, 3, True]); poiché c1 == c2 == 1024 si trova al livello più profondo, SPPF aggiunge una connessione residua (return y + x).

Attenzione spaziale: C2PSA (YOLO11+)#

YOLO11 ha aggiunto C2PSA dopo SPPF. È un blocco CSP il cui ramo attivo è una pila di moduli n PSABlock (Position-Sensitive Attention): cv1 = Conv(c1, 2 * c, 1) divide le caratteristiche, una metà attraversa la pila PSABlock e cv2 = Conv(2 * c, c1, 1) fonde la concatenazione. Ogni PSABlock applica l'attenzione multi-head seguita da una rete feed-forward a due livelli (Conv(c, 2 * c, 1) → Conv(2 * c, c, 1)), entrambi con connessione residua. YOLO26 mantiene lo stesso backbone C3k2 + C2PSA.

Neck: FPN + PAN#

Il neck fonde le mappe delle caratteristiche P3/P4/P5 del backbone con una Feature Pyramid Network (FPN) dall'alto verso il basso, seguita da una Path Aggregation Network (PAN) dal basso verso l'alto. Nella sezione head del file YAML, FPN è nn.Upsample + Concat (trasporta le informazioni semantiche verso risoluzioni più alte), mentre PAN è Conv + Concat con stride 2 (riporta verso l'alto le informazioni di localizzazione):

# 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

Il neck riutilizza il blocco del backbone della propria generazione — C3 in YOLOv5, C2f in YOLOv8, C3k2 in YOLO11 e YOLO26 — quindi ogni punto di fusione esegue lo stesso modulo usato dal backbone. I tre output fusi alimentano la head. YOLOv3 fa eccezione: il suo neck è solo una FPN dall'alto verso il basso (la sua sezione head YAML non contiene downsampling con stride 2), senza il percorso PAN dal basso verso l'alto introdotto da YOLOv5.

Head di rilevamento: basata su anchor → senza anchor → senza NMS#

La head converte le tre mappe delle caratteristiche fuse in predizioni per il task di rilevamento. Il suo design è cambiato nel corso delle versioni, passando da basato su anchor a senza anchor, fino a senza NMS.

Detect senza anchor e disaccoppiata#

YOLOv3 e YOLOv5 originali usavano una head basata su anchor e accoppiata: box di ancoraggio predefiniti e un ramo condiviso per le predizioni di box e classi. I repository indipendenti ultralytics/yolov3 e ultralytics/yolov5 mantengono questo design basato su anchor. Il pacchetto principale ultralytics include invece le varianti senza anchor YOLOv3u e YOLOv5u — gli stessi backbone Darknet-53 e C3 con la head Detect senza anchor di YOLOv8 — e le configurazioni yolov3.yaml e yolov5.yaml documentate qui corrispondono a queste varianti u, non al design storico.

La head Detect (head.py) è senza anchor e disaccoppiata: per ogni livello della piramide esegue due rami paralleli e predice direttamente sui punti della griglia, anziché rispetto a box di ancoraggio.

  • Ramo box (cv2): Conv(x, c2, 3) → Conv(c2, c2, 3) → Conv2d(c2, 4 * reg_max, 1).
  • Ramo classi (cv3): in YOLO11 e YOLO26, due blocchi separabili in profondità (DWConv + 1x1 Conv) → Conv2d(c3, nc, 1); YOLOv8 usa la variante precedente, con due livelli 3x3 Conv → Conv2d(c3, nc, 1).

Ogni punto di ancoraggio produce quindi no = nc + 4 * reg_max output. Eliminando gli anchor predefiniti, si rimuovono dalle iperparametri da ottimizzare le dimensioni e i rapporti d'aspetto dei box di ancoraggio.

Distribution Focal Loss (DFL)#

YOLOv8 e YOLO11 regrediscono ciascuna delle 4 coordinate del box come distribuzione su reg_max = 16 bin, anziché come singolo valore scalare (la formulazione integrale della Generalized Focal Loss). Il modulo DFL rimodella i 4 * reg_max canali del box in (4, reg_max), applica una softmax sui reg_max bin e prende come coordinata predetta l'indice atteso del bin — ossia la somma degli indici di ciascun bin ponderati per la rispettiva probabilità softmax. Questa operazione è implementata come una convoluzione 1x1 fissa, i cui pesi sono gli indici dei bin arange(reg_max), quindi la somma ponderata corrisponde a un singolo prodotto scalare.

YOLO26: senza NMS e senza DFL#

YOLO26 imposta due parametri YAML letti direttamente dalla head:

  • end2end: True — Detect copia in profondità i suoi rami in una head one-to-one (one2one_cv2/one2one_cv3) che impara una singola predizione per oggetto. Questa impostazione YAML crea entrambe le head di addestramento; in fase di esecuzione, nms=False seleziona la head one-to-one e rimuove il passaggio di post-elaborazione Non-Maximum Suppression (NMS). Consulta la guida al rilevamento end-to-end per i dettagli sull'inferenza e sull'esportazione.
  • reg_max: 1 — con un solo bin, self.dfl diventa nn.Identity() e no = nc + 4; la head regredisce direttamente le coordinate e nel grafo ONNX esportato non compare alcuna operazione DFL.

Nelle sue cinque dimensioni di modello (n/s/m/l/x), YOLO26 raggiunge 40.9-57.5 mAP su COCO con una latenza TensorRT T4 di 1.7-11.8 ms, come riportato nell'articolo di YOLO26.

Riepilogo versione per versione#

VersioneBlocco del backbonePooling spazialeAttenzioneHead di rilevamentoDFL
YOLOv3Darknet-53 (Bottleneck)nessuno nella configurazione di basenessunaOriginale: basata su anchor; variante u: senza anchorno / sì (u)
YOLOv5C3 (CSP)SPPFnessunaOriginale: basata su anchor; variante u: senza anchorno / sì (u)
YOLOv8C2fSPPFnessunaSenza anchor, disaccoppiatasì (reg_max=16)
YOLO11C3k2SPPFC2PSASenza anchor, disaccoppiatasì (reg_max=16)
YOLO26C3k2SPPF + shortcutC2PSASenza anchor, doppia head; NMS opzionalerimosso (reg_max=1)

Per i dettagli sui singoli modelli, le tabelle delle prestazioni e gli esempi d'uso, consulta le pagine dedicate a YOLOv3, YOLOv5, YOLOv8, YOLO11 e YOLO26.

Esamina direttamente l'architettura#

Il metodo model.info() stampa un riepilogo di livelli, parametri e FLOPs; l'elenco dei moduli analizzati è disponibile su model.model.model.

Esamina l'architettura di un modello YOLO
from ultralytics import YOLO

# Carica un modello preaddestrato
model = YOLO("yolo11n.pt")

# Fondi i livelli Conv + BatchNorm per far corrispondere i conteggi alle specifiche pubblicate
model.fuse()

# Stampa un riepilogo: livelli, parametri, gradienti, GFLOPs
model.info()

# Esamina la head di rilevamento (l'ultimo modulo della rete)
head = model.model.model[-1]
print(type(head).__name__, "| reg_max:", head.reg_max, "| DFL layer:", type(head.dfl).__name__)

Eseguendo lo snippet su tre generazioni, le modifiche emergono chiaramente dai numeri. Si tratta di output reali di modelli fusi del pacchetto ultralytics, che corrispondono ai conteggi di parametri e FLOPs pubblicati su ciascuna pagina del modello:

ModelloLivelliParametriGFLOPsreg_maxLivello DFL
YOLOv8n723,151,9048.716DFL
YOLO11n1002,616,2486.516DFL
YOLO26n1202,408,9325.51Identity

YOLO26n riporta reg_max=1 e un livello DFL Identity. Per impostazione predefinita, la predizione e la validazione usano one-to-many con NMS; imposta nms=False per l'inferenza senza NMS. Entrambe le head vengono addestrate.

Conteggi con e senza fusione

I valori di parametri e FLOPs sono riportati per il modello fuso (model.fuse()), che unisce ogni Conv al relativo livello di normalizzazione del batch. Questo corrisponde alle specifiche pubblicate; un checkpoint appena caricato mostra conteggi leggermente superiori prima della fusione.

Conclusione#

Nel corso delle versioni, l'architettura YOLO è cambiata una fase alla volta: il backbone è passato da Darknet-53 a blocchi C3, C2f e C3k2 basati su CSP, con attenzione C2PSA; il neck ha mantenuto la struttura FPN + PAN, mentre SPP è diventato SPPF; la head è passata da basata su anchor a senza anchor, per poi arrivare al design di YOLO26 senza DFL e con una head end-to-end opzionale senza NMS.

Per definire architetture personalizzate, consulta la Guida alla configurazione YAML del modello oppure confronta i modelli nelle pagine dei modelli. Per domande, contattaci su GitHub o Discord.

Domande frequenti#

  • Un modello YOLO ha un backbone che estrae caratteristiche dall'immagine con stride 8, 16 e 32, un neck che fonde queste caratteristiche su scale diverse con FPN e PAN e una head che predice bounding box e punteggi di classe. Tutti i modelli Ultralytics YOLO da YOLOv3 a YOLO26 seguono questo design a tre stadi.

  • C2f (YOLOv8) è un blocco CSP che concatena gli output di ogni Bottleneck — mappe di caratteristiche n + 2 — prima della convoluzione di fusione, mentre il precedente C3 ne trasferisce solo 2. C3k2 (YOLO11 e YOLO26) è una sottoclasse di C2f che può sostituire ogni Bottleneck con un blocco C3k (una variante C3 con dimensione del kernel configurabile) quando è attivo il flag c3k. Entrambi sono definiti in block.py.

  • YOLO11 apporta tre modifiche strutturali a YOLOv8: sostituisce il blocco del backbone e del neck C2f con C3k2, inserisce un blocco di self-attention C2PSA dopo SPPF e passa a convoluzioni depthwise separable più leggere nel ramo di classificazione della head. Entrambi mantengono la stessa head Detect disaccoppiata e anchor-free con regressione DFL reg_max=16, quindi le modifiche riducono i conteggi di parametri e FLOPs aumentando l'accuratezza, anziché riprogettare l'interfaccia di rilevamento.

  • I moderni modelli Ultralytics YOLO sono anchor-free. YOLOv8, YOLO11 e YOLO26 usano una head Detect disaccoppiata e anchor-free, con rami separati per la regressione delle bounding box e la classificazione. Gli originali YOLOv3 e YOLOv5 erano basati su anchor, ma Ultralytics li distribuisce nelle varianti YOLOv3u e YOLOv5u, le cui configurazioni usano la stessa head anchor-free di YOLOv8.

  • Sì: YOLO26 include una head one-to-one che supporta l'inferenza senza NMS con nms=False. Il percorso di inferenza predefinito one-to-many usa NMS ed entrambe le head ricevono supervisione durante l'addestramento. Per i dettagli, consulta la Guida al rilevamento end-to-end.

  • La DFL regredisce ogni coordinata della box come una distribuzione softmax su reg_max bin (16 per impostazione predefinita in YOLOv8 e YOLO11) e usa il valore atteso come coordinata, invece di predire un singolo scalare. YOLO26 imposta reg_max=1, così il livello DFL diventa un'operazione identità, la head regredisce direttamente le coordinate e nei grafi ONNX o TensorRT esportati non compare alcuna operazione DFL.

  • Carica il modello in Python e chiama model.info() per ottenere un riepilogo dei livelli, dei parametri e dei GFLOPs. I livelli analizzati si trovano in model.model.model: per esempio, model.model.model[-1] è la head Detect ed espone attributi come reg_max e dfl. L'intera architettura è definita nel file di configurazione YAML del modello.

Commenti