In questo esperimento addestro un Transformer decoder-only da ~20M di parametri su ImageNet-1K trattando la classificazione come task generativo: dato un input immagine, il modello produce il nome della classe come testo.
In sintesi
- Task: generare la categoria (tra 1.000) a partire dall’immagine.
- Architettura: 22 layer, hidden size 256, bottleneck alternati; tokenizer byte-level (256 token).
- Dataset: visual-layer/imagenet-1k-vl-enriched.
- Training: ~20 ore su NVIDIA RTX A4000, senza data augmentation online.
- Risultato: training loss ≈ 0,03, comportamento dei gradienti stabile dopo il warmup.
- Next: provare Kimi Delta Attention (KDA) per ridurre memoria e studiare la capacità di modellazione.
Perché usare un GPT per ImageNet-1K?
La classificazione su IN1K è tradizionalmente formulata come softmax su 1.000 classi. Qui la riformulo come generazione di testo: il modello produce una stringa breve (es. “zebra”, “labrador”, “penna”), il che riduce la finestra contestuale necessaria e porta benefici in termini di memoria e semplicità del target linguistico.
Questa impostazione consente di:
- sfruttare le capacità autoregressive dei decoder-only;
- riutilizzare pipeline NLP (tokenizzazione, log-prob, sampling);
- studiare la robustezza del modello quando la label è una sequenza di byte e non un indice.
Dataset e formattazione del target
- Dataset: ImageNet-1K VL Enriched su Hugging Face.
- Target: la classe testuale è tokenizzata a livello di byte. Le stringhe sono corte, perciò la lunghezza delle sequenze è contenuta (tipicamente decine di token).
Architettura: profonda e “stretta”, con strozzature
Scelte principali
- 22 layer Transformer decoder-only
- Hidden size = 256 (circa 20M di parametri totali)
- Tokenizer byte-level (256 token) → embedding matrix piccola → memoria più bassa
Perché tanta profondità?
Punto su reti più profonde ma più strette per rientrare nel budget di parametri. L’ipotesi è che una maggiore composizione di funzioni (più layer) migliori l’espressività a parità di parametri.
Bottleneck alternati (strozzature)
A partire da circa un terzo della profondità, inserisco strozzature: la dimensione dei blocchi viene alternata tra quella originale e una ridotta, con proiezioni lineari aggiuntive per comprimere/decomprimere.
Obiettivi:
- indurre una compressione informativa che possa favorire la generalizzazione;
- ottenere leggera efficienza parametrica senza rinunciare alla profondità.
Tokenizzazione a livello di byte: pro e contro
- Pro: vocabolario di 256 token, embedding piccoli, semplicità di gestione di qualunque stringa di label.
- Contro: sequenze più lunghe (ogni carattere = 1 token), ma in questo task l’output resta breve, quindi l’impatto è minimo.
Setup di training
- Hardware: 1× NVIDIA RTX A4000
- Durata: ~20 ore
- Augmentation: nessuna data augmentation online
- Stabilità: gradient clipping attivo
Osservazioni sui gradienti
Nelle prime fasi ho visto picchi della norma del gradiente (fino a ~20) che si stabilizzano verso/alla fine della fase di warmup. Sui modelli piccoli e profondi conviene monitorare attentamente: se il clipping resta costantemente saturo, potrebbe indicare inizializzazioni/lr sub-ottimali.
Risultati
- Training loss ≈ 0,03 senza augmentation online.
- Il modello mostra una buona capacità di modellare il task generativo di ImageNet-1K nonostante il budget ridotto (20M parametri).
- Valuterò prossimamente metriche standard (es. top-1/top-5) calcolando l’esatto match tra sequenza generata e label canonica, incluse normalizzazioni (case, spazi, sinonimi).
Nota: rispetto alla softmax a 1.000 classi, la valutazione richiede attenzione alla normalizzazione del testo per evitare falsi negativi (es. “labrador retriever” vs “labrador”).
Modello e codice
- Modello su Hugging Face: mascIT/gradientlab-exp20251025_0_vlm_20m_in1k
- Codice su GitHub: gradientlab – esperimento exp20251025_0_vlm_20m_in1k
Lo script dell’esperimento e le configurazioni si trovano nella cartella indicata. Seguiranno istruzioni d’uso più dettagliate e uno script di valutazione.
Direzioni future: Kimi Delta Attention (KDA)
Nel prossimo step proverò Kimi Delta Attention (KDA), una variante di attenzione lineare pensata per ridurre la complessità/memoria.
Su questo task l’output è molto corto (≈ 10–100 token), quindi l’impatto sui costi potrebbe essere limitato; sono però interessato a misurarne la capacità di modellazione rispetto all’attenzione classica, anche in vista di input più lunghi.
FAQ
Perché non usare direttamente una softmax su 1.000 classi?
Volevo studiare il framing generativo: porta vantaggi di flessibilità, consente label testuali (anche multi-token) e sfrutta tooling NLP esistente.
Un tokenizer byte-level non allunga troppo le sequenze?
Sì, ma qui le label sono brevi, quindi il costo aggiuntivo è trascurabile. In cambio si ottiene semplicità e vocabolario minimo.
Perché puntare sulla profondità con hidden piccoli?
Per testare l’ipotesi che la profondità (composizionalità) compensi un width ridotto a parità di parametri, con possibili benefici di generalizzazione.
Riepilogo “architettura in numeri”
| Caratteristica | Valore |
|---|---|
| Tipo | Transformer decoder-only |
| Parametri | ~20M |
| Layer | 22 |
| Hidden size | 256 |
| Tokenizer | byte-level (256 token) |
| Bottleneck | alternati da ~1/3 della profondità |
| Hardware | 1× NVIDIA RTX A4000 |
| Tempo training | ~20h |
| Loss (train) | ≈ 0,03 |