English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

ospite
1 / ?
torna alle lezioni

Query, Key, Value

Tre Mappe Lineari dallo Stesso Input

Dopo l'embedding (attività 4), ogni posizione porta un vettore x_t a 768 dimensioni. L'Attention inizia producendo tre proiezioni distinte di x:


Q (query): cosa vuole sapere questa posizione?


K (chiave): cosa offre questa posizione ad altre posizioni?


V (valore): quale contenuto fornisce questa posizione se prestata attenzione?


Ogni proiezione proviene da una matrice di pesi appresa:


Q = x · W_Q     # Forma di W_Q: (d_model, d_k)
K = x · W_K     # Forma di W_K: (d_model, d_k)
V = x · W_V     # Forma di W_V: (d_model, d_k)

Tre matrici, tutte addestrate tramite backpropagation. Un modello impara: in questa posizione, quale query recupera al meglio il contesto passato utile? Quale chiave pubblicizza bene il contenuto di questa posizione? Quale valore viene consegnato se selezionato?


Scaled dot-product attention


Un'analogia con la biblioteca

Immagina un catalogo di schede di una biblioteca. Entri con un argomento in mente (la tua query). Ogni scheda elenca parole chiave (una key). Quando il tuo argomento corrisponde alle parole chiave di una scheda, prendi il contenuto del libro (un value). L'attenzione fa questo per ogni token in parallelo: ogni posizione interroga ogni altra posizione, classifica l'allineamento e recupera una combinazione ponderata dei vettori di valore.


Dimensioni ANDREA-120M


QuantitàValoreNote
d_model768Dimensione del vettore in ogni posizione
n_head12Teste di attenzione parallele
d_k64Dimensione per testa (= d_model / n_head)
T1024Lunghezza del contesto

d_k = d_model / n_head = 768 / 12 = 64. Ogni testa vede una fetta di 64 dimensioni di uno spazio completo di 768 dimensioni. L'Attività 6 (grow_a_language_model_multi_head) copre la suddivisione per testa in dettaglio.

Calcola d_k

Calcola d_k per due varianti ANDREA. (a) ANDREA-12M: d_model = 384, n_head = 12. (b) ANDREA-480M: d_model = 1536, n_head = 24. Mostra la tua formula d_k = d_model / n_head per ciascuna.

Perché dividere per sqrt(d_k)

Una matrice di punteggio

Una volta che Q & K esistono (ciascuna forma (T, d_k)), l'attenzione calcola una matrice di punteggio:


scores = Q · K^T     # forma: (T, T)

scores[i, j] = quanto fortemente la query della posizione i si allinea con la key della posizione j. Ogni coppia (i, j) ottiene un punteggio: 1024 × 1024 = 1.048.576 punteggi per testa di attenzione per forward pass.


Perché dividere

I prodotti scalari di due vettori unitari casuali a d dimensioni hanno magnitudine dell'ordine di sqrt(d). Senza scalatura, i punteggi crescono con d_k:


- d_k = 64: prodotti scalari tipici dell'ordine di 8.

- d_k = 256: prodotti scalari tipici dell'ordine di 16.

- d_k = 4096: prodotti scalari tipici dell'ordine di 64.


Punteggi elevati producono una softmax a picco (una posizione domina, i gradienti svaniscono altrove). L'addestramento si blocca. La scalatura corregge una magnitudine:


scaled_scores = (Q · K^T) / sqrt(d_k)

Per ANDREA-120M, sqrt(d_k) = sqrt(64) = 8. Ogni punteggio viene diviso per 8. Le magnitudini rimangono approssimativamente su scala unitaria indipendentemente da d_k. Lo softmax rimane ben comportato. I gradienti fluiscono.


Giustificazione Originale di Vaswani

Da Attention Is All You Need (2017): 'Per grandi valori di d_k, i prodotti scalari crescono in magnitudine, spingendo la funzione softmax in regioni dove ha gradienti estremamente piccoli.' Un divisore sqrt(d_k) contrasta questa crescita.


Una Vista sul Codice

All'interno di microgpt_cuda.cu, questo scaling appare come una divisione letterale:


scores[i][j] = dot(Q[i], K[j]) * (1.0f / sqrtf(d_k));

Una moltiplicazione float per score. Economica. Critica.

Scala a d_model = 4096

Supponi che un team di ricerca costruisca ANDREA-2B con d_model = 4096 & n_head = 32. (a) Calcola d_k. (b) Calcola sqrt(d_k). (c) Spiega in una frase cosa succederebbe se un team dimenticasse di dividere per sqrt(d_k) a questa scala.

Perché la Posizione i Non Può Vedere la Posizione j > i

Un Vincolo Nato dalla Generazione

ANDREA genera un token alla volta. Durante l'inferenza, la posizione 0 produce un primo token, poi la posizione 1 vede l'output della posizione 0 & produce un secondo token, & così via. Un modello non ha mai accesso ai token futuri durante la generazione.


L'addestramento deve rispecchiare questo. Se durante l'addestramento la posizione 5 potesse prestare attenzione alla posizione 6, un modello imparerebbe una scorciatoia: 'prevedere il token 6 leggendo il token 6'. Durante l'inferenza, quella scorciatoia scompare (il token 6 non esiste ancora). Il comportamento addestramento-versus-inferenza di un modello divergerebbe catastroficamente.


