Normalizace a aktivace

Pre-norm, RMSNorm, SwiGLU, residual a proč zrovna takhle.

Co se naučíš: Budeš vědět, proč se normalizuje před blokem a ne za ním, a proč to rozhoduje o hloubce modelu.

7 min čtení + cvičeníNavazuje na:🏗️ Anatomie modelu

Detaily, které vypadají jako kosmetika, a přitom rozhodují o tom, jestli se model o stovkách vrstev vůbec natrénuje. Tři změny proti roku 2017, pre-norm, RMSNorm a SwiGLU, dnes najdeš prakticky v každém modelu. Tahle kapitola vysvětlí, proč se ujaly.


Pre-norm vs. post-norm

Původní transformer normalizoval až za podvrstvou:

post-norm (2017):  x = Norm(x + attention(x))
pre-norm (dnes):   x = x + attention(Norm(x))

Rozdíl je zásadní. U pre-norm vede čistá cesta od vstupu k výstupu přes samé sčítání, residual stream neprochází žádnou normalizací. Gradient tak doteče až dolů i u stovky vrstev.

Post-norm modely nad zhruba dvanáct vrstev vyžadovaly opatrné rozehřívání learning rate a stejně byly nestabilní. Pre-norm se trénuje samo. Cena: mírně horší výsledná kvalita při stejné velikosti, což se řeší tím, že si můžeš dovolit víc vrstev.


Rozdíl je jen v pořadí dvou operací a rozhoduje o tom, jestli se 80vrstvý model vůbec natrénuje. U pre-norm vede od vstupu k výstupu nepřerušená sčítací cesta, po které gradient projde bez zeslabení. U post-norm ho každá vrstva pronásobí, což se přes desítky vrstev nasčítá do exploze nebo do nuly.


LayerNorm → RMSNorm

LayerNorm odečte průměr, vydělí směrodatnou odchylkou a pak přeškáluje naučenými parametry (gain, bias).

RMSNorm vynechá odečítání průměru i bias, jen vydělí odmocninou z průměru druhých mocnin a přeškáluje.

LayerNorm: (x − mean) / std × g + b
RMSNorm:    x / rms(x) × g

Ukázalo se, že centrování na nulu nic podstatného nepřináší, zatímco stojí výpočet i paměť. RMSNorm je o něco rychlejší, jednodušší a numericky stabilnější a modely s ním trénují stejně dobře. Proto ho dnes používá téměř každý.

💡 Ze stejného soudku: moderní modely vynechávají bias členy v lineárních vrstvách. Nic neztratí, ušetří parametry a zjednoduší to distribuovaný trénink.


ReLU → GELU → SwiGLU

Aktivace je nelinearita ve feed-forward části. Bez ní by celý model zkolaboval do jediné lineární transformace.

ReLU (max(0, x)) je nejjednodušší a nejrychlejší, ale tvrdě usekává.

GELU je hladší varianta, okolo nuly propouští malé záporné hodnoty. Ujala se v GPT-2 a spol.

SwiGLU je dnešní standard a funguje jinak: FFN se rozdělí na dvě větve, jedna slouží jako „brána“ (gate), která tu druhou násobí.

klasické FFN:  W₂ · aktivace(W₁ · x)
SwiGLU:        W₃ · ( swish(W₁ · x)  ⊙  (W₂ · x) )
                        brána         obsah

Model se tak učí nejen co propustit, ale i kolik z toho. V praxi to dává lepší výsledky při stejném počtu parametrů, je tam ale háček: SwiGLU potřebuje tři matice místo dvou, takže se d_ff obvykle zmenší zhruba na dvě třetiny, aby počet parametrů zůstal stejný.

Právě proto uvidíš u modelů podivná čísla jako d_ff = 14336 místo hezkých 16384.


Proč na tom záleží v praxi

  • Při čtení specifikace poznáš generaci modelu: RMSNorm + SwiGLU + RoPE + bez biasů = moderní architektura řady LLaMA a jejích následovníků.
  • Při kvantizaci je normalizace citlivé místo, normalizační vrstvy a embeddingy se často nechávají v plné přesnosti, i když zbytek je ve 4 bitech.
  • Při vlastním trénování nebo fine-tuningu je pre-norm důvod, proč ti to vůbec konverguje bez šamanských triků s learning rate.

Kam dál

Jak se residual chová při zpětném průchodu, rozvádí loss a gradient a backprop ručně. Celý blok i s těmito prvky v kódu najdeš v transformeru v kódu, a co se stane, když normalizace chybí, v kapitole když se trénink pokazí.


Cvičení

  1. Vezmi vektor [3, −1, 2, 0] a spočítej ručně, co z něj udělá RMSNorm s gainem samých jedniček.
  2. Proč se u post-norm modelů muselo dělat pečlivé zahřívání learning rate a u pre-norm to přestalo být kritické?
Náčrt řešení: rozbal, až si cvičení zkusíš sám
  1. Výsledek je [1,64, −0,55, 1,10, 0]. Nejdřív střední kvadratická hodnota: (9 + 1 + 4 + 0) / 4 = 3,5, odmocnina 1,871. Pak se každá složka vydělí: 3 / 1,871 = 1,60, −1 / 1,871 = −0,53, 2 / 1,871 = 1,07, 0. Drobné rozdíly proti uvedeným číslům dělá epsilon ve jmenovateli. Všimni si, že se nic neodečítá: RMSNorm na rozdíl od LayerNormu neodstraňuje střední hodnotu, jen mění délku vektoru.
  2. Protože u post-norm gradient prochází normalizací v každé vrstvě a na začátku tréninku snadno exploduje. Zahřívání drží první kroky malé, dokud se aktivace neusadí. Pre-norm nechává residual stream čistý, gradient teče přímo, a trénink je proto od začátku výrazně stabilnější. Zahřívání se používá dál, ale už není tím, co rozhoduje mezi „natrénuje se“ a „diverguje“.

Shrnutí

  • Pre-norm nechává residual stream čistý, a proto jdou trénovat velmi hluboké modely.
  • RMSNorm vypustil centrování i bias, levnější, stabilnější, stejně dobrý.
  • SwiGLU používá bránu, která reguluje, kolik informace projde; proto má FFN tři matice.
  • Kombinace pre-norm + RMSNorm + SwiGLU + RoPE je dnešní společný jmenovatel skoro všech modelů.
Proč se přešlo od post-norm k pre-norm?

Protože u pre-norm vede residual stream od vstupu k výstupu bez normalizace, takže gradient doteče i přes desítky až stovky vrstev. Post-norm modely byly u větších hloubek nestabilní a vyžadovaly opatrné rozehřívání learning rate.

V čem se RMSNorm liší od LayerNorm a proč se vyplatil?

Vynechává odečtení průměru i bias, jen škáluje podle odmocniny z průměru druhých mocnin. Ukázalo se, že centrování na nulu nepřináší měřitelný přínos, zatímco stojí výpočet, takže RMSNorm je rychlejší a jednodušší při stejné kvalitě.

Proč mají moderní modely d_ff jako 14336 místo kulatých hodnot?

Kvůli SwiGLU, který potřebuje tři matice místo dvou. Aby počet parametrů zůstal srovnatelný s klasickým FFN, zmenší se vnitřní šířka zhruba na dvě třetiny a vyjdou z toho právě takováhle nekulatá čísla.