Come eseguire il fine-tuning di YOLO su un dataset personalizzato#
Il fine-tuning adatta un modello preaddestrato al riconoscimento di nuove classi, partendo dai pesi appresi invece che da un'inizializzazione casuale. Anziché addestrare il modello da zero per centinaia di epoche, il fine-tuning sfrutta le caratteristiche preaddestrate di COCO e converge sui dati personalizzati in una frazione del tempo.
Questa guida illustra il fine-tuning di YOLO26 su dataset personalizzati, dall'utilizzo di base a tecniche avanzate come il congelamento dei layer e l'addestramento in due fasi.
Fine-tuning e addestramento da zero#
Un modello preaddestrato ha già appreso caratteristiche visive generali — rilevamento dei bordi, riconoscimento delle texture, comprensione delle forme — da milioni di immagini. Il transfer learning tramite fine-tuning riutilizza questa conoscenza e insegna al modello soltanto l'aspetto delle nuove classi, motivo per cui converge più rapidamente e richiede meno dati. L'addestramento da zero scarta tutto questo e costringe il modello ad apprendere ogni elemento partendo dai pattern a livello di pixel, richiedendo molte più risorse. Consulta la guida alla configurazione YAML dei modelli per scoprire in cosa differiscono i file .yaml contenenti solo l'architettura dai checkpoint.
| Fine-tuning | Addestramento da zero | |
|---|---|---|
| Pesi iniziali | Preaddestrato su COCO (80 classi) | Inizializzazione casuale |
| Comando | YOLO("yolo26n.pt") | YOLO("yolo26n.yaml") |
| Convergenza | Più rapida: il backbone è già addestrato | Più lenta: tutti i layer apprendono da zero |
| Requisiti dei dati | Inferiori: le caratteristiche preaddestrate compensano la minore quantità di dati | Maggiori: il modello deve apprendere tutte le caratteristiche esclusivamente dal dataset |
| Quando usarlo | Classi personalizzate con immagini naturali | Domini fondamentalmente diversi da COCO (medico, satellitare, radar) |
Quando un file .pt viene caricato con YOLO("yolo26n.pt"), i pesi preaddestrati vengono memorizzati nel modello. Chiamando .train(data="custom.yaml") in seguito, tutti i pesi compatibili vengono trasferiti automaticamente alla nuova architettura del modello, i layer non corrispondenti vengono reinizializzati (come la detection head quando il numero di classi è diverso) e l'addestramento ha inizio. Non sono necessari il caricamento manuale dei pesi, la manipolazione dei layer o codice personalizzato per il transfer learning.
Come funziona il trasferimento dei pesi preaddestrati#
Quando un modello preaddestrato viene sottoposto a fine-tuning su un dataset con un numero di classi diverso (ad esempio, dalle 80 classi di COCO a 5 classi personalizzate), Ultralytics esegue un trasferimento dei pesi consapevole delle dimensioni:
- Trasferimento completo di backbone e neck: questi layer estraggono caratteristiche visive generali e le loro forme sono indipendenti dal numero di classi.
- La detection head viene parzialmente reinizializzata: i layer di output della classificazione (
cv3,one2one_cv3) hanno forme legate al numero di classi (80 contro 5). Le righe compatibili i cui nomi delle classi corrispondono vengono rimappate prima di inizializzare quelle non corrispondenti. I layer di regressione dei box (cv2,one2one_cv2) nella head hanno forme fisse indipendentemente dal numero di classi, quindi vengono trasferiti normalmente. - La stragrande maggioranza dei pesi viene trasferita quando cambia il numero di classi. Ad esempio, il fine-tuning di YOLO26n da COCO (80 classi) a un dataset con 5 classi trasferisce 606 tensori di pesi su 708, oltre alle eventuali righe di classificazione compatibili abbinate per nome.
Per i dataset con lo stesso numero di classi del modello preaddestrato (ad esempio, il fine-tuning di pesi preaddestrati su COCO su un altro dataset con 80 classi), viene trasferito il 100% dei pesi, inclusa la detection head.
Trasferimento delle classi con alias dei nomi#
Ultralytics trasferisce le righe corrispondenti della classification head in base al nome della classe tra i dataset, ignorando maiuscole/minuscole e spazi bianchi iniziali e finali. Quando classi equivalenti hanno nomi diversi, rinomina in memoria le classi del checkpoint sorgente prima del caricamento. In questo modo preservi i pesi di classificazione preaddestrati per i concetti condivisi, che altrimenti verrebbero considerati non corrispondenti e inizializzati casualmente.
Questo esempio da Objects365 v2 a COCO rinomina le classi sorgente nel checkpoint caricato, che train() passa quindi come pesi preaddestrati:
from ultralytics import YOLO
# Source Objects365 v2 name (lowercased) -> target COCO name
ALIASES = {
"wild bird": "bird",
"handbag/satchel": "handbag",
"luggage": "suitcase",
"bowl/basin": "bowl",
"orange/tangerine": "orange",
"monitor/tv": "tv",
"stuffed toy": "teddy bear",
"hair dryer": "hair drier",
}
model = YOLO("path/to/yolo26s-objects365.pt")
# Objects365 class names are Title-Cased, so match on the lowercased name
model.model.names = {i: ALIASES.get(name.lower(), name) for i, name in model.model.names.items()}
model.train(data="coco.yaml", epochs=100, imgsz=640)L'impostazione cls_remap abilita per impostazione predefinita questo trasferimento basato sui nomi. Durante l'addestramento viene stampato Remapped N/M cls head rows from pretrained weights by class name quando vengono copiate righe compatibili; imposta cls_remap=False per disabilitarlo.
Esempio di base di fine-tuning#
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # load pretrained model
model.train(data="custom.yaml", epochs=50, imgsz=640)Scelta delle dimensioni del modello#
I modelli più grandi hanno una capacità maggiore, ma anche più parametri da aggiornare, il che può aumentare il rischio di overfitting quando i dati di addestramento sono limitati. Iniziare con un modello più piccolo (YOLO26n o YOLO26s) e aumentare le dimensioni solo se le metriche di validazione raggiungono un plateau è un approccio pratico. Le dimensioni ottimali del modello dipendono dalla complessità del compito, dal numero di classi, dalla diversità del dataset e dall'hardware disponibile per il deployment. Consulta la pagina completa del modello YOLO26 per conoscere le dimensioni disponibili e i benchmark delle prestazioni.
Scelta dell'ottimizzatore e del learning rate#
L'impostazione predefinita optimizer=auto seleziona l'ottimizzatore e il learning rate in base al numero totale di iterazioni di addestramento:
- 10.000 iterazioni o meno (dataset piccoli o poche epoche): AdamW con un learning rate basso calcolato automaticamente
- Più di 10.000 iterazioni (dataset grandi): MuSGD (un ottimizzatore ibrido Muon+SGD) con lr=0.01
Per la maggior parte delle attività di fine-tuning, l'impostazione predefinita funziona bene senza regolazioni manuali. Valuta di impostare esplicitamente l'ottimizzatore quando:
- L'addestramento è instabile (la loss presenta picchi o diverge): prova
optimizer=AdamW, lr0=0.001per una convergenza più stabile - Esegui il fine-tuning di un modello grande su un dataset piccolo: un ottimizzatore esplicito con un learning rate più basso, come
optimizer=AdamW, lr0=0.001, può aiutare a preservare le caratteristiche preaddestrate
Quando optimizer=auto, i valori lr0 e momentum vengono ignorati. Per controllare manualmente il learning rate, imposta esplicitamente l'ottimizzatore: optimizer=SGD, lr0=0.005.
Congelamento dei layer#
Il congelamento impedisce l'aggiornamento di layer specifici durante l'addestramento. Accelera l'addestramento e riduce l'overfitting quando il dataset è piccolo rispetto alla capacità del modello.
Il parametro freeze accetta un intero oppure una lista. Un intero freeze=10 congela i primi 10 layer (indici 0-9), che comprendono la maggior parte del backbone di YOLO26. Il backbone si estende dai layer 0-10, quindi freeze=10 lascia addestrabile il blocco C2PSA finale (layer 10); usa freeze=11 per congelare l'intero backbone. Una lista può contenere indici di layer come freeze=[0, 3, 5] per un congelamento parziale del backbone oppure stringhe con i nomi dei moduli come freeze=["23.cv2", "23.one2one_cv2"] per un controllo dettagliato su rami specifici all'interno di un layer (in questo caso, entrambi i rami di regressione dei box della detection head).
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=50, freeze=10)La profondità di congelamento corretta dipende dalla somiglianza del dominio di destinazione con i dati preaddestrati e dalla quantità di dati di addestramento disponibile:
| Scenario | Raccomandazione | Motivazione |
|---|---|---|
| Dataset grande, dominio simile | freeze=None (predefinito) | Dati sufficienti per adattare tutti i layer senza overfitting |
| Dataset piccolo, dominio simile | freeze=10 | Preserva le caratteristiche del backbone e riduce i parametri addestrabili |
| Dataset molto piccolo | freeze=23 | Si addestra solo la detection head, riducendo al minimo il rischio di overfitting |
| Dominio molto diverso da COCO | freeze=None | Le caratteristiche del backbone potrebbero non trasferirsi bene e richiedere un nuovo addestramento |
La profondità di congelamento può anche essere trattata come un iperparametro: provare alcuni valori (0, 5, 10) e confrontare la mAP di validazione è un metodo pratico per trovare l'impostazione migliore per un dataset specifico.
Iperparametri chiave per il fine-tuning#
In genere il fine-tuning richiede meno regolazioni degli iperparametri rispetto all'addestramento da zero. I parametri più importanti sono:
epochs: il fine-tuning converge più rapidamente dell'addestramento da zero. Inizia con un valore moderato e usapatienceper interrompere anticipatamente l'addestramento quando le metriche di validazione raggiungono un plateau.patience: il valore predefinito di 100 è progettato per esecuzioni di addestramento lunghe. Ridurlo a 10-20 evita di sprecare tempo in esecuzioni già giunte a convergenza.warmup_epochs: il warmup porta gradualmente il learning rate al valore previsto durante le prime epoche, quindi è meno probabile che i batch iniziali disturbino le caratteristiche preaddestrate. Mantienilo diverso da zero durante il fine-tuning, ma non è necessario il valore predefinito completo di 3 epoche: la ricerca evolutiva alla base del fine-tuning ufficiale di YOLO26 su COCO — una continuazione su più epoche a partire dai pesi di Objects365 — si è stabilizzata su circa un'epoca per ogni dimensione del modello.
Per l'elenco completo dei parametri di addestramento, consulta il riferimento alla configurazione dell'addestramento. Per comportamenti non esposti dai parametri — learning rate per layer, gradient clipping o metriche di validazione personalizzate — crea una sottoclasse del trainer.
Fine-tuning in due fasi#
Il fine-tuning in due fasi divide l'addestramento in due fasi. Nella prima fase il backbone viene congelato e vengono addestrati solo neck e head, consentendo ai layer di rilevamento di adattarsi alle nuove classi senza compromettere le caratteristiche preaddestrate. Nella seconda fase tutti i layer vengono scongelati e l'intero modello viene addestrato con un learning rate più basso per perfezionare il backbone in base al dominio di destinazione.
Questo approccio è particolarmente utile quando il dominio di destinazione differisce significativamente da COCO (immagini mediche, immagini aeree, microscopia), poiché il backbone potrebbe richiedere un adattamento, mentre addestrare tutto contemporaneamente causa instabilità. Per lo scongelamento automatico con un approccio basato su callback, consulta Congelamento e scongelamento del backbone.
from ultralytics import YOLO
# Stage 1: freeze backbone, train head and neck
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)
# Stage 2: unfreeze all, fine-tune with lower lr
model = YOLO("runs/detect/stage1/weights/best.pt")
model.train(data="custom.yaml", epochs=30, optimizer="AdamW", lr0=0.001, name="stage2", exist_ok=True)Problemi comuni#
Il modello non produce predizioni#
-
Dati di addestramento insufficienti: l'addestramento con pochissimi campioni è la causa più comune: il modello non può apprendere né generalizzare da una quantità di dati troppo ridotta. Assicurati di avere esempi sufficientemente diversificati per ogni classe prima di analizzare altre cause.
-
Controlla i percorsi del dataset: percorsi di immagini non validi generano un errore del dataset. I singoli file di label mancanti o vuoti vengono trattati come immagini di background e segnalati durante la scansione; una suddivisione di addestramento senza label genera un errore. Convalida il dataset prima dell'addestramento:
yolo detect val model=yolo26n.pt data=custom.yaml -
Riduci la soglia di confidenza: se le predizioni esistono ma vengono filtrate, prova
conf=0.1durante l'inferenza. -
Verifica il numero di classi: assicurati che
ncindata.yamlcorrisponda al numero effettivo di classi nei file di label.
La mAP di validazione raggiunge presto un plateau#
- Aggiungi altri dati: il fine-tuning trae notevoli benefici da dati di addestramento aggiuntivi, soprattutto esempi diversificati con angolazioni, illuminazione e sfondi variabili.
- Controlla il bilanciamento delle classi: le classi sottorappresentate avranno un AP basso. Aggiungi altri esempi o regola
cls_pwsul set di validazione. - Riduci l'augmentation: per dataset molto piccoli, un'augmentation intensa può fare più danni che benefici. Prova
mosaic=0.5omosaic=0.0. - Aumenta la risoluzione: per dataset con oggetti piccoli, prova
imgsz=1280per preservare i dettagli.
Le prestazioni sulle classi originali peggiorano dopo il fine-tuning#
Questo fenomeno è noto come oblio catastrofico: il modello perde le conoscenze apprese in precedenza quando viene sottoposto a fine-tuning esclusivamente su nuovi dati. Senza includere immagini del dataset originale insieme ai nuovi dati, l'oblio è in gran parte inevitabile. Per attenuarlo:
- Unisci i dataset: includi esempi delle classi originali insieme alle nuove classi durante il fine-tuning. Questo è l'unico modo affidabile per prevenire l'oblio.
- Congela backbone e neck: congelare sia il backbone sia il neck, in modo che venga addestrata solo la detection head, è utile per brevi esecuzioni di fine-tuning con un learning rate molto basso.
- Addestra per meno epoche: più a lungo il modello viene addestrato esclusivamente sui nuovi dati, maggiore sarà l'oblio.
FAQ#
Non esiste un minimo fisso: i risultati dipendono dalla complessità del compito, dal numero di classi e dalla somiglianza del dominio con COCO. Le immagini più diversificate (con illuminazione, angolazioni e sfondi variabili) contano più della quantità grezza. Inizia con ciò che hai e aumenta i dati se le metriche di validazione non sono sufficienti.
Carica un file
.ptpreaddestrato e chiama.train()indicando il percorso di undata.yamlpersonalizzato. Ultralytics gestisce automaticamente il trasferimento dei pesi, la reinizializzazione della detection head e la selezione dell'ottimizzatore. Consulta la sezione Fine-tuning di base per l'esempio di codice completo.Le cause più comuni sono percorsi di immagini non validi, file di label mancanti o vuoti, una discrepanza tra
ncnel file YAML e i file di label effettivi oppure una soglia di confidenza troppo alta. Consulta Problemi comuni per una checklist completa per la risoluzione dei problemi.Dipende dalle dimensioni del dataset e dalla somiglianza del dominio. Per dataset piccoli con un dominio simile a COCO, congelare il backbone (
freeze=10) previene l'overfitting. Per domini molto diversi da COCO, lasciare tutti i layer scongelati (freeze=None) consente al backbone di adattarsi. Consulta Congelamento dei layer per raccomandazioni dettagliate.Includi nei dati di addestramento esempi delle classi originali insieme alle nuove classi. Se non è possibile, congelare più layer (
freeze=10o un valore superiore) e usare un learning rate più basso aiuta a preservare la conoscenza preaddestrata. Consulta Le prestazioni sulle classi originali peggiorano per maggiori dettagli.