Come effettuare il fine-tuning di YOLO su un dataset personalizzato#
Il fine-tuning adatta un modello pre-addestrato per riconoscere nuove classi partendo da pesi appresi anziché da un'inizializzazione casuale. Invece di addestrare da zero per centinaia di epoche, il fine-tuning sfrutta le caratteristiche pre-addestrate di COCO e converge su dati personalizzati in una frazione del tempo.
Questa guida spiega come effettuare 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 vs Addestramento da zero#
Un modello pre-addestrato 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 tale conoscenza e insegna al modello solo 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 a imparare ogni cosa partendo dai pattern a livello di pixel, il che richiede molte più risorse.
| Fine-Tuning | Addestramento da zero | |
|---|---|---|
| Pesi di partenza | 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 livelli apprendono da zero |
| Requisiti dei dati | Minori - le caratteristiche preaddestrate compensano la scarsità di dati | Maggiori - il modello deve apprendere tutte le caratteristiche solo dal dataset |
| Quando utilizzare | Classi personalizzate con immagini naturali | Domini fondamentalmente diversi da COCO (medico, satellitare, radar) |
Quando viene caricato un file .pt con YOLO("yolo26n.pt"), i pesi pre-addestrati vengono memorizzati nel modello. Chiamare .train(data="custom.yaml") subito dopo trasferisce automaticamente tutti i pesi compatibili alla nuova architettura del modello, reinizializza qualsiasi layer non corrispondente (come la testa di rilevamento quando il numero di classi differisce) e avvia l'addestramento. Non è richiesto alcun caricamento manuale dei pesi, manipolazione dei layer o codice di transfer learning personalizzato.
Come funziona il trasferimento dei pesi preaddestrati#
Quando un modello preaddestrato viene sottoposto a fine-tuning su un dataset con un numero diverso di classi (ad esempio, passando dalle 80 classi di COCO a 5 classi personalizzate), Ultralytics esegue un trasferimento dei pesi consapevole della forma (shape-aware):
- Il backbone e il neck vengono trasferiti completamente - questi livelli estraggono caratteristiche visive generali e le loro forme sono indipendenti dal numero di classi.
- La testa di rilevamento viene parzialmente reinizializzata: i layer di output della classificazione (
cv3,one2one_cv3) hanno forme legate al conteggio delle classi (80 rispetto a 5), quindi non possono essere trasferiti e vengono inizializzati casualmente. I layer di regressione dei box (cv2,one2one_cv2) nella testa hanno forme fisse indipendentemente dal numero di classi, quindi vengono trasferiti normalmente. - La stragrande maggioranza dei pesi viene trasferita quando si cambia il numero di classi. Ad esempio, il fine-tuning di YOLO26n da COCO (80 classi) su un dataset a 5 classi trasferisce 606 tensori di pesi su 708: solo i livelli di classificazione dipendenti dal conteggio delle classi vengono reinizializzati, mentre il backbone, il neck e i rami di regressione dei box rimangono intatti.
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 a 80 classi), il 100% dei pesi viene trasferito, inclusa la detection head.
Trasferisci classi con alias di nome#
Ultralytics trasferisce le righe della classification-head corrispondenti per nome di classe tra i dataset, ignorando le maiuscole/minuscole e gli spazi vuoti circostanti. Quando classi equivalenti usano nomi diversi, rinomina le classi del checkpoint di origine in memoria prima del caricamento. Questo preserva i pesi di classificazione preaddestrati per concetti condivisi che altrimenti verrebbero trattati come non corrispondenti e inizializzati casualmente.
Questo esempio da Objects365 v2 a COCO rinomina le classi di origine sul checkpoint caricato, che train() passa quindi come pesi pre-addestrati:
from ultralytics import YOLO
# Source Objects365 v2 name -> 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")
model.model.names = {i: ALIASES.get(name, name) for i, name in model.model.names.items()}
model.train(data="coco.yaml", epochs=100, imgsz=640)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 della dimensione del modello#
Modelli più grandi offrono maggiore capacità 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 passare a uno più grande solo se le metriche di validazione si stabilizzano è un approccio pratico. La dimensione ottimale del modello dipende dalla complessità del compito, dal numero di classi, dalla diversità del dataset e dall'hardware disponibile per il deployment. Consulta la pagina del modello YOLO26 completa per le dimensioni disponibili e i benchmark delle performance.
Selezione 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 (piccoli dataset o poche epoche): AdamW con un learning rate basso, calcolato automaticamente
- > 10.000 iterazioni (dataset di grandi dimensioni): MuSGD (un ottimizzatore ibrido Muon+SGD) con lr=0.01
Per la maggior parte dei compiti di fine-tuning, l'impostazione predefinita funziona bene senza alcuna regolazione manuale. Considera di impostare l'ottimizzatore esplicitamente quando:
- L'addestramento è instabile (i picchi di loss divergono): prova
optimizer=AdamW, lr0=0.001per una convergenza più stabile - Fine-tuning di un modello grande su un dataset piccolo: un learning rate inferiore come
lr0=0.001aiuta a preservare le caratteristiche pre-addestrate
Quando optimizer=auto, i valori di lr0 e momentum vengono ignorati. Per controllare manualmente il learning rate, imposta l'ottimizzatore in modo esplicito: optimizer=SGD, lr0=0.005.
Blocco dei livelli (Freezing Layers)#
Il congelamento impedisce a specifici layer di aggiornarsi durante l'addestramento. Ciò accelera l'addestramento e riduce l'overfitting quando il dataset è piccolo rispetto alla capacità del modello.
Il parametro freeze accetta un numero intero o una lista. Un numero intero freeze=10 congela i primi 10 layer (indici 0-9), coprendo la maggior parte del backbone di YOLO26. Il backbone si estende dai layer 0 al 10, quindi freeze=10 lascia addestrabile l'ultimo blocco C2PSA (layer 10); usa freeze=11 per congelare l'intero backbone. Una lista può contenere indici di layer come freeze=[0, 3, 5] per il congelamento parziale del backbone, o stringhe con i nomi dei moduli come freeze=["23.cv2", "23.one2one_cv2"] per un controllo granulare su rami specifici all'interno di un layer (in questo caso, entrambi i rami di regressione dei box della testa di rilevamento).
model.train(data="custom.yaml", epochs=50, freeze=10)La profondità di blocco corretta dipende da quanto il dominio di destinazione è simile ai dati di preaddestramento e da quanti dati di addestramento sono disponibili:
| Scenario | Raccomandazione | Logica |
|---|---|---|
| Dataset grande, dominio simile | freeze=None (predefinito) | Dati sufficienti per adattare tutti i livelli senza overfitting |
| Dataset piccolo, dominio simile | freeze=10 | Preserva le caratteristiche del backbone, riduce i parametri addestrabili |
| Dataset molto piccolo | freeze=23 | Solo la detection head viene addestrata, riducendo al minimo il rischio di overfitting |
| Dominio lontano da COCO | freeze=None | Le caratteristiche del backbone potrebbero non trasferirsi bene e necessitare di riaddestramento |
La profondità di blocco può anche essere trattata come un iperparametro - provare alcuni valori (0, 5, 10) e confrontare l'mAP di validazione è un modo pratico per trovare l'impostazione migliore per uno specifico dataset.
Iperparametri chiave per il fine-tuning#
Il fine-tuning generalmente richiede meno regolazioni degli iperparametri rispetto all'addestramento da zero. I parametri più importanti sono:
epochs: Il fine-tuning converge più rapidamente rispetto all'addestramento da zero. Inizia con un valore moderato e usapatienceper interrompere anticipatamente l'esecuzione quando le metriche di validazione si stabilizzano.patience: Il valore predefinito di 100 è progettato per esecuzioni di addestramento lunghe. Ridurlo a 10-20 evita di sprecare tempo su esecuzioni che hanno già converso.warmup_epochs: Il warmup predefinito (3 epoche) aumenta gradualmente il learning rate da zero, il che impedisce a grandi aggiornamenti dei gradienti di danneggiare le caratteristiche pre-addestrate nelle prime iterazioni. Si consiglia di mantenere l'impostazione predefinita anche per il fine-tuning.
Per l'elenco completo dei parametri di addestramento, consulta la guida di riferimento alla configurazione dell'addestramento.
Fine-Tuning a due stadi#
Il fine-tuning a due stadi suddivide l'addestramento in due fasi. Il primo stadio blocca il backbone e addestra solo il neck e la head, permettendo ai livelli di rilevamento di adattarsi alle nuove classi senza disturbare le caratteristiche preaddestrate. Il secondo stadio sblocca tutti i livelli e addestra l'intero modello con un learning rate più basso per rifinire il backbone per il dominio di destinazione.
Questo approccio è particolarmente utile quando il dominio di destinazione differisce significativamente da COCO (immagini mediche, immagini aeree, microscopia), dove il backbone potrebbe necessitare di adattamento ma addestrare tutto in una sola volta 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, lr0=0.001, name="stage2", exist_ok=True)Insidie comuni#
Il modello non produce previsioni#
- Dati di addestramento insufficienti: addestrare con pochissimi campioni è la causa più comune - il modello non può apprendere o generalizzare da troppi pochi dati. Assicurati di avere abbastanza esempi diversi per classe prima di indagare altre cause.
- Controlla i percorsi dei dataset: percorsi non corretti in
data.yamlproducono silenziosamente zero etichette. Eseguiyolo detect val model=yolo26n.pt data=custom.yamlprima dell'addestramento per confermare che le etichette vengano caricate correttamente. - Abbassa la soglia di confidenza: se le predizioni esistono ma vengono filtrate, prova
conf=0.1durante l'inferenza. - Verifica il conteggio delle classi: assicurati che
ncindata.yamlcorrisponda al numero effettivo di classi nei file delle etichette.
L'mAP di validazione si stabilizza precocemente#
- Aggiungi più dati: il fine-tuning beneficia significativamente di dati di addestramento aggiuntivi, specialmente esempi diversi con angolazioni, illuminazione e sfondi vari.
- Controlla il bilanciamento delle classi: le classi sottorappresentate avranno un AP basso. Usa
cls_pwper applicare la ponderazione delle classi basata sulla frequenza inversa (inizia concls_pw=0.25per uno squilibrio moderato, aumenta a1.0per uno squilibrio grave). - Riduci l'augmentations: per dataset molto piccoli, un'augmentation pesante può fare più male che bene. 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 è noto come dimenticanza catastrofica: il modello perde la conoscenza precedentemente appresa quando viene sottoposto a fine-tuning esclusivamente su nuovi dati. La dimenticanza è quasi inevitabile senza includere immagini del dataset originale insieme ai nuovi dati. Per mitigare ciò:
- Unisci i dataset: includi esempi delle classi originali insieme alle nuove classi durante il fine-tuning. Questo è l'unico modo affidabile per prevenire la dimenticanza.
- Blocca backbone e neck: bloccare sia il backbone che il neck in modo che venga addestrata solo la detection head aiuta nelle brevi sessioni di fine-tuning con un learning rate molto basso.
- Addestra per meno epoche: più a lungo il modello viene addestrato esclusivamente sui nuovi dati, più la dimenticanza aumenta.
FAQ#
Non c'è un minimo fisso: i risultati dipendono dalla complessità del compito, dal numero di classi e da quanto il dominio è simile a COCO. Immagini più diverse (illuminazione, angolazioni e sfondi vari) contano più della quantità pura. Inizia con ciò che hai e aumenta la scala se le metriche di validazione non sono sufficienti.
Carica un file
.ptpre-addestrato e chiama.train()con il percorso di undata.yamlpersonalizzato. Ultralytics gestisce automaticamente il trasferimento dei pesi, la reinizializzazione della testa di rilevamento e la selezione dell'ottimizzatore. Consulta la sezione Fine-Tuning di Base per l'esempio di codice completo.Le cause più comuni sono percorsi errati in
data.yaml(che producono silenziosamente zero etichette), una mancata corrispondenza trancnello YAML e i file delle etichette effettivi, o una soglia di confidenza troppo alta. Consulta Problemi Comuni per una checklist completa per la risoluzione dei problemi.Dipende dalla dimensione del dataset e dalla somiglianza del dominio. Per dataset piccoli con un dominio simile a COCO, il congelamento del backbone (
freeze=10) impedisce l'overfitting. Per domini molto diversi da COCO, lasciare tutti i layer non congelati (freeze=None) consente al backbone di adattarsi. Consulta Congelamento dei Layer per raccomandazioni dettagliate.Includi esempi delle classi originali nei dati di addestramento insieme alle nuove classi. Se ciò non è possibile, congelare più layer (
freeze=10o superiore) e utilizzare un learning rate inferiore aiuta a preservare la conoscenza pre-addestrata. Consulta Le prestazioni peggiorano sulle classi originali per maggiori dettagli.