Configurazione YAML del modello
Il file di configurazione YAML del modello è il progetto architettonico delle reti neurali di Ultralytics . Definisce il modo in cui gli strati si collegano, i parametri utilizzati da ciascun modulo e il modo in cui l'intera rete si adatta alle diverse dimensioni del modello.
Struttura di configurazione
I file YAML del modello sono organizzati in tre sezioni principali che lavorano insieme per definire l'architettura.
Sezione Parametri
La sezione dei parametri specifica le caratteristiche globali del modello e il suo comportamento in scala:
# 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 only
nc
imposta il numero di classi previste dal modello.scales
definire fattori di scala composti che regolano la profondità, la larghezza e i canali massimi del modello per produrre diverse varianti di dimensioni (da nano a extra-large).kpt_shape
si applica ai modelli di posa. Può essere[N, 2]
per(x, y)
punti chiave o[N, 3]
per(x, y, visibility)
.
Ridurre la ridondanza con scales
Il scales
consente di generare più dimensioni di modelli da un singolo YAML di base. Per esempio, quando si carica yolo11n.yaml
Ultralytics legge la base yolo11.yaml
e applica il n
fattori di scala (depth=0.50
, width=0.25
) per costruire la variante nano.
nc
e kpt_shape
sono dipendenti dal set di dati
Se il set di dati specifica un diverso nc
oppure kpt_shape
Ultralytics sovrascriverà automaticamente la configurazione del modello in fase di esecuzione, in modo che corrisponda allo YAML del dataset.
Architettura backbone e head
L'architettura del modello è composta da sezioni backbone (estrazione delle caratteristiche) e head (attività specifiche):
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]] # 6: Upsample
- [[-1, 2], 1, Concat, [1]] # 7: Skip connection
- [-1, 3, C2f, [256]] # 8: Process features
- [[8], 1, Detect, [nc]] # 9: Detection layer
Formato delle specifiche di livello
Ogni strato segue lo stesso schema: [from, repeats, module, args]
Componente | Scopo | Esempi |
---|---|---|
da | Connessioni di ingresso | -1 (precedente), 6 (strato 6), [4, 6, 8] (multi ingresso) |
ripete | Numero di ripetizioni | 1 (singolo), 3 (ripetere 3 volte) |
modulo | Tipo di modulo | Conv , C2f , TorchVision , Detect |
argomenti | Argomenti del modulo | [64, 3, 2] (canali, kernel, stride) |
Modelli di connessione
Il from
crea modelli di flusso di dati flessibili in tutta la rete:
- [-1, 1, Conv, [64, 3, 2]] # Takes input from previous layer
- [[-1, 6], 1, Concat, [1]] # Combines current layer with layer 6
- [[4, 6, 8], 1, Detect, [nc]] # Detection head using 3 feature scales
Indicizzazione dei livelli
I livelli sono indicizzati a partire da 0. Gli indici negativi si riferiscono ai livelli precedenti (-1
= strato precedente), mentre gli indici positivi si riferiscono a strati specifici in base alla loro posizione.
Ripetizione del modulo
Il 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 layer
Il conteggio effettivo delle ripetizioni viene moltiplicato per il fattore di scala della profondità dalla configurazione delle dimensioni del modello.
Moduli disponibili
I moduli sono organizzati per funzionalità e definiti nella directoryUltralytics modules. Le tabelle seguenti mostrano i moduli comunemente utilizzati per categoria, mentre molti altri sono disponibili nel codice sorgente:
Operazioni di base
Modulo | Scopo | Sorgente | Argomenti |
---|---|---|---|
Conv |
Convoluzione + BatchNorm + Attivazione | conv.py | [out_ch, kernel, stride, pad, groups] |
nn.Upsample |
Sovracampionamento spaziale | PyTorch | [size, scale_factor, mode] |
nn.Identity |
Funzionamento passante | PyTorch | [] |
Blocchi compositi
Modulo | Scopo | Sorgente | Argomenti |
---|---|---|---|
C2f |
Collo di bottiglia CSP con 2 convoluzioni | blocco.py | [out_ch, shortcut, expansion] |
SPPF |
Pooling spaziale a piramide (veloce) | blocco.py | [out_ch, kernel_size] |
Concat |
Concatenazione a livello di canale | conv.py | [dimension] |
Moduli specializzati
Modulo | Scopo | Sorgente | Argomenti |
---|---|---|---|
TorchVision |
Caricare qualsiasi modello torchvision | blocco.py | [out_ch, model_name, weights, unwrap, truncate, split] |
Index |
Estrarre un tensor specifico dall'elenco | blocco.py | [out_ch, index] |
Detect |
Testa di rilevamento YOLO | head.py | [nc, anchors, ch] |
Elenco completo dei moduli
Questo rappresenta un sottoinsieme dei moduli disponibili. Per l'elenco completo dei moduli e dei loro parametri, esplorare la directory modules.
Caratteristiche avanzate
Integrazione di TorchVision
Il modulo TorchVision consente la perfetta integrazione di qualsiasi modello TorchVision come backbone:
from ultralytics import YOLO
# Model with ConvNeXt backbone
model = YOLO("convnext_backbone.yaml")
results = model.train(data="coco8.yaml", epochs=100)
backbone:
- [-1, 1, TorchVision, [768, convnext_tiny, DEFAULT, True, 2, False]]
head:
- [-1, 1, Classify, [nc]]
Ripartizione dei parametri:
768
: Canali di uscita previsticonvnext_tiny
: Architettura del modello (modelli disponibili)DEFAULT
: Utilizzare i pesi preaddestratiTrue
: Rimuovere la testa di classificazione2
: Tronca gli ultimi 2 stratiFalse
: Restituisce un singolo tensor (non un elenco)
Caratteristiche multiscala
Impostare l'ultimo parametro su True
per ottenere mappe di caratteristiche intermedie per il rilevamento multiscala.
Modulo indice per la selezione delle caratteristiche
Quando si utilizzano modelli che producono più mappe di caratteristiche, il modulo Indice seleziona gli output specifici:
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 detection
Sistema di risoluzione dei moduli
Capire come Ultralytics individua e importa i moduli è fondamentale per la personalizzazione:
Processo di ricerca del modulo
Ultralytics utilizza un sistema a tre livelli in parse_model
:
# Core resolution logic
m = getattr(torch.nn, m[3:]) if "nn." in m else getattr(torchvision.ops, m[4:]) if "ops." in m else globals()[m]
- Moduli PyTorch: Nomi che iniziano con
'nn.'
→torch.nn
spazio dei nomi - Operazioni TorchVision: Nomi che iniziano con
'ops.'
→torchvision.ops
spazio dei nomi - ModuliUltralytics : Tutti gli altri nomi → spazio dei nomi globale tramite importazioni
Catena di importazione dei moduli
I moduli standard diventano disponibili attraverso le importazioni in tasks.py
:
from ultralytics.nn.modules import ( # noqa: F401, E501
SPPF,
C2f,
Conv,
Detect,
# ... many more modules
Index,
TorchVision,
)
Integrazione di moduli personalizzati
Modifica del codice sorgente
La modifica del codice sorgente è il modo più versatile per integrare i moduli personalizzati, ma può essere complicata. Per definire e utilizzare un modulo personalizzato, seguite questi passaggi:
-
Definire il modulo in
ultralytics/nn/modules/block.py
:class CustomBlock(nn.Module): def __init__(self, c1, c2): super().__init__() self.layers = nn.Sequential(nn.Conv2d(c1, c2, 3, 1, 1), nn.BatchNorm2d(c2), nn.ReLU()) def forward(self, x): return self.layers(x)
-
Esporre il proprio 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 alle importazioni in
ultralytics/nn/tasks.py
:from ultralytics.nn.modules import CustomBlock # noqa
-
Gestire argomenti speciali (se necessario) all'interno
parse_model()
inultralytics/nn/tasks.py
:elif m is CustomBlock: c1, c2 = ch[f], args[0] # input channels, output channels args = [c1, c2, *args[1:]]
-
Utilizzare il modulo nel modello YAML:
# custom_model.yaml nc: 1 backbone: - [-1, 1, CustomBlock, [64]] head: - [-1, 1, Classify, [nc]]
-
Controllare i FLOP per verificare che il passaggio in avanti funzioni:
from ultralytics import YOLO model = YOLO("custom_model.yaml", task="classify") model.info() # should print non-zero FLOPs if working
Configurazioni di esempio
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]] # 7
Modello di 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 detection
Modello 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]]
- [-1, 1, nn.AdaptiveAvgPool2d, [1]]
head:
- [-1, 1, Classify, [nc]]
Migliori pratiche
Suggerimenti per il design dell'architettura
Iniziare in modo semplice: Iniziare con architetture collaudate prima di personalizzare. Utilizzate le configurazioni YOLO esistenti come modelli e modificatele in modo incrementale piuttosto che costruirle da zero.
Eseguire i test in modo incrementale: Convalidare ogni modifica passo dopo passo. Aggiungete un modulo personalizzato alla volta e verificate che funzioni prima di procedere alla modifica successiva.
Canali di monitoraggio: Assicurarsi che le dimensioni dei canali corrispondano tra i livelli collegati. I canali di uscita (c2
) di uno strato deve corrispondere ai canali di ingresso (c1
) dello strato successivo nella sequenza.
Utilizzare le connessioni a salto: Sfruttare il riutilizzo delle funzionalità con [[-1, N], 1, Concat, [1]]
modelli. Queste connessioni aiutano a gestire il flusso dei gradienti e consentono al modello di combinare caratteristiche provenienti da scale diverse.
Scala appropriata: Scegliere le scale del modello in base ai vincoli computazionali. Usare nano (n
) per i dispositivi edge, piccoli (s
) per prestazioni equilibrate, e scale più grandi (m
, l
, x
) per ottenere la massima precisione.
Considerazioni sulle prestazioni
Profondità vs. larghezza: le reti profonde catturano caratteristiche gerarchiche complesse attraverso più livelli di trasformazione, mentre le reti larghe elaborano più informazioni in parallelo a ogni livello. Bilanciate questi aspetti in base alla complessità del vostro compito.
Saltare le connessioni: Migliorano il flusso del gradiente durante l'addestramento e consentono il riutilizzo delle caratteristiche in tutta la rete. Sono particolarmente importanti nelle architetture più profonde per evitare che i gradienti svaniscano.
Blocchi a collo di bottiglia: Ridurre il costo computazionale mantenendo l'espressività del modello. Moduli come C2f
utilizzano un numero inferiore di parametri rispetto alle convoluzioni standard, pur mantenendo la capacità di apprendimento delle caratteristiche.
Caratteristiche multiscala: Essenziale per rilevare oggetti di dimensioni diverse nella stessa immagine. Utilizzare modelli di Feature Pyramid Network (FPN) con più teste di rilevamento a scale diverse.
Risoluzione dei problemi
Problemi comuni
Problema | Causa | Soluzione |
---|---|---|
KeyError: 'ModuleName' |
Modulo non importato | Aggiungi a tasks.py importazioni |
Disadattamento delle dimensioni del canale | Non corretto args specifiche |
Verificare la compatibilità dei canali di ingresso/uscita |
AttributeError: 'int' object has no attribute |
Tipo di argomento sbagliato | Controllare la documentazione del modulo per verificare i tipi di argomenti corretti |
Il modello non riesce a costruire | Non valido from riferimento |
Assicurarsi che i livelli di riferimento esistano |
Suggerimenti per il debug
Quando si sviluppano architetture personalizzate, il debug sistematico aiuta a identificare tempestivamente i problemi:
Utilizzare Identity Head per i test
Sostituire le teste complesse con nn.Identity
per isolare i problemi della spina dorsale:
nc: 1
backbone:
- [-1, 1, CustomBlock, [64]]
head:
- [-1, 1, nn.Identity, []] # Pass-through for debugging
Ciò consente di ispezionare direttamente le uscite della dorsale:
import torch
from ultralytics import YOLO
model = YOLO("debug_model.yaml")
output = model.model(torch.randn(1, 3, 640, 640))
print(f"Output shape: {output.shape}") # Should match expected dimensions
Ispezione dell'architettura del modello
Il controllo del conteggio delle FLOPs e la stampa di ogni livello possono aiutare a individuare i problemi con la configurazione del modello personalizzato. Il conteggio dei FLOP dovrebbe essere diverso da zero per un modello valido. Se è zero, è probabile che ci sia un problema con il forward pass. L'esecuzione di un semplice passaggio in avanti dovrebbe mostrare l'errore esatto riscontrato.
from ultralytics import YOLO
# Build model with verbose output to see layer details
model = YOLO("debug_model.yaml", 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
- Iniziare in modo minimale: Testare prima con l'architettura più semplice possibile
- Aggiungere in modo incrementale: Costruire la complessità strato per strato
- Controllare le dimensioni: Verificare la compatibilità del canale e delle dimensioni spaziali
- Convalidare il ridimensionamento: Test con diverse scale di modelli (
n
,s
,m
)
FAQ
Come posso modificare il numero di classi nel mio modello?
Impostare il nc
all'inizio del file YAML, in modo che corrisponda al numero di classi del dataset.
nc: 5 # 5 classes
Posso usare un backbone personalizzato nel mio modello YAML?
Sì. È possibile utilizzare qualsiasi modulo supportato, comprese le dorsali di TorchVision, oppure definire un proprio modulo personalizzato e importarlo come descritto in Integrazione di moduli personalizzati.
Come faccio a scalare il mio modello per dimensioni diverse (nano, piccolo, medio, ecc.)?
Utilizzare il scales
sezione nel file YAML per definire i fattori di scala per la profondità, la larghezza e i canali massimi. Il modello li applicherà automaticamente quando si caricherà il file YAML di base con la scala aggiunta al nome del file (ad esempio, yolo11n.yaml
).
Che cosa fa il [from, repeats, module, args]
formato significa?
Questo formato specifica come viene costruito ogni strato:
from
: sorgente/i di ingressorepeats
Numero di volte in cui ripetere il modulomodule
: il tipo di stratoargs
: argomenti per il modulo
Come si risolvono gli errori di mancata corrispondenza dei canali?
Verificare che i canali di uscita di un livello corrispondano ai canali di ingresso previsti per il livello successivo. Utilizzare print(model.model.model)
per ispezionare l'architettura del modello.
Dove posso trovare un elenco dei moduli disponibili e dei loro argomenti?
Controllare il codice sorgente nella sezione ultralytics/nn/modules
directory per tutti i moduli disponibili e i loro argomenti.
Come si aggiunge un modulo personalizzato alla configurazione YAML?
Definire il modulo nel codice sorgente, importarlo come mostrato in Modifica del codice sorgente e riferirlo per nome nel file YAML.
È possibile utilizzare i pesi preaddestrati con uno YAML personalizzato?
Sì, è possibile utilizzare model.load("path/to/weights")
per caricare i pesi da un checkpoint preaddestrato. Tuttavia, solo i pesi dei livelli corrispondenti vengono caricati correttamente.
Come si convalida la configurazione del modello?
Usa model.info()
per verificare se il conteggio dei FLOP è diverso da zero. Un modello valido dovrebbe mostrare un conteggio di FLOPs non nullo. Se è zero, seguire i suggerimenti in Suggerimenti per il debug per trovare il problema.