Congelamento dei layer

Il congelamento tiene fissi i pesi selezionati mentre il resto del modello si addestra. I selettori fanno riferimento ai gruppi di congelamento ordinati propri di una famiglia o ai suoi nomi di modulo, non a numeri di layer grezzi presi da un grafo YAML.

Congela qualcosa

freeze è opzionale e di default non congela nulla.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # I primi 10 gruppi sono l'intero backbone di YOLOv9.model.train(data="my-dataset.yaml", epochs=50, freeze=10)
CLI
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \  epochs=50 freeze=10
Per nome
from libreyolo import LibreYOLO model = LibreYOLO("LibreRFDETRs.pt")model.train(data="my-dataset.yaml", epochs=50, freeze="backbone")
Più selettori
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")model.train(data="my-dataset.yaml", freeze=["backbone", "neck"])

Il congelamento avviene dopo la costruzione del modello e dopo l'eventuale ricostruzione della testa per un nuovo numero di classi, e prima che venga creato l'ottimizzatore, così l'ottimizzatore riceve sempre e solo parametri addestrabili.

Che cosa può essere un selettore

ValoreSignificato
None, False, "", "none"Addestra ogni parametro
10 o "10"Congela i primi dieci gruppi di congelamento della famiglia
[0, 3, 7]Congela quei gruppi, indicizzati da zero
"backbone"Congela il gruppo, il modulo o il prefisso di parametro corrispondente
["backbone", "neck"]Congela ognuno dei selettori elencati
["backbone", 3]Le liste miste funzionano

Una stringa viene analizzata prima di essere interpretata, quindi la CLI e una configurazione YAML accettano le stesse forme di Python. freeze="[0, 3, 'head']" viene letto come una lista letterale, freeze="backbone,neck" viene diviso sulla virgola, e una semplice stringa decimale diventa un conteggio.

freeze=True viene rifiutato perché ambiguo.

I selettori per nome corrispondono al nome di un gruppo di congelamento, al nome di un modulo o a un prefisso di nome di parametro, e i caratteri glob *, ? e [ funzionano. Un model. iniziale è trattato in modo flessibile, così sia backbone sia model.backbone funzionano, qualunque sia la forma usata internamente dalla famiglia.

I gruppi li definisce la famiglia

Un intero fa riferimento alla lista ordinata di gruppi di congelamento propria della famiglia, non a una posizione in un grafo condiviso. Le famiglie di LibreYOLO non sono tutte un unico modello sequenziale indicizzato da YAML, quindi un numero di layer grezzo significherebbe una cosa diversa su ciascuna di esse.

YOLOv9 ordina i suoi gruppi a partire dall'ingresso: dieci stadi di backbone, poi sei stadi di neck, poi la testa. Per questo freeze=10 è esattamente il backbone. backbone, neck e head sono selettori per nome stabili costruiti sopra di esso.

I gruppi di RF-DETR sono backbone.encoder, backbone.projector, decoder, queries, transformer.encoder_output e head. Qui i nomi sono la scelta migliore, perché i componenti di un transformer non corrispondono a un conteggio di layer. backbone corrisponde per prefisso a entrambi i gruppi del backbone.

Le famiglie che non definiscono gruppi semantici ripiegano su un default conservativo: ogni figlio diretto del modello che possiede almeno un parametro, in ordine di dichiarazione. Di solito è una lista corta, quindi un intero grande non troverà abbastanza gruppi:

freeze index 10 is out of range for 3 available freeze groups.

Per vedere la lista reale invece di tirare a indovinare:

Elencare in ordine i gruppi di congelamento di una famiglia
from libreyolo import LibreYOLO9from libreyolo.models.yolo9.trainer import YOLO9Trainer model = LibreYOLO9("LibreYOLO9s.pt", size="s")trainer = YOLO9Trainer(model=model.model, wrapper_model=model, size="s") for index, (name, _module) in enumerate(trainer.get_freeze_groups()):    print(index, name)

Gli errori si fanno sentire

Ogni modo di sbagliare solleva un errore invece di addestrare qualcosa che non hai chiesto.

Un selettore che non corrisponde a nulla solleva un errore, indicando quali selettori hanno mancato il bersaglio:

freeze selector(s) matched no parameters: 'backbon'

Un congelamento che non lascerebbe nulla di addestrabile solleva un errore, sia al momento del congelamento sia di nuovo quando viene costruito l'ottimizzatore:

freeze would leave no trainable parameters. Use a smaller freeze value or
target a narrower module.

Che è quello che fa freeze="all", dato che all corrisponde a ogni parametro.

Quando il congelamento riesce, una riga registra quello che è successo:

Layer freezing: selectors=[10], tensors=124, params=2103776, trainable=1863456/3967232

Il BatchNorm congelato smette di aggiornarsi

Un parametro congelato sta comunque dentro un modulo le cui statistiche di running continuerebbero a muoversi. Ogni modulo di tipo BatchNorm i cui parametri finiscono nell'insieme congelato viene messo in modalità eval, e il trainer la riapplica dopo la chiamata a model.train() di ogni epoca, così le statistiche restano fisse per tutta l'esecuzione.

È attivo di default ed è ciò che fa sì che congelare un backbone lo congeli davvero.

Combinare con LoRA

freeze e lora=True funzionano insieme. Su RF-DETR, DEIM e ConvNeXt i parametri degli adapter restano addestrabili anche quando il gruppo che li contiene è congelato, che è la combinazione che vuoi: un backbone congelato con gli adapter che imparano sopra di esso. Vedi Fine-tuning con LoRA.

Ambito

Questo è un congelamento statico deciso all'avvio. Lo scongelamento programmato e il congelamento progressivo non fanno parte dell'interfaccia.

Correlati

  • Iperparametri per il resto di train().
  • Distillazione per l'altro modo di trasferire la conoscenza di un modello grande in un addestramento.

Verificato con LibreYOLO v1.5.0.