Mechanismus pozornosti: jak se model naučí, kam se dívat
Pozornost jako měkký slovník s dotazy, klíči a hodnotami, úloha, kterou bez ní obyčejná síť nezvládne, čitelné váhy, proč se dělí √d, sebepozornost a cesta k transformerům — na modelu napsaném od nuly.
Série Základy AI Díl 69 z 83
- Mapa umělé inteligence: co je co a jak to do sebe zapadá
- Stručná historie umělé inteligence: od Turinga po jazykové modely
- Data, model, trénink, inference: základní pojmy na jednom příkladu
- Jak číst matematický zápis: symboly, indexy, sumy a kvantifikátory
- Množiny a relace: stavebnice, ze které se skládají definice v AI
- Funkce a zobrazení: proč je každý model v AI funkce
- Logika a důkazy: pravidla, podle kterých se v AI uvažuje
- Grafy a stromy: struktura, na které stojí hledání i neuronové sítě
- Lineární algebra pro strojové učení: vektory, matice a proč AI hlavně násobí
- Derivace, gradient a řetízkové pravidlo: jak model zjistí, kterým směrem se učit
- Gradientní sestup: jak se model učí
- Co je pravděpodobnost: od hodu kostkou ke Kolmogorovovým axiomům
- Podmíněná pravděpodobnost a Bayesova věta: jak změnit odhad, když se dozvíte něco nového
- Náhodná veličina a distribuční funkce: jedna funkce, která o rozdělení řekne všechno
- Funkce hustoty a pravděpodobnostní funkce: proč má spojitá veličina v bodě pravděpodobnost nula
- Střední hodnota, rozptyl a kovariance: kde rozdělení leží, jak je široké a co s čím souvisí
- Přehled pravděpodobnostních rozdělení: Bernoulli, binomické, Poisson, rovnoměrné, normální a exponenciální
- Zákon velkých čísel a centrální limitní věta: proč se průměry chovají tak předvídatelně
- Statistika a odhady parametrů: maximální věrohodnost, MAP a intervaly spolehlivosti
- Teorie informace: entropie, křížová entropie a KL divergence — odkud se berou ztrátové funkce
- Prohledávání stavového prostoru: BFS, DFS, UCS a A* s animacemi
- Hry a protivník: minimax, alfa-beta ořezávání a Monte Carlo tree search
- Splňování omezujících podmínek: backtracking, propagace omezení a AC-3 na sudoku a mapě krajů
- Logika a znalostní systémy: dopředné a zpětné řetězení, rezoluce a expertní systémy
- Plánování: STRIPS, svět kostek, heuristiky z relaxace a plánování v AI agentech
- Lokální hledání a simulované žíhání: obchodní cestující přes krajská města
- Genetické algoritmy: populace, křížení, mutace a výběr na batohu na výlet
- Evoluční strategie a genetické programování: od pravidla jedné pětiny po Keplerův zákon
- Optimalizace mravenčí kolonií: jak feromonová stopa najde krátkou cestu
- Optimalizace hejnem částic: setrvačnost, vlastní zkušenost a zkušenost hejna
- Neuroevoluce: evoluce vah i tvaru neuronových sítí a algoritmus NEAT
- Fuzzy množiny a funkce příslušnosti: jak zapsat „trochu teplo“
- Fuzzy logika a pravděpodobnost: proč „trochu teplo“ neznamená „pravděpodobně teplo“
- Fuzzy logika: t-normy, implikace a pravidla KDYŽ–PAK
- Fuzzy řízení: Mamdani a Sugeno od ventilátoru po kyvadlo na vozíku
- Fuzzy shlukování: algoritmus fuzzy c-means a body mezi shluky
- Neuro-fuzzy systémy (ANFIS): fuzzy pravidla, která se učí z dat
- Markovovy řetězce: přechodová matice, stacionární rozdělení a PageRank
- Skryté Markovovy modely: Viterbiho algoritmus a nepoctivé kasino
- Bayesovské sítě: proč je tráva mokrá a co z toho plyne pro postřikovač
- Kalmanův filtr: jak z nepřesných měření odhadnout, kde auto je a jak rychle jede
- Druhy strojového učení: s učitelem, bez učitele, s částečným učitelem a další
- Přeučení a regularizace: proč model, který zná data nazpaměť, selže
- Vyhodnocení modelu: křížová validace, F1 a křivka ROC
- Shlukování a snížení dimenze: k-means, PCA a t-SNE
- Klasifikace a regrese: dvě úlohy učení s učitelem
- Lineární regrese: nejmenší čtverce geometricky i maticově
- Polynomiální a nelineární regrese: jak přímku ohnout
- Logistická regrese: sigmoida, šance a křížová entropie
- Vícetřídní klasifikace a softmax: od dvou tříd k mnoha
- Naivní Bayesův klasifikátor: spamový filtr, který funguje lépe, než by měl
- Ztrátové funkce: co přesně model minimalizuje
- Rozhodovací stromy a k nejbližších sousedů: modely bez vzorců
- Ansámbly: náhodný les a gradient boosting
- SVM a jádrový trik: nejširší hranice a jak ji ohnout
- Signál a vzorkování: proč platí Nyquistův teorém
- Fourierova transformace: rozklad signálu na frekvence
- Filtry a konvoluce: vyhlazení, hrany a odstranění šumu
- Zvuk a řeč: spektrogram, melová škála a MFCC
- Obraz jako signál: pixely, barvy, konvoluce a hrany
- Perceptron a umělý neuron: nejjednodušší neuronová síť a co neumí
- Neuronová síť od nuly: zpětné šíření chyby krok za krokem
- Aktivace, inicializace a normalizace: drobnosti, na kterých hluboká síť stojí
- Konvoluční sítě: jak síť poznává obrázky
- Rekurentní sítě: paměť pro posloupnosti a mizející gradient
- LSTM a GRU: brány, které rozhodují, co si síť zapamatuje
- Autoenkodéry: síť, která se učí data stlačit a zase rozbalit
- Embeddingy a word2vec: jak se slovo stane vektorem
- Mechanismus pozornosti: jak se model naučí, kam se dívat
- Transformery a velké jazykové modely: architektura krok za krokem
- Tokenizace: jak se text rozseká na kousky pro model
- Předtrénování a škálování: proč větší model a víc dat funguje
- Doladění a RLHF: jak se z doplňovače textu stane asistent
- Prompty, kontext a RAG: jak modelu dát správné informace
- Variační autoenkodéry (VAE): nové obrázky ze spojitého latentního prostoru
- Generativní adversariální sítě (GAN): padělatel proti detektivovi
- Difúzní modely: jak se z čistého šumu stane obrázek
- Markovovy rozhodovací procesy: stavy, akce, odměny a Bellmanovy rovnice
- Q-learning a DQN: učení hodnoty akcí od tabulky po neuronovou síť
- Policy gradient a PPO: učení přímo strategie
- Jak funguje AI agent: jazykový model ve smyčce s nástroji
- Programování s AI agenty: zadání, testy a kontrola
- Vyhodnocení a bezpečnost AI systémů: jak měřit a jak hlídat
Celá osnova série 83 z 83 témat hotovo
- Co počítá pozornost a proč je to měkký slovník.
- Proč pozornost vyřeší úlohu, na které selže průměrování i plně propojená síť.
- Proč se skóre dělí √d a co je sebepozornost.
Co se hodí znát předem: LSTM a GRU: brány, které rozhodují, co si síť zapamatuje, Embeddingy a word2vec: jak se slovo stane vektorem
Když čtete větu „Pes nepřeskočil plot, protože byl moc vysoký“, slovo „byl“ si v hlavě spojíte s plotem, ne se psem — a kdyby tam stálo „moc unavený“, spojili byste ho se psem. Při čtení se pořád díváte zpátky na to, co je právě důležité. Rekurentní sítě tohle neumějí: všechno, co přečetly, musí nacpat do jednoho stavu pevné velikosti. Pozornost jim dovolí podívat se na kterékoli dřívější slovo přímo. Z tohohle jednoho nápadu vznikly transformery a s nimi všechny dnešní velké jazykové modely.
Navazuje na díly LSTM a GRU a Embeddingy a word2vec.
1. Pozornost jako měkký slovník
Definice — pozornost (dotaz, klíče, hodnoty)
Nechť d, m, n ∈ ℕ, d, m, n ≥ 1. Nechť q ∈ ℝd je dotaz, k1, …, kn ∈ ℝd jsou klíče a v1, …, vn ∈ ℝm jsou hodnoty (klíč ki a hodnota vi tvoří i-tou položku). Pozornost (škálovaná, se skalárním součinem) přiřadí dotazu vektor
Attention(q; k1, …, kn; v1, …, vn) = ∑i=1n ai vi ∈ ℝm,
kde pro i = 1, …, n:
- skóre si = q · ki/√d, přičemž q · ki = ∑r=1d qr(ki)r je skalární součin;
- váhy (a1, …, an) = softmax(s1, …, sn), tj. ai = exp(si)/∑j=1n exp(sj) (funkce softmax je zavedená v dílu Vícetřídní klasifikace a softmax).
Platí ai > 0 a ∑i=1n ai = 1, takže výsledek pozornosti je vážený průměr hodnot, ve kterém má větší váhu hodnota té položky, jejíž klíč má s dotazem větší skalární součin.
V neuronové síti vznikají dotaz, klíče a hodnoty z reprezentací vstupu: nechť x ∈ ℝp je reprezentace toho, kdo se ptá, x1, …, xn ∈ ℝp′ reprezentace položek a WQ ∈ ℝd×p, WK ∈ ℝd×p′, WV ∈ ℝm×p′ naučené matice. Pak q = WQx, ki = WKxi a vi = WVxi pro i = 1, …, n.
Obyčejný slovník najde klíč, který se s dotazem shoduje přesně, a vrátí jeho hodnotu. Pozornost je slovník „měkký“: porovná dotaz se všemi klíči, každému dá váhu podle podobnosti a vrátí vážený průměr hodnot. Když jeden klíč sedí mnohem líp než ostatní, je to skoro totéž jako obyčejný slovník. A protože je všechno spojité, dá se to učit gradientním sestupem: síť se sama naučí, jak dotazy a klíče vypadat mají.
o = ∑i ai vi, ai = exp(si)/∑j exp(sj), si = q · ki/√d
- q
- dotaz — popis toho, co právě hledáme; je jeden a porovnává se se všemi klíči
- ki
- klíč — „štítek“ položky i; podle něj se pozná, jestli se k dotazu hodí. Klíč je oddělený od hodnoty, protože podle čeho hledáme a co chceme dostat jsou dvě různé věci (písmeno a číslice)
- si
- skóre — skalární součin je velký, když dotaz a klíč míří stejným směrem; je to nejlevnější míra podobnosti, kterou jde i derivovat
- √d
- odmocnina z dimenze vektorů — drží skóre v rozumném rozsahu, ať softmax není hned od začátku „jistý“ (oddíl Proč dělit √d)
- ai
- váha — softmax ze skóre udělá kladná čísla se součtem 1; tvrdé „vyber nejlepší klíč“ by nešlo derivovat, měkké vážení jde. Tytéž váhy kreslí zeleně obrázek v oddílu Kam se model dívá
- vi
- hodnota — to, co si z položky odneseme; výsledek o je jejich vážený průměr
Příklad — měkký slovník se třemi položkami
Dimenze d = 2, dotaz q = (2; 1), klíče k1 = (1; 0), k2 = (0; 1), k3 = (−1; 0) a hodnoty (pro jednoduchost čísla) v = (10; 20; 30).
q · ki = (2; 1; −2), √2 = 1,414 → s = (2/1,414; 1/1,414; −2/1,414) = (1,414; 0,707; −1,414)
exp(si) = (4,113; 2,028; 0,243), ∑j exp(sj) = 6,384
a = (4,113/6,384; 2,028/6,384; 0,243/6,384) = (0,644; 0,318; 0,038)
o = 0,644 · 10 + 0,318 · 20 + 0,038 · 30 = 6,44 + 6,35 + 1,14 = 13,94
Barvy odpovídají členům vzorce výše.
Dotaz se nejvíc podobá prvnímu klíči, takže výsledek je blízko jeho hodnotě 10, ale je do něj přimíchaná i dvacítka. Obyčejný slovník by vrátil přesně 10; čím víc se skóre prvního klíče od ostatních odliší, tím víc se mu měkký slovník přiblíží.
def pozornost(q, klice, hodnoty):
d = len(q)
s = [skal(q, k) / sqrt(d) for k in klice] # skóre: jak moc klíč sedí k dotazu
m = max(s)
e = [exp(si - m) for si in s] # odečtení maxima výsledek nezmění, jen brání přetečení
a = [ei / sum(e) for ei in e] # váhy: kladné, součet 1
return sum(ai * v for ai, v in zip(a, hodnoty)) # vážený průměr hodnot
2. Úloha, kterou bez pozornosti nevyřešíte
Model dostane šest dvojic písmeno → číslice, třeba b → 1, h → 4, a → 4, g → 2, c → 9, f → 8, a dotaz „a → ?“. Správná odpověď je 4. Dvojice jsou pokaždé jiné, takže se nedá nic naučit nazpaměť — model musí v každém příkladu najít tu správnou dvojici. Porovnáme tři modely učené stejně (Adam, 4 000 kroků po 16 příkladech):
- pozornost — dotaz se porovná se všemi dvojicemi, 874 parametrů,
- průměrování — stejný model, ale všechny dvojice mají stejnou váhu 1/6,
- plně propojená síť — všech šest dvojic a dotaz najednou na vstupu, skrytá vrstva 64 neuronů, 8 138 parametrů.
Definice — model s pozorností pro úlohu „slovník“ a jeho ztráta
Nechť 𝒫 = {a, b, …, h} je množina osmi písmen a 𝒞 = {0, 1, …, 9} množina deseti číslic. Pro písmeno π ∈ 𝒫 označme eπ ∈ {0, 1}8 jeho vektor one-hot (jednička na pozici písmena, jinde nuly; viz díl Embeddingy a word2vec) a pro číslici c ∈ 𝒞 obdobně uc ∈ {0, 1}10.
Příklad úlohy je šestice dvojic (πi, ci) ∈ 𝒫 × 𝒞, i = 1, …, 6, s navzájem různými písmeny (πi ≠ πj pro i ≠ j), spolu s dotazovaným písmenem π* = πi* pro nějaké i* ∈ {1, …, 6}. Správná odpověď je c* = ci*. Vstupy modelu jsou
xi = (eπi, uci) ∈ {0, 1}18 (i = 1, …, 6), xdotaz = eπ* ∈ {0, 1}8,
kde (e, u) značí spojení dvou vektorů za sebe. Model s pozorností s dimenzí d = 16 má parametry WQ ∈ ℝd×8, WK, WV ∈ ℝd×18, WO ∈ ℝ10×d a bO ∈ ℝ10 a počítá:
- q = WQxdotaz, ki = WKxi, vi = WVxi pro i = 1, …, 6;
- o = Attention(q; k1, …, k6; v1, …, v6) = ∑i=16 aivi ∈ ℝd (definice pozornosti výše);
- y = softmax(WOo + bO) ∈ ℝ10; složka yc je pravděpodobnost, kterou model dává číslici c ∈ 𝒞.
Ztráta na jednom příkladu je
L = −ln yc*,
tj. křížová entropie (s přirozeným logaritmem, v jednotkách nat) mezi správnou odpovědí ve tvaru one-hot uc* a předpovědí y (křížová entropie je zavedená v dílu Teorie informace). Průměrování je týž model, jen krok 2 počítá s pevnými vahami ai = 1/6 pro všechna i.
Model, který nic neví a dá všem deseti číslicím yc = 1/10, má ztrátu −ln 1/10 = ln 10 ≈ 2,303 — to je čárkovaná čára v obrázku níže.
Příklad — odkud se berou počty parametrů
pozornost: WQ 16 × 8 + WK 16 × 18 + WV 16 × 18 + WO 10 × 16 + bO 10 = 128 + 288 + 288 + 160 + 10 = 874
plně propojená síť: vstup 6 · 18 + 8 = 116, 64 × 116 + 64 + 10 × 64 + 10 = 7 424 + 64 + 640 + 10 = 8 138
Matice pozornosti mají stejný tvar pro všech šest dvojic — jedno WK slouží každé pozici. Plně propojená síť má pro každou pozici vlastní kus matice W1, a proto má parametrů 9krát víc.
Pozornost má po učení na 1 000 nových příkladech přesnost 100,0 %. Průměrování 34,9 % — vidí, které hodnoty se ve slovníku vyskytují, ale ne, která patří k dotazu. Plně propojená síť, přestože má devětkrát víc parametrů, jen 27,4 %: musí se pro každou ze šesti pozic zvlášť naučit „když se písmeno na této pozici shoduje s dotazem, vezmi číslici vedle“, a na to jí 64 000 příkladů nestačí. Pozornost má tu operaci zabudovanou a stejnou pro každou pozici — podobně jako konvoluce má zabudovaný posun.
3. Kam se model dívá
Váhy se dají přímo vyčíst: model téměř celou pozornost věnuje dvojici s dotazovaným písmenem — v průměru přes 300 nových příkladů 96,4 %. Nikdo mu neřekl „porovnej písmena“; matice WQ a WK se to naučily samy, protože jen tak šlo chybu zmenšit. Tahle čitelnost je jedna z příjemných vlastností pozornosti — i když u velkých modelů s desítkami vrstev je výklad vah mnohem ošidnější.
Příklad — jaký náskok ve skóre znamená váha 0,964
Zjednodušeně předpokládejme, že ostatních pět dvojic má stejné skóre a správná je o Δ výš. Pak
asprávná = eΔ/eΔ + 5 ⇔ Δ = ln 5 · asprávná/1 − asprávná
Δ = ln 5 · 0,964/0,036 = ln 133,9 = 4,9
Správná dvojice tedy dostane asi 134krát větší váhu než každá jiná. K tomu stačí, aby skóre (už vydělené √d) bylo o necelých pět jednotek vyšší — jinými slovy, aby model měl matice WQ, WK naladěné tak, že shodné písmeno dává výrazně větší skalární součin než neshodné.
4. Proč dělit √d
Skalární součin dvou náhodných vektorů dimenze d se složkami s rozptylem 1 má rozptyl d; skóre jsou tedy s rostoucí dimenzí čím dál větší a softmax z nich dělá skoro jistotu.
Věta — rozptyl skalárního součinu roste s dimenzí
Nechť d ∈ ℕ, d ≥ 1, a nechť q = (q1, …, qd) a k = (k1, …, kd) jsou náhodné vektory v ℝd, jejichž složky q1, …, qd, k1, …, kd jsou navzájem nezávislé náhodné veličiny a pro každé j = 1, …, d platí
E[qj] = E[kj] = 0, Var(qj) = Var(kj) = 1.
Pak E[q · k] = 0 a
Var(q · k) = d, a proto Var(q · k/√d) = 1.
Důkaz. Pro jeden člen: z nezávislosti E[qjkj] = E[qj] E[kj] = 0 a E[qj2] = Var(qj) + (E[qj])2 = 1, stejně E[kj2] = 1. Proto
Var(qjkj) = E[qj2kj2] − 02 = E[qj2] · E[kj2] = 1 · 1 = 1.
Členy qjkj pro různá j jsou nezávislé (každý závisí na jiné dvojici složek), takže E[q · k] = ∑j E[qjkj] = 0 a rozptyly se sčítají: Var(q · k) = ∑j=1d 1 = d. Pro konstantu c je Var(cX) = c2 Var(X), takže dělení √d dá rozptyl d/d = 1. ∎
Var(q · k/√d) = 1/d · ∑j=1d Var(qjkj) = 1/d · d = 1
- q
- dotaz — na začátku učení vychází z náhodně nastavených matic, takže se chová jako náhodný vektor
- k
- klíč — totéž; jejich skalární součin je skóre před škálováním
- ∑ Var(qjkj) = d
- každá z d složek přidá k rozptylu jedničku — čím víc složek, tím víc se skóre rozjedou od nuly; typická velikost skóre je √d
- √d a 1/d
- vydělit náhodnou veličinu číslem √d znamená vydělit její rozptyl d — přesně tolik, kolik jsme přidali; vyjde rozptyl 1 bez ohledu na d
První řádek tabulky to potvrzuje: velikost skóre je zhruba √d = 2, 4, 8, 16. Vychází o trochu menší, protože jde o průměr přes pouhých šest skóre v každém pokusu a odmocnina z takového odhadu rozptylu ho v průměru mírně podceňuje.
| Dimenze d | 4 | 16 | 64 | 256 |
|---|---|---|---|---|
| typická velikost skóre | 1,8 | 3,8 | 7,6 | 15,4 |
| největší váha bez škálování | 0,57 | 0,78 | 0,89 | 0,94 |
| největší váha s dělením √d | 0,40 | 0,42 | 0,42 | 0,42 |
Pro náhodné dotazy a klíče (šest klíčů, tedy rovnoměrně by měl každý 0,17) dá softmax bez škálování při d = 256 nejlepšímu klíči v průměru 94 % váhy — model by si byl „jistý“, i když neví nic. Takový softmax má skoro nulový gradient a učení stojí. Po vydělení √d zůstane největší váha kolem 0,42 v každé dimenzi: model začne nejistý a jistotu si musí zasloužit.
Příklad — proč „jistý“ softmax neučí
Derivace softmaxu: ∂ai/∂sj = ai([i = j] − aj), kde [i = j] je 1 pro i = j a 0 jinak; tedy pro váhu podle vlastního skóre ai(1 − ai). Dosadíme průměrné největší váhy z tabulky pro d = 256:
bez škálování: 0,94 · (1 − 0,94) = 0,94 · 0,06 = 0,056
s dělením √d: 0,42 · (1 − 0,42) = 0,42 · 0,58 = 0,244
a kdyby byla váha 0,99: 0,99 · 0,01 = 0,010
Gradient, který přes softmax proteče ke skóre (a dál k WQ, WK), se těmito činiteli násobí. Čím jistější softmax, tím menší krok učení — u váhy blízko 1 se skoro zastaví.
5. Self-attention: každé slovo se ptá všech
Definice — sebepozornost a více hlav
Nechť n, d, dk, dv ∈ ℕ jsou kladná čísla a x1, …, xn ∈ ℝd vektory tokenů jedné posloupnosti; uložme je jako řádky matice X ∈ ℝn×d. Nechť WQ, WK ∈ ℝd×dk a WV ∈ ℝd×dv jsou naučené matice. Sebepozornost (self-attention) je zobrazení ℝn×d → ℝn×dv, které z téže posloupnosti spočte pro každý token j = 1, …, n dotaz, klíč i hodnotu
qj = WQTxj, kj = WKTxj, vj = WVTxj
(tj. řádky matic Q = XWQ, K = XWK, V = XWV) a nový vektor tokenu j určí pozorností jeho dotazu na všechny tokeny:
zj = Attention(qj; k1, …, kn; v1, …, vn) = ∑i=1n aji vi, (aj1, …, ajn) = softmax(qj · k1/√dk, …, qj · kn/√dk).
Nechť dále h ∈ ℕ, h ≥ 1, a pro každé r = 1, …, h má hlava r vlastní matice WQ(r), WK(r), WV(r) uvedených rozměrů; headr ∈ ℝn×dv je výsledek sebepozornosti s nimi. Nechť WO ∈ ℝhdv×d. Vícehlavá pozornost je
MultiHead(X) = [head1, …, headh] WO ∈ ℝn×d,
kde [·, …, ·] značí matice položené vedle sebe (spojení po sloupcích, výsledek má rozměr n × hdv). Každý token tedy dostane nový vektor, který je v každé hlavě váženým průměrem hodnot všech tokenů posloupnosti.
V naší úloze se ptal jeden dotaz. V textu se ptá každé slovo: „byl“ hledá, ke komu patří, „plot“ hledá své přídavné jméno. Každá hlava se může specializovat na jiný druh vztahu — jedna na podmět a přísudek, jiná na to, co stojí hned vedle. Všechno se počítá najednou, maticovým násobením, a proto je to na grafických kartách tak rychlé.
Když dotazy všech n tokenů naskládáme pod sebe do matice Q (n × dk) a stejně tak klíče do K a hodnoty do V, spočte se celá vrstva dvěma násobeními matic:
A = softmaxpo řádcích(Q KT/√dk), výstup = A V
- Q
- dotazy všech tokenů, řádek j je qj — každý token se ptá zvlášť
- KT
- klíče všech tokenů, transponované, aby součin QKT dal v buňce (j, i) právě skalární součin qj · ki — všech n2 skóre jednou operací
- √dk
- škálování dimenzí jedné hlavy, ze stejného důvodu jako výše
- A
- matice vah n × n: řádek j říká, kolik pozornosti token j věnuje kterému tokenu; softmax po řádcích, aby každý řádek dal součet 1
- V
- hodnoty; řádek j součinu AV je vážený průměr hodnot pro token j — nový vektor tokenu
MultiHead(X) = [ head1, …, headh ] WO, headr = Attention( XWQ(r), XWK(r), XWV(r) )
- XWQ(r)
- dotazy hlavy r: X (n × d) jsou vektory tokenů, každá hlava má vlastní matici, a tak se může ptát na něco jiného
- XWK(r)
- klíče hlavy r — tytéž tokeny se v každé hlavě „nabízejí“ pod jiným štítkem
- XWV(r)
- hodnoty hlavy r — i to, co si hlava odnese, je jiné
- headr
- výstup jedné hlavy (n × dk, obvykle dk = d/h); hlav je víc, protože jeden softmax umí dát velkou váhu jen málo tokenům a token potřebuje sbírat informace o několika vztazích naráz
- WO
- výstupní matice d × d — výsledky hlav jsou jen položené vedle sebe, tahle matice je smíchá zpět do jednoho vektoru tokenu
def sebepozornost(X, hlavy, W_O):
# X: n × d (řádek = token); hlavy: seznam trojic (W_Q, W_K, W_V), každá d × d_k
vystupy = []
for W_Q, W_K, W_V in hlavy:
Q, K, V = X @ W_Q, X @ W_K, X @ W_V # n × d_k
S = Q @ K.T / sqrt(d_k) # n × n skóre: každý s každým
A = softmax(S, po_radcich=True) # váhy, každý řádek dá součet 1
vystupy.append(A @ V) # n × d_k
return spoj_vedle_sebe(vystupy) @ W_O # n × d
Cena: každý token se porovná s každým, takže skóre je n2. Pro 1 000 tokenů je to 1 000 000 skóre v každé hlavě každé vrstvy, pro 100 000 tokenů 10 000 000 000. Dlouhý kontext je proto drahý a hledají se způsoby, jak ho zlevnit.
Příklad — počty operací a parametrů v původním transformeru
Původní transformer (Vaswani a kol., 2017) měl vektory tokenů dimenze d = 512 a h = 8 hlav, tedy dk = 512/8 = 64. Pro n = 1 000 tokenů a jednu hlavu:
QKT: n2 skóre po dk násobeních = 1 000 000 · 64 = 64 milionů násobení
AV: dalších n2 · dk = 64 milionů; pro 8 hlav dohromady 8 · 128 milionů ≈ 1 miliarda
parametry jedné vrstvy pozornosti: WQ, WK, WV všech hlav 3 · 512 · (8 · 64) + WO 512 · 512 = 4 · 5122 = 1 048 576 (bez posunů)
Počet parametrů na délce textu nezávisí — stejné matice slouží každé pozici —, počet operací roste s n2.
6. Od překladu k transformerům
- Pozornost v překladu (Dzmitry Bahdanau, Kjunghjun Čo, Yoshua Bengio, 2014). Překladová rekurentní síť si při psaní každého slova překladu „prohlíží“ slova originálu — a z vah je vidět, které slovo překládá které.
- „Attention Is All You Need“ (Ashish Vaswani a kol., Google, 2017) rekurenci vyhodila úplně a postavila model jen z vrstev sebepozornosti: transformer. O něm je další díl.
- Dnes. Pozornost se používá i pro obrázky (Vision Transformer), zvuk, proteiny (AlphaFold 2) a všude tam, kde je potřeba propojit vzdálené části vstupu.
Definice — aditivní pozornost (Bahdanau a kol., 2014) proti skalárnímu součinu
Nechť originál má n slov a kodér pro i-té z nich spočetl stav hi ∈ ℝdh, i = 1, …, n. Nechť dekodér právě píše t-té slovo překladu (t ≥ 1) a jeho předchozí stav je st−1 ∈ ℝds. Nechť W ∈ ℝp×ds, U ∈ ℝp×dh a w ∈ ℝp jsou naučené parametry (p je počet neuronů skryté vrstvy) a tanh se aplikuje po složkách. Aditivní pozornost spočte pro i = 1, …, n:
- skóre malou sítí s jednou skrytou vrstvou: eti = wT tanh(W st−1 + U hi) ∈ ℝ;
- váhy (at1, …, atn) = softmax(et1, …, etn);
- kontextový vektor, který dekodér použije při volbě t-tého slova: ct = ∑i=1n ati hi ∈ ℝdh.
V řeči tohoto dílu je st−1 dotaz a hi klíč i hodnota zároveň. Transformer nahradil síť pro skóre skalárním součinem q · ki/√d: dá podobné výsledky, ale všechna skóre se spočtou jedním násobením matic, což je na grafické kartě mnohem rychlejší.
7. Shrnutí
- Pozornost je měkký slovník: porovná dotaz se všemi klíči, softmaxem z toho udělá váhy a vrátí vážený průměr hodnot.
- Na úloze „slovník“ dosáhla 100,0 %, průměrování 34,9 % a plně propojená síť s devětkrát víc parametry 27,4 %.
- Naučené váhy jsou čitelné: na správné dvojici v průměru 96,4 % pozornosti.
- Dělení √d brání tomu, aby softmax byl předčasně jistý (bez něj při d = 256 největší váha 0,94 i pro náhodná data).
- V sebepozornosti se ptá každý token všech ostatních; cena roste s druhou mocninou délky textu.
Chcete si to osahat? Nechte AI agenta načíst malý předtrénovaný jazykový model (třeba GPT-2) a vykreslit váhy pozornosti pro větu „Pes nepřeskočil plot, protože byl moc vysoký.“ Najdete hlavu, která spojí „byl“ s „plot“?
Máte na to jiný názor? Napište na support@coden-app.com.