Analisi tecnica del Transformer: autoattenzione come nuova baseline per la trasduzione di sequenze
La trasduzione di sequenze richiede modelli che catturino dipendenze a lungo raggio con elevato parallelismo. Il Transformer introduce un encoder–decoder basato unicamente su autoattenzione e reti feed-forward posizione‑per‑posizione, eliminando sia ricorrenza sia convoluzione, migliorando accuratezza e throughput d’addestramento su benchmark di traduzione neurale.
Challenge
I modelli encoder–decoder dominanti al 2017 alternavano attenzione con ricorrenza (RNN) o convoluzione (CNN), incorrendo in colli di bottiglia fondamentali:
- RNN: sequenzialità intrinseca con O(n) operazioni e lunghezza massima del cammino O(n), che ostacola il flusso del gradiente e il parallelismo.
- CNN: minore profondità sequenziale ma necessità di kernel ampi o dilatazione per il contesto globale, aumentando profondità, cammino minimo e costi computazionali/memoria.
Obiettivo: ottenere un’architettura con operazioni sequenziali minime e lunghezze di cammino O(1) senza sacrificare la capacità di modellazione.
Solution
Il Transformer realizza tutte le interazioni tra token tramite autoattenzione stratificata e strati feed‑forward indipendenti per posizione, con connessioni residuali e layer normalization in ciascun sotto‑blocco.
- Attenzione a prodotto scalare scalato:
\[ \mathrm{Attn}(Q, K, V) = \mathrm{softmax}\!\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V \]
- Attenzione multi‑testa:
\[ \mathrm{head}_i=\mathrm{Attn}\!\left(QW_i^{Q}, KW_i^{K}, VW_i^{V}\right),\quad \mathrm{MultiHead}(Q,K,V)=\mathrm{Concat}(\mathrm{head}_1,\dots,\mathrm{head}_h)W^{O} \]
- Codifica posizionale sinusoidale:
\[ \mathrm{PE}(pos,2i)=\sin\!\left(\frac{pos}{10000^{2i/d_{\mathrm{model}}}}\right),\quad \mathrm{PE}(pos,2i+1)=\cos\!\left(\frac{pos}{10000^{2i/d_{\mathrm{model}}}}\right) \]
- Decoder con mascheramento causale, attenzione incrociata encoder–decoder e stesse FFN posizione‑per‑posizione.
Complessità per strato: self‑attention densa O(n²d) con O(1) operazioni sequenziali; RNN O(nd²) con O(n) operazioni sequenziali. L’attenzione locale di r raggiunge O(n r d) preservando il parallelismo.
Evidence
- Setup: WMT’14 En→De (~4,5M coppie) e En→Fr (~36M), tokenizzazione BPE, beam search con normalizzazione della lunghezza.
- Risultati singolo modello:
- Transformer‑Base (6×6, \(d_{\mathrm{model}}=512\), \(h=8\)): 27,3 BLEU su En→De.
- Transformer‑Big (\(d_{\mathrm{model}}=1024\), \(h=16\)): 28,4 BLEU su En→De, 41,8 BLEU su En→Fr.
- Efficienza:
- Base: ~12 ore a 27,3 BLEU su 8×P100.
- Big: ~3,5 giorni a 41,8 BLEU su 8×P100.
- Pratiche di stabilizzazione: residual, layer norm, scaling per \(\sqrt{d_{\mathrm{model}}}\), dropout su pesi di attenzione e residual, label smoothing, schedule LR con warm‑up e decadimento \(1/\sqrt{t}\).
- Analisi: teste specializzate in dipendenze lunghe e coreferenza; bias induttivo parallelizzabile compatibile con pattern linguistici globali.
Takeaway
- Un encoder–decoder basato esclusivamente su autoattenzione è sufficiente per traduzione neurale SOTA, con cammino O(1) e pieno parallelismo.
- Limite principale: costo quadratico in tempo/memoria rispetto alla lunghezza della sequenza per attenzione densa globale.
- Direzioni: attenzione locale/sparsa/fattorizzata per migliori asintotiche; estensione a contesti lunghi, summarization, QA, dialog e multimodale.
Appendice: Pseudocodice essenziale
# Scaled Dot-Product Attention (PyTorch-like pseudocode)
import math
def scaled_dot_product_attention(Q, K, V, mask=None, dropout=None):
# Q: [B, h, n_q, d_k], K: [B, h, n_k, d_k], V: [B, h, n_k, d_v]
scores = Q @ K.transpose(-2, -1) / math.sqrt(Q.size(-1))
if mask is not None:
scores = scores.masked_fill(mask == 0, float('-inf'))
weights = softmax(scores, dim=-1)
if dropout is not None:
weights = dropout(weights)
return weights @ V # [B, h, n_q, d_v]
# Multi-Head wrapper (shapes omitted for brevity)
def multi_head_attention(x_q, x_kv, Wq, Wk, Wv, Wo, mask=None):
Q = project(x_q, Wq) # split heads
K = project(x_kv, Wk)
V = project(x_kv, Wv)
H = scaled_dot_product_attention(Q, K, V, mask=mask)
H = combine_heads(H)
return H @ Wo