Anatomie modelu

Kompletní průchod vrstvami: co se kde počítá a proč.

Co se naučíš: Projdeš celý model vrstvu po vrstvě a budeš vědět, co se kde počítá a kde leží parametry.

11 min čtení + cvičeníNavazuje na:🔬 Transformer po lopatě

V transformeru po lopatě jsi viděl myšlenku. Tady projdeme konkrétní architekturu, jakou dnes používá prakticky každý moderní model, od vstupního tokenu až po pravděpodobnosti na výstupu, s rozměry a s tím, co se v každém kroku doopravdy počítá. Tohle je hranice mezi „umím volat API“ a „rozumím tomu, co pod tím běží“.


🛠️ Tuhle architekturu si můžeš spustit: postav si vlastní model je devadesát řádků NumPy, které se natrénují za sedmnáct sekund.

Rozměry, které uvidíš v každé specifikaci

ZnačkaCo to jeTypická hodnota (model ~7–8 B)
d_modelšířka vektoru, kterým se token reprezentuje4096
n_layerspočet opakovaných bloků32
n_headspočet attention hlav32
n_kv_headspočet hlav pro klíče a hodnoty (u GQA méně)8
head_dimrozměr jedné hlavy, obvykle d_model / n_heads128
d_ffvnitřní šířka feed-forward části~14 336
vocabvelikost slovníku32 000 – 200 000
ctxmaximální délka kontextu8 k – 1 M

Z těchhle čísel se dá spočítat všechno podstatné: velikost modelu, spotřeba paměti i cena jednoho tokenu. K tomu se dostaneme ve čtení specifikace.


Cesta tokenu skrz model

"Paříž"
  │
  ├─ 1. tokenizace            → ID tokenu, např. 15243
  ├─ 2. embedding lookup      → vektor délky d_model (4096 čísel)
  │
  ├─ 3. ┌──────── blok 1 ────────┐
  │     │ RMSNorm               │
  │     │ Multi-head attention  │ ← dívá se na předchozí tokeny
  │     │ + residual            │
  │     │ RMSNorm               │
  │     │ FFN (SwiGLU)          │ ← „přemýšlení“ nad tím, co attention přinesla
  │     │ + residual            │
  │     └───────────────────────┘
  │        ... × n_layers (32×)
  │
  ├─ 4. závěrečná RMSNorm
  ├─ 5. projekce na slovník    → vocab čísel (logits)
  └─ 6. softmax + vzorkování   → další token

Klíčové je, že blok je pořád stejný a jen se opakuje. Model není nic jiného než tenhle sendvič naskládaný třicetkrát až stokrát na sebe.


Vizuálně:

1–2. Od textu k vektoru

Tokenizer (dnes BPE nebo SentencePiece) rozseká text na tokeny a přidělí jim ID. Embedding matice velikosti vocab × d_model je obyčejná vyhledávací tabulka: ID → řádek.

Jeden token = jeden vektor. Věta o 10 tokenech = matice 10 × 4096.

💡 Embedding matice je u malých modelů překvapivě velká část parametrů: 32 000 × 4096 = 131 M. Proto se u některých modelů sdílí se výstupní projekcí (tzv. weight tying).


3a. Attention: co si token přitáhne od ostatních

Pro každý token se z jeho vektoru spočítají tři projekce:

  • Q (query): „co hledám“
  • K (key): „co nabízím“
  • V (value): „co předám, když si mě někdo vybere“

Skóre mezi tokeny je skalární součin Q a K, přeškálovaný a prohnaný softmaxem, výsledkem jsou váhy, kterými se sečtou hodnoty V. Zapisuje se to jako softmax(QKᵀ / √head_dim) · V, ale podstata je: vážený průměr toho, co ostatní tokeny nabízejí.

Dvě věci, které to dělá použitelným:

  • Kauzální maska. Token nesmí vidět do budoucnosti, takže se skóre k pozdějším tokenům nastaví na minus nekonečno. Bez toho by model při tréninku „opisoval“ odpověď.
  • Víc hlav. Projekce se rozdělí na n_heads nezávislých sad a každá počítá vlastní pozornost. Jedna sleduje syntax, jiná koreference, další téma. Výsledky se spojí a promítnou zpět do d_model.

Podrobně, včetně GQA a KV cache, v attention do hloubky.


3b. FFN: kde bydlí většina znalostí

Za attention následuje feed-forward síť aplikovaná na každý token zvlášť:

d_model (4096) → d_ff (14336) → zpět d_model (4096)

Rozšíří vektor do širšího prostoru, tam ho nelineárně zpracuje a zase stáhne. Právě tady leží zhruba dvě třetiny parametrů modelu a s nimi i většina faktických znalostí. Attention rozhoduje odkud brát informace, FFN co si o nich myslet.

Moderní modely tu používají SwiGLU místo jednoduché aktivace, viz normalizace a aktivace.


✍️ Chceš to vidět na číslech? Attention ručně projde celý výpočet na třech tokenech. A transformer v kódu ukáže totéž jako padesát řádků PyTorche.

3c. Residual a normalizace

Kolem attention i FFN vede residual spojení: výstup se přičte ke vstupu, ne že by ho nahradil.

x = x + attention(norm(x))
x = x + ffn(norm(x))

