Lekce 07 · 20 min čtení
Self-attention
Jak nechat každé slovo podívat se na ostatní a vzít si od nich, co potřebuje. Query, Key, Value a scaled dot-product attention.
Úvod
Tahle lekce je ta nejdůležitější v celém kurzu. Self-attention je nápad, na kterém stojí každý dnešní velký model. Vezmeme si na něj víc času a víc příkladů než na cokoliv dosud. Když ti něco nebude dávat smysl napoprvé, je to normální. Mně to trvalo dlouho.
Začnu příkladem mimo AI. Sedíš v hospodě a kolem tebe běží tři konverzace naráz. Tvůj mozek nedává všem stejnou pozornost. Když někdo o dva stoly dál řekne tvoje jméno, okamžitě se naladíš tam. Když padne slovo, které tě zajímá, ucho se otočí. Filtruješ šum a soustředíš se na to, co je teď relevantní.
Přesně tohle dělá self-attention. Každé slovo ve větě se rozhlédne po ostatních slovech a vytáhne si od nich informaci, kterou zrovna potřebuje. A je úplně jedno, jestli to relevantní slovo stojí hned vedle, nebo o dvacet slov dál.

V hospodě je ruchu dost. Důležité je vybrat si, čemu zrovna věnovat ucho.
Proč to vůbec chceme
Vzpomeň si na náš bigram. Ten viděl vždycky jen jedno slovo dozadu. „Pan Švejk řekl poslušně" zvládl, ale o větu dál ztratil nit. Problém je, že jazyk je plný vztahů na dálku.
Ve větě „Švejk, kterého rytmistr den předtím seřval, se spokojeně usmál" patří „usmál se" ke „Švejk", ne k „rytmistr". Ta dvě slova dělí půl věty. Bigram nemá šanci. Potřebujeme mechanismus, který nechá „usmál" sáhnout přes celou větu zpátky ke „Švejk". A to je attention.
Tři role: Query, Key, Value
Tady je celý trik. Každé slovo dostane tři různé vektory, každý hraje jinou roli. Drž se téhle hospodské analogie, fakt to pomáhá:
- Query (dotaz): co dané slovo zrovna hledá. Jako bys do místnosti zakřičel „kdo tu mluví o pivu?".
- Key (klíč): co dané slovo nabízí, čím se ohlašuje. Jako cedulka na čele „já jsem o pivu".
- Value (hodnota): co slovo skutečně předá dál, když si ho někdo vybere. Vlastní obsah, který přispěje.
Query, Key i Value vzniknou z embeddingu slova, každý přes svoji váhovou matici (ty se model naučí). Pro nás teď stačí: každé slovo má dotaz, klíč a hodnotu.
Skóre: kdo se ke komu hodí
Jak slovo pozná, na koho se má dívat? Porovná svůj dotaz s klíčem každého slova. A porovnání dvou vektorů už umíme z lekce 3: skalární součin. Čím víc si dotaz a klíč sednou, tím vyšší skóre.
To dělení (kde je délka vektorů) je jen technická pojistka. Když jsou vektory dlouhé, skalární součiny vycházejí velké a softmax by z nich udělal moc ostré špičky, se kterými se pak špatně trénuje. Vydělením to zkrotíme. Ber to jako hlasitost staženou na rozumnou úroveň.
Skóre pak proženeme softmaxem (taky z lekce 4), zvlášť pro každé slovo. Tím dostaneme váhy pozornosti: kladná čísla se součtem 1, která říkají, jak moc se dané slovo dívá na každé jiné.
Tady je to naživo. Klikni na řádek (na slovo, které model zrovna zpracovává) a koukni, kam se dívá. Zkus i kauzální masku:
AttentionHeatmap · kdo se dívá na koho
Řádek = slovo, které zrovna zpracováváme. Sloupec = na koho se dívá. Tmavší = víc pozornosti.
Když model zpracovává slovo vypil, dívá se hlavně na: pan, švejk, pivo
Pozn.: Q a K jsou tu ručně nastavené, aby vzorec dával smysl. V reálu si je model najde sám.
Všimni si, jak to dává smysl. Sloveso vypil se dívá na svůj podmět i předmět
(pan, švejk, pivo). Předmět pivo se dívá zpátky na sloveso vypil.
Předložka v se lepí na hospodě. Nikdo to slovu neřekl, vyplývá to ze shody
dotazů a klíčů.
Kauzální maska: proč model nesmí koukat dopředu
Když přepneš „kauzální maska", každé slovo smí koukat jen na sebe a na slova před sebou, ne za sebe. To je nutné pro generování textu: když model hádá další slovo, samozřejmě ještě nesmí vidět to, co teprve přijde. Bylo by to podvádění. GPT proto attention vždycky takhle maskuje.
Výstup: vážený mix hodnot
Váhy pozornosti zatím jen říkají, kam se dívat. Co s tím? Vezmeme hodnoty (Value) všech slov a uděláme jejich vážený průměr podle těch vah. Slovo, na které se hodně díváme, přispěje do výsledku hodně. Slovo, které ignorujeme, skoro vůbec.
A to je celá self-attention pohromadě:
Každé slovo si tím přimíchá do své reprezentace informaci z relevantních slov
v kontextu. vypil po průchodu attention „ví", kdo pil a co. Přesně ten vztah
na dálku, který bigramu chyběl.
V kódu
Napíšeme celou scaled dot-product attention v numpy. Pár řádků, ale je v nich
schovaná půlka moderní AI. Pro názornost dáme jako hodnoty (V) jednotkovou
matici, takže výstup rovnou ukáže, z koho se každé slovo namíchalo.
Zkus si vybrat jiné slovo (změň "vypil" třeba na "v" nebo "pivo") a koukni,
na co se dívá. Tahle jedna funkce, softmax(Q @ K.T / sqrt(d)) @ V, je
doslova jádro transformeru. Zbytek architektury jsou už jen chytré obaly kolem ní.
Cvičení
Cvičení · lekce7-cv1
Dotaz Q = [1, 0, 1] a klíč K = [1, 1, 1]. Jaké je skóre (skalární součin
Q · K) před škálováním?
Cvičení · lekce7-cv2
Vektory mají délku d = 16. Číslem se ve scaled dot-product attention dělí
skóre? (Zadej to číslo.)
Cvičení · lekce7-cv3
Váhy pozornosti pro jedno slovo (jeden řádek) vzniknou softmaxem. Na kolik se sečtou?
Cvičení · lekce7-cv4
V heatmapě nahoře zapni kauzální masku a klikni na pivo. Na co se teď pivo
dívá a co se změnilo oproti vypnuté masce? Napiš sem jednou větou.
Shrnutí
- Self-attention nechá každé slovo podívat se na ostatní a vzít si od nich relevantní informaci, i přes velkou vzdálenost ve větě.
- Každé slovo má tři vektory: Query (co hledám), Key (co nabízím), Value (co předám dál).
- Skóre = skalární součin dotazu a klíče, vydělený . Softmax z něj udělá váhy pozornosti se součtem 1.
- Výstup slova je vážený průměr hodnot ostatních slov podle těch vah.
- Celé naráz: .
- Kauzální maska zakáže koukat dopředu, což je nutné pro generování.
Co bude příště
Jedna attention je jeden úhel pohledu. Jenže ve větě běží víc vztahů zároveň: kdo s kým, co kde, kdy. Jedna hlava pozornosti to všechno naráz neuhlídá.
V Lekci 8 (Multi-head + poziční kódování) pustíme na větu víc hlav pozornosti naráz, každou se svým úhlem pohledu, a jejich výstupy slepíme. A vyřešíme jeden tichý problém, kterého sis možná všiml: attention sama o sobě vůbec neví, v jakém pořadí slova jdou. To opravíme pozičním kódováním.