jancll.com

Lekce 03 · 14 min čtení

Embeddings

Jak dát slovům souřadnice ve významovém prostoru. Vektory, kosinová podobnost, nejbližší sousedé.

Úvod

Z minulé lekce máme tokeny. Jenže token je pořád jen číslo, ID řádku ve slovníku. Token pivo má třeba číslo 472 a token hospoda číslo 9000. A pro model jsou ta dvě čísla úplně cizí, stejně jako 472 a 473. Žádný vztah, žádná blízkost, nic. Přitom my víme, že pivo a hospoda k sobě patří.

Potřebujeme slovům dát čísla, která něco říkají o jejich významu. Ne jedno číslo, ale celý seznam čísel. Tomu seznamu se říká vektor a celému nápadu embedding: každý token dostane svůj vektor a tokeny s podobným významem budou mít podobné vektory.

To je celý trik téhle lekce. Pojďme si ho rozebrat.

Švejk ukazuje na mapu embeddingů, kde se podobné tokeny shlukují u sebe

Slova dostala souřadnice. Švejk hledá, co k čemu patří.

Slovo jako vektor

Vektor je jen seznam čísel. [0.9, 0.1, 0.8] je vektor o třech rozměrech. Můžeš si ho představit jako souřadnice bodu v prostoru: tři čísla, tři osy, jeden bod.

A teď ten nápad: dej každému slovu souřadnice tak, aby slova s podobným významem ležela blízko sebe. pivo kousek od hospoda. regiment kousek od kasárna. A naopak pivo a regiment daleko od sebe, protože spolu nemají moc společného.

Reálné embeddingy mají stovek rozměrů, což si nikdo neumí představit. Ale princip je vidět už na dvou. Tahle mapa má jen dvě osy a každé slovo je jeden bod. Klikni na nějaké a podívej se, kdo mu leží nejblíž:

EmbeddingProjector · mapa slov ze Švejka

Klikni na slovo a zvýrazní se jeho nejbližší sousedé.

pivohospodarumkalichštamgastlejstrorazítkoúřadeskortaarestregimentkasárnabagnetmanévrykanónŠvejkLukášVaněkBalounKatz

Pozn.: souřadnice jsou ilustrativní, ručně rozmístěné do shluků. Skutečné embeddingy mají stovky rozměrů a model si je dopočítá sám.

Všimni si, že se slova sama seskupila do shluků podle kontextu, ve kterém se ve Švejkovi objevují. Hospodská slova v jednom rohu, vojna v druhém, postavy ve třetím. Nikdo je tam neposadil ručně podle významu. Kdyby tyhle souřadnice vznikly z reálného textu, vznikly by z toho, jak se slova používají vedle sebe. A přesně to se v opravdovém modelu děje, jen v mnoha rozměrech najednou.

Odkud se ta čísla berou?

Tady ti je předkládám hotová, ručně rozmístěná, aby mapa hezky vyšla. V reálu si je model najde sám během trénování: začne s náhodnými čísly a postupně je upravuje tak, aby mu pomáhala líp hádat další token. Jak přesně, na to si počkáme do lekce o učení. Zatím stačí vědět, že embeddingy nejsou ručně psané, ale naučené.

Jak změříme „blízkost"

Říkám „blízko" a „daleko", ale jak se to měří u vektorů? Nejčastější míra je kosinová podobnost. Místo vzdálenosti bodů se dívá na úhel mezi dvěma vektory (mezi šipkami z počátku do těch bodů).

Spočítá se takhle:

cos(A,B)=ABAB\text{cos}(A, B) = \frac{A \cdot B}{\lVert A \rVert \, \lVert B \rVert}

V čitateli je skalární součin (vynásob složky po dvojicích a sečti), ve jmenovateli délky obou vektorů (aby na výsledek nezáleželo, jak jsou vektory dlouhé, jen kterým směrem míří). Výsledek je číslo mezi −1 a 1:

  • 1 znamená „míří stejným směrem", tedy hodně podobný význam.
  • 0 znamená „kolmé na sebe", tedy nesouvisí.
  • −1 znamená „přesně opačný směr".