Bez residualu by hluboká síť nešla natrénovat, gradienty by cestou zpět zmizely. Díky němu si můžeš celý model představit jako postupné dopisování poznámek do jednoho sešitu: každá vrstva do reprezentace tokenu něco přidá, nic nepřepíše. Tomuhle „sešitu“ se říká residual stream a je to nejužitečnější mentální model, jaký si o transformeru můžeš udělat.


4–6. Z vektoru zpátky na slovo

Poslední vrstva vydá pro každou pozici vektor d_model. Projekce na slovník ho převede na vocab čísel (logits), skóre pro každý možný další token. Softmax z nich udělá pravděpodobnosti a vzorkovač jeden vybere, podle parametrů.

⚠️ Model počítá logits pro každou pozici, ale při generování tě zajímá jen ta poslední. Zbytek se zahodí. Při tréninku se naopak využijí všechny, proto je trénink efektivnější na jeden průchod než generování.


Kolik to má parametrů

Hrubý rozpad pro model 7 B (per vrstva):

attention (s GQA, 8 KV hlav):
  W_Q: d_model × d_model                  = 4096 × 4096      ≈ 17 M
  W_O: d_model × d_model                  = 4096 × 4096      ≈ 17 M
  W_K: d_model × (n_kv_heads × head_dim)  = 4096 × 1024      ≈  4 M
  W_V: totéž                                                 ≈  4 M
                                                    celkem   ≈ 42 M

FFN (SwiGLU, tři matice):
  3 × d_model × d_ff = 3 × 4096 × 14336                      ≈ 176 M

                                        celkem ≈ 218 M na vrstvu
× 32 vrstev                                    ≈ 7,0 mld
+ embeddingy (128k × 4096)                     ≈ 0,53 mld
+ výstupní projekce (pokud není sdílená)       ≈ 0,53 mld

Vidíš dvě věci, které se hodí mít v hlavě: FFN je přes 80 % parametrů vrstvy a hloubka násobí všechno.

⚠️ Pozor na časté zjednodušení „attention = 4 × d_model²“. To platí jen pro plné MHA. S GQA jsou matice K a V mnohem menší (n_kv_heads × head_dim místo d_model), takže attention vyjde zhruba na 42 M místo 67 M a podíl FFN ještě povyroste.

💡 Weight tying: některé modely sdílejí embedding matici s výstupní projekcí (je to táž transformace, jen opačným směrem). U malého modelu s velkým slovníkem to ušetří stovky milionů parametrů; velké modely to dnes spíš nedělají, protože kapacita navíc se vyplatí.


Co se změnilo proti roku 2017

Původní transformer měl encoder i decoder, normalizaci za blokem, absolutní sinusoidální pozice a ReLU. Dnešní model je decoder-only, s normalizací před blokem, RoPE pozicemi, RMSNorm, SwiGLU a bez bias členů. Proč se každá z těch změn ujala, rozebírá vývoj 2017 → 2026.


Cvičení

  1. U modelu s d_model 4096 a FFN šířkou 14336 spočítej, kolik procent parametrů vrstvy leží v attention a kolik ve feed-forward části (attention s GQA, 32 hlav, 8 KV hlav, head_dim 128).
  2. Proč se residual přičítá k nenormalizovanému vstupu, když se před blok dává normalizace?
Náčrt řešení: rozbal, až si cvičení zkusíš sám
  1. Attention 19 %, FFN 81 %. Attention: 2 × 4096² + 2 × 4096 × 1024 = 41 943 040. FFN se SwiGLU: 3 × 4096 × 14336 = 176 160 768. Dohromady 218 103 808, takže attention tvoří necelou pětinu. To je dobré mít v hlavě, protože attention se o sobě mluví mnohem víc, ale parametry, a tím i většina paměti a výpočtu, leží jinde.
  2. Aby zůstala nepřerušená cesta od vstupu k výstupu. Kdyby se přičítal normalizovaný vstup, každá vrstva by residual stream pronásobila normalizací a gradient by se přes desítky vrstev zeslaboval. Takhle vede od embeddingu až k výstupu čistá sčítací dálnice, do které jednotlivé bloky jen přispívají. Viz normalizace a aktivace.

Shrnutí

  • Model = embedding → N× (norm → attention → residual → norm → FFN → residual) → norm → logits.
  • Attention rozhoduje, odkud brát informace; FFN drží většinu parametrů i znalostí.
  • Residual stream je „sešit“, do kterého každá vrstva přidává, nikdy nepřepisuje.
  • Z rozměrů d_model, n_layers, d_ff, vocab spočítáš velikost i paměťové nároky.
Ve které části transformerového bloku leží většina parametrů a co z toho plyne?

Ve feed-forward síti, zhruba dvě třetiny. Attention rozhoduje, odkud se informace berou, ale FFN je místo, kde je uložená většina naučených znalostí. Proto zvětšování d_ff zvedá kapacitu modelu rychleji než přidávání attention hlav.

K čemu slouží kauzální maska a co by se stalo bez ní?

Zabraňuje tokenu vidět pozdější tokeny. Bez ní by model při tréninku mohl „opisovat“ budoucí text, naučil by se predikci triviálně a při generování, kde budoucnost neexistuje, by selhal.

Proč se říká, že vrstvy do reprezentace tokenu „dopisují“, místo aby ji přepisovaly?

Kvůli residual spojení: výstup každé podvrstvy se ke vstupu přičítá. Vzniká tak residual stream, do kterého jednotlivé vrstvy postupně přidávají informace a díky němu jde natrénovat i síť o desítkách či stovkách vrstev.