Prima del paper ‘Attention is all you need’ (2017), l’attention era solo un componente aggiuntivo per LSTM e GRU. Quel paper ha eliminato completamente il modello RNN esistente e ha proposto un nuovo modello Seq2Seq basato esclusivamente sull’attention.
RNN esistenti

La sequenza viene ricevuta token per token ad ogni step. Ad ogni step, lo hidden state viene codificato e prodotto in output. L’attention veniva usata anche per pesare le informazioni degli step precedenti, determinando quanta informazione passata usare allo step corrente.
Ma a causa della proprietà intrinseca delle RNN di avere tempi di elaborazione proporzionali alla lunghezza della sequenza, problemi fondamentali come la long-term dependency e il gradient vanishing/exploding non potevano essere risolti completamente.
RNN bidirezionali
 Le RNN esistenti non possono usare informazioni sugli step futuri negli step precedenti. Nella Forward RNN sopra, ‘I’ non può accedere a informazioni su ‘go’ o ‘home’. Ma esistono contesti che richiedono informazioni successive, quindi sono state considerate le Backward RNN.
L’idea è apprendere in parallelo con la sequenza invertita. Nell’esempio sopra, per ‘go’ si ottengono due hidden state: e . Concatenandoli semplicemente si ottiene un nuovo hidden state di dimensione doppia.
Transformer
Self-attention
 (Figura 1)
Supponiamo che i vettori di input esistano come mostrato sopra. Il Transformer crea vettori di encoding che riflettono bene i contenuti della sequenza, nello stesso formato dei vettori di input.
Se vediamo questa figura come un decoder, allora I, go, home sono input che si presentano come hidden state a specifici time step. Simultaneamente, I, go, home possono essere visti come l’insieme dei vettori hidden state dell’encoder.
 Nel post precedente sull’attention, la similarità veniva calcolata tramite prodotto interno tra hidden state dell’encoder e vettori hidden state del decoder.
Eseguire questo processo all’interno di un singolo set di vettori è il motivo per cui la (Figura 1) è chiamata modulo di self-attention.
Problema
Dato che la similarità viene misurata all’interno di un singolo set di vettori, la similarità di un vettore con se stesso sarà molto più alta che con gli altri. Il vettore di output conterrà solo auto-informazione.
Quello che vogliamo è un’interpretazione significativa della sequenza (come in Seq2Seq), non un’auto-replicazione.
Soluzione
Per affrontare questo, si ideano tre vettori:
- Query: determina quali vettori del set usare selettivamente.
- Key: il vettore materiale che viene moltiplicato internamente con la Query per la similarità.
- Values: il vettore a cui vengono applicati i pesi di similarità query-key.
Struttura della self-attention Il set di vettori di input viene trasformato in vettori query, key e value attraverso matrici di trasformazione lineare separate , , .
Processo di encoding Supponiamo di codificare ‘I’.
-
Calcolo di Q, K, V Si crea il vettore Query tramite , il vettore Key tramite , il vettore Values tramite . La similarità generata da corrisponde 1-a-1 con .
-
Calcolo dei pesi dell’attention Si calcola la similarità tra Q e K e si applica softmax. Come nella (Figura 1), si può vedere che la auto-similarità è più bassa di quanto ci si aspetterebbe. Si ottiene una similarità oggettiva che non è dominata dall’auto-similarità.
-
Applicazione dei pesi di attention ai vettori value Si ottiene il vettore di encoding desiderato per ‘I’.
-
Ripetizione per l’elemento successivo della sequenza Solo la Query viene ricalcolata tramite ; Key e Value riutilizzano i risultati precedenti.
Parallelizzazione con matrici

