Var Gradienttoppar Kommer Från
En Lugn Mini-Batch & en Chockerande En
De flesta mini-batches producerar gradienter med rimliga magnituder. Cross-entropy-förlust för en modell som redan ungefär passar datan håller sig i ett smalt band; backprop bär tillbaka den signalen som gradienter av liknande storlek.
Vissa mini-batches gör det inte. Tre källor till gradienttoppar:
1. Outlier-exempel. En enda sekvens med en extremt sällsynt tokenkombination producerar en förlust långt från medelvärdet & en gradient långt från medelvärdet.
2. Numeriska kantfall. En nära-noll softmax-denominator, en layernorm som producerar NaN, en FP16-overflow. Var och en kan producera gradienter av flera magnituder större än typiska.
3. Distributionsskift. Byte av datakällor under en enda träningsrunda chockar modellen med en ny distribution. ANDREA's bandit omblandar källvikter var 7 till 42 steg. Varje byte är ett litet distributionsskift.
ANDREA-120M v1: Spike-kaskad
v1 hade ingen gradientklippning. Källövergångar var 7 till 42 steg från banditen matade modellen korta burst av repo-docs (liststrukturerad), sedan gutenberg (lång prosa), sedan hermes3-general (Q&A). Varje övergång producerade gradienttoppar: varje topp tryckte vikterna in i degenerativa attraktorer i 120M-skala.
Viktig empirisk fakta. ANDREA-12M överlevde samma bandit utan klippning. Mindre viktmatriser förblir robusta mot gradientstötar; en enda dålig batch kan inte driva 12M parametrar in i en okontrollerbar attractor på samma sätt som den kan driva 120M. Klippning blir viktigare ju större modellen blir.
Global L2-normklippning
Två val: Per-tensor eller global
Två sätt att begränsa gradientstorlekar:
Per-tensor-klippning. Klipp varje gradienttensor oberoende. Embedding-gradienten klipps till sin egen norm; attention-gradienten klipps till sin egen norm. Enkelt, men förvränger relativa skalor: en liten spik i en tensor (nu noll gradient) paras med en enorm gradient i en annan (orörd).
Global L2-normklippning. Behandla alla gradienter som en stor vektor. Beräkna den totala L2-normen över alla parametrar. Om normen överstiger max_norm, skala varje gradient med samma faktor. Bevarar relativa storlekar över tensorer.
ANDREA använder global. Pascanu et al. (2013) visade empiriskt att global clipping överträffar per-tensor för transformerträning.
Matematiken
Beräkna den globala L2-normen:
norm = sqrt(summa över alla parametrar av g_i^2)
Om norm <= max_norm, passerar gradienterna oförändrade. Om norm > max_norm, skala varje gradient med max_norm / norm:
g_i_clipped = g_i * (max_norm / norm)
Efter skalning blir den nya normen exakt max_norm. ANDREA använder max_norm = 1.0.
Beräkna en skalningsfaktor
Varför gradientnormberäkning behöver tre kärnor
Den naiva algoritmen kan inte köras på en GPU
Pseudokod för global L2-normberäkning:
total = 0
för varje parameter p:
för varje element g i p.grad:
total += g * g
norm = sqrt(total)
På en GPU misslyckas denna naiva loop av två anledningar:
1. Sekventiell ackumulation. En enda total-ackumulator tvingar varje tråd att vänta på varje annan tråd, vilket motverkar GPU-parallellism.
2. Heterogena tensorer. ANDREA-120M har tensorer med kraftigt olika former: embedding (8449 x 768), attention QKV (768 x 768), layernorm (768). En kernel kan inte effektivt iterera alla former.
ANDREA:s tre-kernels-pipeline
Dela upp arbetet i tre CUDA-kernels i microgpt_cuda.cu:
Kernel 1: k_grad_norm_partial. För varje parametertensor, beräkna en partiell summa av kvadrater. Varje trådblock reducerar en bit av tensoren; resultaten skrivs till en liten skrapbuffer. Parallellism: ett block per bit, hundratals block över alla tensorer.
Kernel 2: k_grad_norm_final. Reducera scratch-buffern till en enda skalär. Ta dess kvadratrots. En liten kernel, körs på mikrosekunder.
Kernel 3: k_grad_scale. Om norm > max_norm, beräkna scale = max_norm / norm & multiplicera varje gradient-element med scale. En genomgång över varje gradient-tensor, pinsamt parallell.
Ordningsföljden är viktig: Pre-Adam
Klippnings-pipelinen körs FÖRE AdamW uppdaterar m, v eller någon parameter. Varför?
Klippade gradienter matar AdamW:s exponentiella glidande medelvärden. Om en spik fick flöda in i m & v, skulle det korrumpera de löpande medelvärdena & sakta ner återhämtningen i många steg efter spiken. Klippning före Adam håller spikens effekt begränsad till det enda dåliga steget.
Varför tre kernels, inte en?
Hur No-Clipping Dödade v1
Bandit Source Transitions Varje 7 till 42 Steg
ANDREA:s bandit arbetar i faser. Varje fas varar 7, 14, 21, 28 eller 42 steg (valda slumpmässigt). Vid varje fasgräns skiftar source-vikterna: kanske repo-docs hoppar från 0.1 till 0.6, gutenberg sjunker från 0.4 till 0.1, hermes3-general stiger från 0.5 till 0.7.
Varje övergång är en distributionschock för modellen. Förlusten spikar kortvarigt. Gradienterna spikar med den: en modell som minimerade förlusten mot gutenberg-smakad prosa ser nu repo-docs-smakade liststrukturer, & gradienterna bär ett korrigerande signal som kan vara 10x eller 100x typisk magnitud.
v1 Felmode
[TITLE andrea/]Utan klippning flödade de 10-100x gradienttopparna in i AdamW:s m & v genomsnitt. AdamW:s utjämning innebar att toppeffekten kvarstod i många steg efter det faktiska dåliga batchen. Kombinerat med ingen viktminskning (vanilla Adam i v1), ackumulerades viktuppdateringar drivna av toppar över faser tills vikterna drev in i en degenererad attractor: en tokens logit dominerade softmax, sampledat utdata var den token, träningskontexten innehöll den token, gradienten förstärkte den token. Repetitionslåsning.
v2 Stabilitet
v2 lade till klippning med max_norm = 1.0, tillsammans med AdamW & LR-uppvärmning. Toppeffekten på m & v är bunden; vikterna kan inte driva snabbare än lr max_norm = 0.0003 1.0 = 0.0003 per parameter per steg vid topp. Fasövergångar producerar fortfarande toppar, men de topparna klipps av innan de når optimizern.
Resultat: v2 (efter datafilter v2.5 & v3-polering) nådde faktisk återkallelse, flerstyckeskoherens, & 9.5/10 externa betyg på biologi- & signalbehandlingsexempel.
Kopplingen Kapacitet-Sprödhet
Samma bandit. Samma data. Samma hyperparametrar förutom klippning. Varför överlevde 12M utan klippning medan 120M kollapsade?
Två sammansatta faktorer:
1. Större viktmatriser lagrar fler attraktorer. En 768x768 attention-projektion har 590K parametrar; även liten drift per parameter producerar meningsfulla förändringar i attention-beteendet. En 384x384 attention-projektion har 147K parametrar & stannar i en mer begränsad delmängd.
2. Fler lager betyder fler multiplikativa interaktioner. v3 har 12 transformerlager (mot 6 för 12M). Spikar propagerar genom 12 lager av sammansatta icke-linjäriteter; varje lager kan förstärka den tidigare lagrets drift.
Skörhet ökar med kapacitet. Klippning blir obligatorisk över en viss skaltröskel; ANDREA placerar den tröskeln någonstans mellan 12M & 120M parametrar.
Diagnostisering av v1-kaskaden
Var annars används klippning?
Relaterade aktiviteter
Tre syskon länkar till clipping:
- Aktivitet 10: AdamW. Clipping skyddar AdamW:s m & v från spik-kontaminering. Utan clipping korrumperar en dålig batch optimizer-tillståndet i 50+ steg.
- Aktivitet 11: LR-uppvärmning. Uppvärmning dämpar lr; clipping dämpar g. Tillsammans: vid steg 1 är den värsta parameteruppdateringen lr_after_warmup max_norm = 1.5e-7 1.0 = 1.5e-7, mot 0.0003 * 50 = 0.015 utan någon av skydden. En 100 000x reduktion i värsta-falls tidig uppdateringsmagnitud.
- Aktivitet 14: Multi-armed bandits. Banditfasens längd (7 till 42 steg) är kort specifikt för att förhindra att någon enskild källa dominerar; klippning är det som gör de frekventa övergångarna säkra.
Klippning är den billigaste stabilitetsvinsten i transformerträning: 3 små CUDA-kärnor, mikrosekunder per steg, avgörande inverkan på om 120M+ modeller konvergerar eller kollapsar.