Self-Attention
L'autoattenzione consente a ogni token di una sequenza di attribuire un peso a tutti gli altri token, usando query, key e value ricavati dallo stesso input. È il nucleo dei Transformer.
L'autoattenzione è una forma di attenzione in cui query, chiavi e valori provengono tutti dalla stessa sequenza; così ogni token costruisce una nuova rappresentazione a partire da tutti gli altri token della sequenza. Un singolo livello di autoattenzione può collegare in un solo passaggio la prima e l'ultima parola di un paragrafo, o gli angoli opposti di un'immagine, mentre una rete neurale ricorrente (RNN) richiede un passaggio per posizione e una rete neurale convoluzionale (CNN) ha bisogno di molti livelli sovrapposti per ampliare il proprio campo visivo. Associata a livelli feed-forward, forma il Transformer introdotto nel documento del 2017 Attention Is All You Need, alla base dei modelli linguistici di grandi dimensioni (LLM), dei Vision Transformer (ViT) e dei rilevatori basati su Transformer.
Come funziona la self-attention#
Ogni token di input, rappresentato come embedding, viene moltiplicato per tre matrici apprese per ottenere una query, una chiave e un valore. L'output per il token i è una media ponderata del vettore valore di ciascun token; i pesi sono dati da una softmax dei prodotti scalari scalati tra la query del token i e tutte le chiavi: è l'attenzione a prodotto scalare scalato descritta nella pagina dedicata al meccanismo di attenzione. Poiché query, chiavi e valori sono proiezioni degli stessi token, una sequenza di n token produce una matrice dei pesi n × n. Nella frase «L'animale non ha attraversato la strada perché era troppo stanco», la riga relativa a «era» può assegnare la maggior parte del peso ad «animale» e incorporare il significato di quella parola nella propria rappresentazione.
L'autoattenzione multi-testa esegue in parallelo più di questi calcoli su proiezioni più piccole e concatena i risultati; così teste diverse possono cogliere relazioni diverse, come la sintassi in una testa e la coreferenza in un'altra. Il Transformer originale usava 8 teste da 64 dimensioni ciascuna in un modello a 512 dimensioni.
Cecità all'ordine e mascheramento causale#
L'autoattenzione tratta il proprio input come un insieme. Rimescolare i token rimescola gli output nello stesso modo e non cambia nient'altro, quindi i modelli aggiungono informazioni posizionali, come gli embedding sinusoidali del Transformer originale o l'embedding posizionale rotatorio (RoPE) presente nella maggior parte degli LLMs attuali. Gli encoder come BERT consentono a ogni token di prestare attenzione in entrambe le direzioni. Gli LLMs con solo decoder applicano una maschera causale, così ogni token presta attenzione solo a sé stesso e ai token precedenti; questo consente al modello di generare testo da sinistra a destra e di riutilizzare le chiavi e i valori dei token precedenti memorizzati in una cache KV. MultiheadAttention di PyTorch mostra entrambe le proprietà quando lo stesso tensore viene passato come query, chiave e valore:
import torch
torch.manual_seed(0)
tokens = torch.randn(1, 5, 16) # una sequenza di 5 token con 16 caratteristiche ciascuno
attn = torch.nn.MultiheadAttention(embed_dim=16, num_heads=2, batch_first=True)
# Autoattenzione: query, chiavi e valori sono tutti proiezioni degli stessi token
out, weights = attn(tokens, tokens, tokens)
print("Attention weights shape:", tuple(weights.shape))
# Riordinare i token riordina soltanto gli output, quindi senza informazioni posizionali l'ordine delle parole è invisibile
perm = torch.tensor([3, 0, 4, 1, 2])
out_shuffled, _ = attn(tokens[:, perm], tokens[:, perm], tokens[:, perm])
print("Same outputs after shuffling:", torch.allclose(out_shuffled, out[:, perm], atol=1e-6))
# Una maschera causale blocca l'attenzione ai token successivi, come in un LLM con solo decoder
mask = torch.triu(torch.ones(5, 5, dtype=torch.bool), diagonal=1)
_, causal_weights = attn(tokens, tokens, tokens, attn_mask=mask)
print(causal_weights[0].detach().round(decimals=2))Stampa una forma dei pesi (1, 5, 5), True per il test di riordino e una matrice triangolare inferiore: il primo token assegna un peso di 1.00 a sé stesso, il secondo ripartisce il peso tra i primi due token con valori di 0.31 e 0.69, e ogni elemento sopra la diagonale è 0.00.
Autoattenzione e termini correlati#
- Meccanismo di attenzione: l'operazione generale che pondera i valori in base alla somiglianza tra query e chiavi. L'autoattenzione è il caso in cui tutti e tre provengono da un'unica sequenza.
- Attenzione incrociata: le query provengono da una sequenza, mentre chiavi e valori ne provengono da un'altra. Un decoder di traduzione presta attenzione alla frase sorgente codificata, le query degli oggetti di un decoder DETR prestano attenzione alle caratteristiche dell'immagine e un modello di diffusione da testo a immagine presta attenzione al prompt.
- Convoluzione: applica lo stesso piccolo filtro in ogni posizione, quindi ogni output vede una finestra locale fissa con pesi indipendenti dal contenuto. L'autoattenzione calcola i pesi in base al contenuto e copre l'intero input.
Il Transformer originale encoder-decoder combina autoattenzione bidirezionale, autoattenzione causale e attenzione incrociata:
Costo e varianti efficienti#
Calcolare il punteggio di ogni coppia di token fa crescere tempo e memoria in proporzione al quadrato della lunghezza della sequenza: 1.000 token producono un milione di punteggi per testa e 100.000 token ne producono dieci miliardi. FlashAttention calcola l'autoattenzione esatta in blocchi senza memorizzare l'intera matrice; la grouped-query attention (GQA) condivide chiavi e valori tra le teste per ridurre la cache KV, mentre l'attenzione a finestra scorrevole, sparsa e lineare riduce il numero di coppie. Nella visione, il numero di token dipende dalla risoluzione dell'immagine, quindi molti rilevatori applicano l'autoattenzione solo dove le mappe delle caratteristiche sono più piccole. YOLO26 esegue l'autoattenzione multi-testa solo nel blocco C2PSA alla fine del suo backbone e in un blocco C3k2 con attenzione nel neck; entrambi operano sulla mappa delle caratteristiche 20×20 con stride 32 di un'immagine da 640 pixel, ovvero 400 token. Il modulo di attenzione calcola query, chiavi e valori con una convoluzione 1×1 su quella mappa e aggiunge informazioni posizionali tramite una convoluzione depthwise 3×3 applicata ai valori.