Consideriamo la frase ‘Thinking Machines’. Per eseguire la self-attention, servono Q, K, V. Si potrebbe calcolare Q, K, V per ‘Thinking’ (), poi calcolare il vettore di output, e fare lo stesso per .
Ma parallelizziamo con le matrici.
Sia la matrice la concatenazione di e . Il prodotto scalare di con dà , che è uguale alla concatenazione di e . Lo stesso vale per e .
Miglioramento sui limiti delle RNN
Il Transformer produce vettori di encoding convertendo tutti i contenuti della sequenza in Q, K, V, indipendentemente dalla lunghezza o dall’ordine. Si è liberato dalla struttura fondamentale delle RNN dove lo hidden state fatica a portare informazioni precedenti man mano che le sequenze si allungano, migliorando sostanzialmente il problema della long-term dependency.
Scaled Dot-Product Attention
- Input: query , un set di key-value
- Q, K, V, Output sono tutti vettori!
- Output: somma pesata dei values
- Vettore pesato: prodotto interno di query e key corrispondente
- Query e key hanno la stessa dimensionalità .
- La dimensionalità del value è .
- e non devono essere uguali!
- L’applicazione del peso ai values è una moltiplicazione scalare indipendente dalla dimensione.
Generalizzazione

- i: quale vettore di input
- j: indice per calcolare i prodotti interni di q con tutti i k

La prima formula mostra il risultato della self-attention per una singola query. Estendiamola a una matrice Query, dove ogni riga è una query.

-
Il prodotto delle matrici Q e K crea una matrice le cui righe sono vettori pre-softmax per tutti i prodotti interni query-key.
-
Si applica softmax al risultato del prodotto Q-K. La softmax su una matrice è row-wise per default. Ogni riga diventa un vettore di pesi che somma a 1.
-
Si moltiplica il risultato del passo 2 per la matrice dei values. Questo esegue la moltiplicazione element-wise dei vettori di pesi con i vettori value. Essendo un prodotto interno, i pesi vengono moltiplicati lungo le colonne e sommati.
Questo mi ha confuso perché l’ordine di calcolo differisce leggermente dai diagrammi concettuali precedenti.

Qui, il peso 0.2 viene moltiplicato scalarmene a , 0.1 a , 0.7 a , producendo modificati. Questi 3 vettori vengono poi semplicemente sommati per formare un vettore 3-dimensionale.

Nella formula reale, i pesi per tutte le query sono già calcolati e memorizzati riga per riga. Anche i values sono memorizzati riga per riga. Quindi moltiplicare le due matrici applica la moltiplicazione dei pesi per colonna e la somma per riga.
Le spiegazioni concettuali vengono calcolate in parallelo tramite operazioni matriciali.
Riepilogo del Transformer
 Solo la parte di scaling è diversa; questo riassume tutto quanto spiegato sopra.
Ordine di calcolo semplificato:
- Calcolo di Q, K, V
- Esecuzione del calcolo dell’attention secondo la formula
- Ottenimento del vettore di encoding!
Come diagramma: 
Perché scalare per
Tra colleghi, l’abbiamo semplicemente inteso come prevenzione del gradient exploding. È in parte valido, ma la lezione del Professor Jaegeol Ju ha dato la risposta rigorosa.
Varianza Si assumano due vettori con media 0 e varianza 1:
(a, b), (x, y)
Il loro prodotto si calcola come trasponendo (x,y).
Fatti matematici
- Moltiplicare variabili casuali con la stessa media preserva media e varianza.
- Sommare due variabili casuali somma le loro varianze.
- Dividere una variabile casuale per divide la sua varianza per .
Quindi la varianza di è 2. Qui abbiamo usato vettori 2D quindi la differenza è piccola, ma con 100 dimensioni la varianza sarebbe 100.
Se la varianza è 2, la deviazione standard è , e supponiamo che il risultato del prodotto sia . Se la varianza saltasse a 100, questi potrebbero diventare . (Valori non esatti.)
Nella softmax, una deviazione standard maggiore significa che la distribuzione di probabilità si concentra sui valori più grandi. Una deviazione standard minore produce una distribuzione più uniforme.
Quindi, al crescere della dimensione, la distribuzione di probabilità può deviare significativamente da quella intesa. Se certe probabilità softmax diventano troppo grandi o piccole, il gradient vanishing diventa un rischio.
Perciò, usando i fatti matematici sopra, si ripristina la varianza. Dividendo per si divide la varianza per 2, riportandola a 1.
Ecco perché il Transformer scala per . Perché .