Důležité je to, že kosinová podobnost kouká jen na směr, ne na délku. Slovo použité 1000× a slovo použité 10× můžou mířit stejným směrem a být si plně podobné, i když jejich vektory mají různou velikost.

V kódu

Pojďme to spočítat. Vezmeme pár slov, dáme jim malé ruční vektory a změříme, co je čemu podobné. Klikni Run.

python · pyodide

Koukni na výstup. cos(pivo, hospoda) vyjde skoro 1, protože jejich vektory míří skoro stejným směrem. cos(pivo, regiment) je o dost níž. A nejbližší soused každého slova sedí s tím, co bys čekal: pivo k hospodě, regiment ke kasárnám. Švejk leží někde mezi vším, protože se motá po celé knize.

Tohle je celé jádro vyhledávání podle významu. Když dnešní nástroj „najde podobné dokumenty" nebo „odpoví na otázku z tvých poznámek", pod kapotou často dělá přesně tohle: spočítá vektory a hledá nejbližší sousedy.

Slavný trik: počítání s významy

Když jsou slova vektory, můžeš s nimi počítat. Nejznámější příklad z angličtiny: vezmi vektor slova king, odečti man, přičti woman, a nejbližší soused výsledku je queen. Vektor jako by v sobě nesl složku „královskost" a složku „pohlaví" zvlášť, takže se s nimi dá hýbat.

Nečekej od toho zázraky, u řady dvojic to nevyjde a je v tom dost přitažené za vlasy. Ale jako ukázka, že se v těch číslech opravdu schovává kus struktury významu, je to pořád pěkné.

Cvičení

Cvičení · lekce3-cv1

Spočti kosinovou podobnost vektorů A = [1, 0] a B = [1, 1]. (Zadej jako desetinné číslo.)

Cvičení · lekce3-cv2

Jaká je kosinová podobnost vektorů [1, 0] a [0, 1]? Jsou na sebe kolmé.

Cvičení · lekce3-cv3

Spočti kosinovou podobnost vektorů [2, 1] a [4, 2]. (Pozor na to, co jsme říkali o směru a délce.)

Cvičení · lekce3-cv4

V kódu výš přidej do emb dvě tři vlastní slova s vlastními vektory (klidně od oka) a pusť to. Sedí nejbližší sousedé tvojí intuici, nebo tě něco překvapilo? Napiš sem jednu dvojici.

Shrnutí

  • Token je jen ID. Aby model chápal význam, dáme každému tokenu vektor, což je seznam čísel neboli souřadnice bodu v prostoru.
  • Slova s podobným významem mají podobné vektory a leží blízko sebe. Shluky na mapě vznikají z toho, jak se slova používají vedle sebe.
  • Blízkost měříme kosinovou podobností: cos(A,B)=ABAB\text{cos}(A,B) = \frac{A \cdot B}{\lVert A\rVert\,\lVert B\rVert}. Výsledek je od −1 (opačné) přes 0 (nesouvisí) po 1 (stejný směr).
  • Kosinová podobnost kouká na směr, ne na délku vektoru.
  • Embeddingy nejsou psané ručně, model si je najde sám při trénování.

Co bude příště

Máme slova jako vektory. Teď s nimi potřebujeme něco užitečného spočítat, a od toho je tu neuronová síť.

V Lekci 4 (Neuronka, forward pass) vezmeme vektor na vstupu, prožene ho jedna vrstva čísel a na výstupu dostaneme předpověď dalšího tokenu. Uvidíš, že „vrstva neuronové sítě" je jen maticové násobení plus jedna funkce navrch. Nic, co bys nezvládl ručně na papíře. A přesně to si zkusíme.