Guida alla configurazione YAML del modello#
Il file di configurazione YAML del modello funge da progetto architetturale per le reti neurali Ultralytics. Definisce come si collegano i livelli, quali parametri usa ciascun modulo e come viene scalata l'intera rete per adattarsi a modelli di dimensioni diverse.
Struttura della configurazione#
I file YAML dei modelli sono organizzati in tre sezioni principali che collaborano per definire l'architettura.
Sezione dei parametri#
La sezione parameters specifica le caratteristiche globali e il comportamento di scaling del modello:
# 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 onlyncimposta il numero di classi che il modello prevede.scalesdefinisce fattori di scaling composti che modificano profondità, larghezza e numero massimo di canali del modello per generare varianti di dimensioni diverse (da nano a extra-large).kpt_shapesi applica ai modelli di stima della posa. Può essere[N, 2]per i punti chiave(x, y)o[N, 3]per(x, y, visibility).
Il parametro scales consente di generare modelli di dimensioni diverse da un unico YAML di base. Ad esempio, quando carichi yolo26n.yaml, Ultralytics legge il file di base yolo26.yaml e applica i fattori di scaling n (depth=0.50, width=0.25) per creare la variante nano.
Se il tuo dataset specifica un nc o un kpt_shape diverso, Ultralytics sovrascriverà automaticamente la configurazione del modello in fase di esecuzione per adattarla al file YAML del dataset.
Architettura del backbone e della head#
L'architettura del modello è composta dalle sezioni backbone (estrazione delle caratteristiche) e head (specifica per l'attività):
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 layerGli indici dei livelli proseguono dal backbone alla head e le mappe delle caratteristiche concatenate devono avere dimensioni spaziali corrispondenti.
Formato delle specifiche dei livelli#
Ogni livello segue uno schema coerente: [from, repeats, module, args]
| Componente | Scopo | Esempi |
|---|---|---|
| from | Connessioni di input | -1 (precedente), 6 (livello 6), [4, 6, 8] (input multipli) |
| repeats | Numero di ripetizioni | 1 (singolo), 3 (ripeti 3 volte) |
| module | Tipo di modulo | Conv, C2f, TorchVision, Detect |
| args | Argomenti del modulo | [64, 3, 2] (canali, kernel, stride) |
Schemi di connessione#
Il campo from crea schemi flessibili di flusso dei dati in tutta la rete:
- [-1, 1, Conv, [64, 3, 2]] # Takes input from previous layerI livelli sono indicizzati a partire da 0. Gli indici negativi fanno riferimento ai livelli precedenti (-1 = livello precedente), mentre gli indici positivi fanno riferimento a livelli specifici in base alla loro posizione.
Ripetizione dei moduli#
Il parametro repeats crea sezioni di rete più profonde:
- [-1, 3, C2f, [128, True]] # Creates 3 consecutive C2f blocks
- [-1, 1, Conv, [64, 3, 2]] # Single convolution layerIl numero effettivo di ripetizioni viene moltiplicato per il fattore di scaling della profondità definito dalla configurazione delle dimensioni del modello.
Moduli disponibili#
I moduli sono organizzati per funzionalità e definiti nella directory dei moduli Ultralytics. Le tabelle seguenti mostrano i moduli più usati per categoria; il codice sorgente ne contiene molti altri:
Operazioni di base#
| Modulo | Scopo | Origine | Argomenti |
|---|---|---|---|
Conv | Convoluzione + BatchNorm + attivazione | conv.py | [out_ch, kernel, stride, pad, groups] |
nn.Upsample | Upsampling spaziale | PyTorch | [size, scale_factor, mode] |
nn.Identity | Operazione pass-through | PyTorch | [] |
Blocchi compositi#
| Modulo | Scopo | Origine | Argomenti |
|---|---|---|---|
C2f | Bottleneck CSP con 2 convoluzioni | block.py | [out_ch, shortcut, groups, expansion] |
SPPF | Spatial Pyramid Pooling (veloce) | block.py | [out_ch, kernel_size] |
Concat | Concatenazione lungo i canali | conv.py | [dimension] |
Moduli specializzati#
| Modulo | Scopo | Origine | Argomenti |
|---|---|---|---|
TorchVision | Carica qualsiasi modello torchvision | block.py | [out_ch, model_name, weights, unwrap, truncate, split] |
Index | Estrai un tensore specifico da un elenco | conv.py | [out_ch, index] |
Detect | Head di rilevamento YOLO | head.py | [nc] |
Questo rappresenta un sottoinsieme dei moduli disponibili. Per l'elenco completo dei moduli e dei relativi parametri, consulta la directory dei moduli.
Funzionalità avanzate#
Integrazione con TorchVision#
Il modulo TorchVision consente di integrare facilmente qualsiasi modello TorchVision come backbone:
from ultralytics import YOLO
# Modello con backbone ConvNeXt
model = YOLO("convnext_backbone.yaml")
results = model.train(data="imagenet10", epochs=100)Imposta l'ultimo parametro su True per ottenere mappe delle caratteristiche intermedie per il rilevamento multi-scala.
Modulo Index per la selezione delle caratteristiche#
Quando usi modelli che producono più mappe delle caratteristiche, il modulo Index seleziona output specifici:
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 detectionSistema di risoluzione dei moduli#
Capire come Ultralytics individua e importa i moduli è fondamentale per personalizzarli:
Procedura di ricerca dei moduli#
Ultralytics usa un sistema a tre livelli in parse_model:
# Logica di risoluzione principale
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]
) # recupera il modulo- Moduli PyTorch: i nomi che iniziano con
'nn.'→ namespacetorch.nn - Operazioni TorchVision: i nomi che iniziano con
'torchvision.ops.'→ namespacetorchvision.ops - Moduli Ultralytics: tutti gli altri nomi → namespace globale tramite le importazioni
Catena di importazione dei moduli#
I moduli standard diventano disponibili tramite le importazioni in tasks.py:
from ultralytics.nn.modules import ( # noqa: F401
SPPF,
C2f,
Conv,
Detect,
# ... molti altri moduli
Index,
TorchVision,
)Integrazione di moduli personalizzati#
Modifica del codice sorgente#
Modificare il codice sorgente è il modo più versatile per integrare moduli personalizzati, ma può essere complicato. Per definire e usare un modulo personalizzato, segui questi passaggi:
-
Installa Ultralytics in modalità sviluppo usando il metodo di clonazione Git descritto nella guida introduttiva.
-
Definisci il tuo modulo in
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) -
Esponi il tuo modulo a livello di pacchetto in
ultralytics/nn/modules/__init__.py:from .block import CustomBlock # noqa makes CustomBlock available as ultralytics.nn.modules.CustomBlock -
Aggiungi le importazioni in
ultralytics/nn/tasks.py:from ultralytics.nn.modules import CustomBlock # noqa -
Aggiungi il modulo a
base_modulesall'interno diparse_model(). I moduli in questo insieme ricevono automaticamente i canali di input e output:base_modules = frozenset( { # Moduli esistenti... CustomBlock, } ) -
Usa il modulo nel file YAML del modello:
# custom_model.yaml nc: 1 backbone: - [-1, 1, CustomBlock, [64]] head: - [-1, 1, Classify, [nc]] -
Controlla i FLOPs per verificare che il passaggio forward funzioni:
from ultralytics import YOLO model = YOLO("custom_model.yaml", task="classify") model.info() # dovrebbe stampare FLOPs diversi da zero se funziona
Esempi di configurazione#
Modello di rilevamento di 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]] # 7Modello con 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 detectionModello di classificazione#
# 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 esegue già internamente l'average pooling adattivo.
Best practice#
Consigli per la progettazione dell'architettura#
Inizia in modo semplice: comincia da architetture collaudate prima di personalizzarle. Usa le configurazioni YOLO esistenti come modelli di riferimento e apporta modifiche graduali invece di costruire tutto da zero.
Esegui test incrementali: convalida ogni modifica passo dopo passo. Aggiungi un modulo personalizzato alla volta e verifica che funzioni prima di procedere con la modifica successiva.
Monitora i canali: assicurati che le dimensioni dei canali corrispondano tra i livelli collegati. I canali di output (c2) di un livello devono corrispondere ai canali di input (c1) del livello successivo nella sequenza.
Usa connessioni skip: sfrutta il riutilizzo delle feature con i pattern [[-1, N], 1, Concat, [1]]. Queste connessioni migliorano il flusso del gradiente e consentono al modello di combinare feature provenienti da scale diverse.
Scegli la scala appropriata: scegli le scale del modello in base ai tuoi vincoli computazionali. Usa nano (n) per i dispositivi edge, small (s) per prestazioni bilanciate e le scale più grandi (m, l, x) per ottenere la massima accuratezza.
Considerazioni sulle prestazioni#
Profondità e larghezza: le reti profonde acquisiscono feature gerarchiche complesse attraverso più livelli di trasformazione, mentre le reti larghe elaborano più informazioni in parallelo a ogni livello. Bilancia questi aspetti in base alla complessità del tuo compito.
Connessioni skip: migliorano il flusso del gradiente durante l'addestramento e consentono di riutilizzare le feature in tutta la rete. Sono particolarmente importanti nelle architetture più profonde per evitare la scomparsa del gradiente.
Blocchi bottleneck: riducono il costo computazionale mantenendo l'espressività del modello. Moduli come C2f usano meno parametri delle convoluzioni standard, preservando la capacità di apprendere le feature.
Feature multi-scala: sono essenziali per rilevare oggetti di dimensioni diverse nella stessa immagine. Usa pattern di rete piramidale delle feature (FPN) con più head di rilevamento a scale diverse.
Risoluzione dei problemi#
Problemi comuni#
| Problema | Causa | Soluzione |
|---|---|---|
KeyError: 'ModuleName' | Modulo non importato | Aggiungilo agli import in tasks.py |
| Dimensione dei canali non corrispondente | Specifiche args errate | Verifica la compatibilità dei canali di input e output |
AttributeError: 'int' object has no attribute | Tipo di argomento errato | Consulta la documentazione del modulo per verificare i tipi di argomento corretti |
| Impossibile creare il modello | Riferimento from non valido | Assicurati che i livelli a cui fai riferimento esistano |
Consigli per il debug#
Quando sviluppi architetture personalizzate, un debug sistematico aiuta a individuare tempestivamente i problemi:
Usa una head Identity per i test
Sostituisci le head complesse con nn.Identity per isolare i problemi del backbone:
nc: 1
backbone:
- [-1, 1, CustomBlock, [64]]
head:
- [-1, 1, nn.Identity, []] # Pass-through for debuggingIn questo modo puoi esaminare direttamente gli output del 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 dimensionsIspezione dell'architettura del modello
Controllare il conteggio FLOPs e stampare ogni livello può aiutarti a individuare problemi nella configurazione personalizzata del modello. Il conteggio FLOPs deve essere diverso da zero perché il modello sia valido. Se è zero, probabilmente c'è un problema nel forward pass. Eseguendo un semplice forward pass dovrebbe essere visualizzato l'errore esatto che si verifica.
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}")Convalida passo dopo passo
- Inizia con il minimo indispensabile: esegui prima i test con l'architettura più semplice possibile
- Aggiungi elementi gradualmente: aumenta la complessità livello per livello
- Controlla le dimensioni: verifica la compatibilità dei canali e delle dimensioni spaziali
- Convalida la scalabilità: esegui test con scale del modello diverse (
n,s,m)
Domande frequenti#
Imposta il parametro
ncall'inizio del file YAML in modo che corrisponda al numero di classi del tuo dataset.nc: 5 # 5 classesSì. Puoi usare qualsiasi modulo supportato, inclusi i backbone TorchVision, oppure definire un modulo personalizzato e importarlo come descritto in Integrazione di moduli personalizzati.
Usa la sezione
scalesnel file YAML per definire i fattori di scala di profondità, larghezza e numero massimo di canali. Il modello li applicherà automaticamente quando carichi il file YAML di base con la scala aggiunta al nome del file (ad es.yolo26n.yaml).Questo formato specifica come viene costruito ciascun livello:
from: sorgente/i di inputrepeats: numero di ripetizioni del modulomodule: tipo di livelloargs: argomenti del modulo
Verifica che i canali di output di un livello corrispondano ai canali di input previsti per il livello successivo. Usa
print(model.model.model)per esaminare l'architettura del tuo modello.Consulta il codice sorgente nella directory
ultralytics/nn/modulesper trovare tutti i moduli disponibili e i relativi argomenti.Definisci il modulo nel codice sorgente, importalo come mostrato in Modifica del codice sorgente e richiamalo per nome nel file YAML.
Sì, puoi usare
model.load("path/to/weights")per caricare i pesi da un checkpoint preaddestrato. Tuttavia, verranno caricati correttamente solo i pesi dei livelli corrispondenti.Usa
model.info()per verificare che il conteggio FLOPs sia diverso da zero. Un modello valido deve avere un conteggio FLOPs diverso da zero. Se è zero, segui i suggerimenti in Consigli per il debug per individuare il problema.