Ho testato 4 architetture Feed-Forward dei Transformer su un GPT a 2 milioni di parametri - Ecco cosa vince
Introduzione
Quando LLaMA, Mistral e DeepSeek usano tutti SwiGLU nelle loro reti feed-forward, è facile pensare di dover fare lo stesso. Ma conta davvero sulle piccole scale con cui la maggior parte di noi sperimenta? O è solo un trucco per miliardi di parametri?
Volevo saperlo. Così ho condotto un esperimento controllato: ho addestrato un GPT a 2 milioni di parametri da zero 12 volte, cambiando nulla se non l'architettura FFN e la funzione di attivazione. Stessi dati, stesso seed, stesso ottimizzatore. Il risultato è un benchmark pulito e riproducibile che risponde a una domanda molto pratica: cosa dovrei usare nel mio piccolo transformer?
Ecco l'intera configurazione, i numeri e una guida passo-passo per replicare l'esperimento da solo.
1. La pipeline di training (costruita da zero)
Prima di arrivare alle architetture, un rapido sguardo alla pipeline. Tutto è implementato in PyTorch puro - nessun HuggingFace Trainer, nessun PyTorch Lightning. Questo dà controllo completo su ogni dettaglio, fondamentale per un confronto equo.
Passi della pipeline:
Ingestione dei dati: Estrazione del testo da 6 libri PDF (finanza, gestione del rischio, economia) usando PyMuPDF. Pulizia, deduplicazione e combinazione in un singolo corpus.
Tokenizzer: Addestramento di un tokenizzatore BPE da zero con dimensione del vocabolario 4096.
Modello: Un Transformer solo-decoder (MiniGPT) con FFN configurabile - ne parliamo più avanti.
Training: Loop scritto a mano con gradient clipping, loss di validazione e tracciamento della perplessità.
Riproducibilità: Seed casuale fisso (42), cuDNN deterministico, loss iniziale verificata e test di overfit riuscito su un singolo batch.
L'intera pipeline è open source e può essere eseguita con un singolo comando (vedi Sezione 7).
2. Setup sperimentale
| Iperparametro | Valore |
|---|---|
| Dimensione vocabolario | 4096 |
| d_model | 128 |
| Attention heads | 4 |
| Strati | 4 |
| Lunghezza massima sequenza | 64 |
| Dropout | 0.0 (disabilitato) |
| Dim nascosta FFN | 512 (d_model × 4) |
| Parametri totali (std.) | 1.85M |
| Parametri totali (gated) | 2.11M |
| Dati | 750K token (6 libri) |
| Split Train/Val | 90% / 10% |
| Ottimizzatore | AdamW (lr=1e-3) |
| Dimensione batch | 128 |
| Epoche | 5 |
| Seed | 42 |
3. Le quattro architetture FFN
FFN Standard (Transformer originale, BERT, GPT-2)
FFN(x) = Linear2( Activation( Linear1(x) ) )
Due strati lineari, attivazione nel mezzo. Semplice, veloce, ben compreso.
FFN Gated (SwiGLU, ReGLU, GiGLU)
Gate(x) = Activation( Linear_gate(x) )
Up(x) = Linear_up(x)
FFN(x) = Linear_down( Gate(x) * Up(x) )
Tre proiezioni lineari. Il "gate" controlla quali informazioni fluiscono; il percorso "up" fornisce il contenuto. Questo è ciò che usano LLaMA e Mistral.
Le tre varianti differiscono solo nell'attivazione applicata al gate:
- SwiGLU: SiLU (swish)
- ReGLU: ReLU
- GiGLU: GELU
Per ogni architettura, ho testato tutte e tre le attivazioni - sì, anche "ReGLU con GELU" - perché vogliamo vedere se l'attivazione stessa conta indipendentemente dall'idea del gate.
4. Risultati: Training loss dopo 5 epoche
| Tipo FFN | Attivazione | Train Loss (↓) | Parametri |
|---|---|---|---|
| Standard | ReLU | ~0.82* | 1.85M |
| Standard | GELU | 0.78 | 1.85M |
| Standard | SiLU | 0.84 | 1.85M |
| SwiGLU | ReLU | 0.76 | 2.11M |
| SwiGLU | SiLU | 0.74 | 2.11M |
| SwiGLU | GELU | 0.75 | 2.11M |
| ReGLU | SiLU | 0.74 | 2.11M |
| ReGLU | GELU | 0.75 | 2.11M |
| ReGLU | ReLU | 0.76 | 2.11M |
| GiGLU | ReLU | 0.92 | 2.11M |
| GiGLU | GELU | 0.92 | 2.11M |
| GiGLU | SiLU | 0.92 | 2.11M |
Risultati chiave dalla tabella:
- SwiGLU+SiLU vince con una loss di 0.74, corrispondendo alla ricetta LLaMA.
- Standard+GELU è un secondo molto vicino a 0.78 - solo 5% peggiore.
- SiLU è la migliore attivazione per FFN gated, battendo costantemente ReLU e GELU.
- GELU è la migliore per FFN standard (0.78 vs 0.84 per SiLU, 0.82 per ReLU).
- GiGLU fallisce a questa scala - le sue prestazioni rimangono notevolmente indietro rispetto ad altre architetture.
5. Perché il gating aiuta (e perché non sempre)
In un FFN gated, il modello impara quali informazioni mantenere. Pensate così:
- FFN Standard: "Elabora tutto allo stesso modo."
- FFN Gated: "Decidi cosa è importante, poi elabora quello."
Il gate può sopprimere il rumore, amplificare le caratteristiche rilevanti o anche spegnere dimensioni irrilevanti. Questo è potente, ma ha un costo: una terza matrice di pesi, un training leggermente più lento e la necessità di una capacità del modello sufficiente per imparare comportamenti di gate utili.
A 2 milioni di parametri, il guadagno è reale ma modesto (0.04 di loss). A 7 miliardi di parametri, LLaMA e altri mostrano che questo divario si amplia considerevolmente. Quindi per i modelli piccoli, potete tranquillamente restare con Standard+GELU e mantenere le cose semplici.
6. Quindi, quale FFN dovreste usare?
| La vostra situazione | La mia raccomandazione |
|---|---|
| Modello < 1M parametri | Standard + GELU |
| Modello 1M-10M parametri | SwiGLU + SiLU o Standard + GELU (pareggio) |
| Modello > 10M parametri | SwiGLU + SiLU |
| Critico per memoria o velocità | Standard + GELU |
| Riproducere LLaMA/Mistral | SwiGLU + SiLU |
7. Riproducete questo esperimento da soli
Tutto è nel mio repository GitHub: raw-pytorch-minigpt.
Clona e configura
git clone https://github.com/hussainnazary2/raw-pytorch-minigpt.git
cd raw-pytorch-minigpt
bash setup.sh
Esegui un esperimento specifico (es. SwiGLU+SiLU)
git checkout exp-ffn-swiglu-silu
python src/trainer.py
Ogni esperimento ha il suo tag git. Il config.yaml contiene gli iperparametri esatti. Tutte le corsi usano seed 42 - otterrete gli stessi numeri.
Se volete eseguire tutti gli esperimenti e costruire la tabella da soli, controllate la cartella experiments/ per gli script.
8. Cosa succederà dopo
Continuerò ad espandere questo benchmark con:
- Metriche di loss di validazione per tutte le configurazioni
- Dimensioni del modello più grandi (2M, 5M parametri)
- Diversi domini di dati
L'obiettivo è costruire un riferimento pratico e open source per chiunque addestri piccoli transformer da zero.
Avete provato diverse architetture FFN nei vostri modelli? Mi piacerebbe sapere cosa ha funzionato per voi - lasciate un commento o contattatemi.
Questo post fa parte della serie "Building GPT from Scratch". Seguite per altri esperimenti su cosa conta davvero nell'addestramento dei transformer.
Avete bisogno di aiuto per i vostri esperimenti sui transformer? Contattateci per discutere l'ottimizzazione dell'architettura e le strategie di addestramento.