Una Maschera

Una maschera causale blocca l'attenzione da qualsiasi posizione i a qualsiasi posizione j > i. Implementazione: imposta scaled_scores[i][j] = -infinito ovunque j > i. Dopo softmax, quelle entrate diventano exp(-inf) = 0. La maschera azzera l'attenzione alle posizioni future in modo pulito.


per i in range(T):
per j in range(T):
if j > i:
scaled_scores[i][j] = -1e9   # efficacemente -inf

Dopo la softmax (per riga), ogni riga somma a 1, ma solo le entrate [0, i] portano massa di probabilità. La posizione i mescola informazioni solo dalle posizioni passate.


Visualizzazione di una Maschera

Una matrice di punteggi di forma (T, T) con maschera applicata appare come una struttura triangolare inferiore:


scaled_scores dopo la maschera, softmax riga per riga:

riga 0:  [1.0, 0,   0,   0,   ...]   # vede solo se stessa
riga 1:  [0.4, 0.6, 0,   0,   ...]   # vede le posizioni 0, 1
riga 2:  [0.2, 0.3, 0.5, 0,   ...]   # vede 0, 1, 2
riga 3:  [0.1, 0.2, 0.3, 0.4, ...]   # vede 0, 1, 2, 3
...

Distribuzione di probabilità strettamente triangolare inferiore per riga. Il futuro rimane invisibile.


Perché un Transformer Decoder-Only Ha Bisogno di Questo

I modelli decoder-only come ANDREA, GPT e LLaMA condividono un unico obiettivo: prevedere il token successivo dal passato. Una maschera causale rende questo obiettivo addestrabile in parallelo: ogni posizione calcola la propria previsione del token successivo contemporaneamente, e nessuna posizione bara sbirciando avanti.

Maschera & Varianti

L'Attività 2 (intro) ha trattato tre varianti di transformer: encoder-only, encoder-decoder, decoder-only. (a) Quale variante usa una maschera causale? (b) Spiega in una frase perché una variante diversa (encoder-only, come BERT) NON userebbe una maschera causale. (c) Quale obiettivo addestra un encoder non mascherato?

Dai Punteggi all'Output

Softmax: Da punteggi a probabilità

I punteggi mascherati e scalati variano ancora su numeri reali. Softmax converte ogni riga in una distribuzione di probabilità:


A[i][j] = exp(scaled_scores[i][j]) / sum_k exp(scaled_scores[i][k])

Tre proprietà ne risultano:

Explanation of Translation Choices

Key Decisions: - Technical terms preserved: "Softmax", "probability distribution" → "distribuzione di probabilità", math notation unchanged - Precise terminology: "Masked, scaled scores" → "Punteggi mascherati e scalati" (standard ML terminology in Italian) - Natural flow: "Scores to Probabilities" → "Da punteggi a probabilità" (preposition "da" creates smooth title) - Mathematical integrity: Formula preserved exactly as specified - Formatting preserved: All markdown, code blocks, spacing identical to original Italian ML Terminology Used: - "probability distribution" = "distribuzione di probabilità" - "real numbers" = "numeri reali" - "converts each row" = "converte ogni riga" - "result" = "risultano" (plural agreement with "tre proprietà")


- A[i][j] >= 0 per tutte le (i, j).

- sum_j A[i][j] = 1 per ogni riga i.

- Punti raw più grandi producono probabilità più grandi (monotona).


Il vettore di probabilità della riga i dice a un modello: quanto dovrebbe la posizione i prestare attenzione a ciascuna posizione precedente quando calcola la sua uscita?


Somma Pesata di V

Un'uscita finale di attenzione per la posizione i:


output[i] = sum_j A[i][j] · V[j]

Ogni vettore di valore V[j] viene ponderato dalla probabilità di attenzione A[i][j], poi sommato. L'output della posizione i combina i vettori di valore da ogni posizione precedente, ponderati per rilevanza.


In forma matriciale, tutte le posizioni contemporaneamente:


Attention(Q, K, V) = softmax(mask(Q · K^T / sqrt(d_k))) · V

Una riga. Un intero meccanismo di attenzione. Vaswani et al. scrissero quella riga nel 2017; i transformer non sono cambiati fondamentalmente da allora.


Forma di Uscita Per-Head

Uscita di una testa di attenzione: forma (T, d_k). Per ANDREA-120M: (1024, 64). Tutte le 12 teste calcolano in parallelo; le loro uscite si concatenano in (1024, 768) e alimentano una proiezione lineare finale (W_O), poi passano all'MLP di un blocco transformer.


L'Attività 6 (grow_a_language_model_multi_head) copre una suddivisione multi-head. L'Attività 7 (grow_a_language_model_transformer_block) copre tutto ciò che circonda l'attenzione: connessioni residue, layer norm, MLP.

Sintetizza un Pipeline

Sintetizza un intero pipeline di attenzione con le tue parole. Descrivi cosa succede a una singola posizione i (es. posizione 5 in una sequenza) dal vettore di input x_5 all'uscita attention[5]. Nomina quattro operazioni in ordine: (1) proiezione su Q/K/V, (2) calcolo dei punteggi scalati contro tutte le posizioni, (3) applicazione maschera causale + softmax, (4) somma dei vettori V pesati dalle probabilità. Un breve paragrafo.