At få det til at træne — og til at generalisere
Et sekslagsnetværk med loss fast på ln 2, fikset én måling ad gangen. Så double descent: 5.000 parametre på 40 punkter.
På denne side
Netværket fra kapitel 5 virker. Det har ni parametre, det lærer XOR, og dets gradienter stemmer med PyTorch ned til seksten decimaler.
Gør det seks lag dybt, og det holder helt op med at lære. Ikke langsomt — helt. Her er et sekslagsnetværk på et to-spiral-klassifikationsproblem, trænet i 5.000 trin:
step 1: loss 0.693147
step 5000: loss 0.693147
accuracy: 50.0 %Det tal er ikke vilkårligt. er den binære cross-entropy for en model, der outputter sandsynlighed for alt, og 50 % er et møntkast på et balanceret datasæt. Efter fem tusind trin har netværket ikke rykket et eneste ciffer. Intet crashede, intet advarede, og gradienterne er stadig helt rigtige.
Dette kapitel handler om afstanden mellem et netværk, der kører, og et netværk, der virker. Det har to halvdele, der ligner forskellige emner, men er samme arbejde: at få loss til at gå ned, og at få den til at gå ned på data, modellen aldrig har set.
Hvorfor sekslagsnetværket er dødt
Link til afsnittet: Hvorfor sekslagsnetværket er dødtStart med at kigge i stedet for at gætte. Send en batch inputs igennem, og print standardafvigelsen for aktiveringerne ved hvert lag og derefter standardafvigelsen for vægtgradienterne:
def profile(model, x):
h = x
for layer in model:
h = layer(h)
if isinstance(layer, (nn.Tanh, nn.ReLU)):
print(f"activation std: {h.std().item():.4f}")
model(x).sum().backward()
for p in model.parameters():
if p.dim() == 2:
print(f"gradient std: {p.grad.std().item():.2e}")Tre initialiseringer, samme arkitektur, seks lag af :
| initialisering | aktiverings-std, lag 1→6 |
|---|---|
| normal, std | 0,0145 · 0,0016 · 0,0002 · 0,0000 · 0,0000 · 0,0000 |
| normal, std | 0,6573 · 0,9296 · 0,9585 · 0,9634 · 0,9637 · 0,9625 |
| Xavier | 0,1579 · 0,1493 · 0,1353 · 0,1333 · 0,1325 · 0,1403 |
| initialisering | gradient-std, første lag → sidste |
|---|---|
| normal, std | 3,20e-06 · 4,97e-07 · … · 6,40e-06 |
| normal, std | 1,94e+03 · 2,28e+02 · 1,22e+02 · 4,43e+01 · 1,85e+01 · 7,30e+00 |
| Xavier | 2,31e+00 · 4,50e-01 · 4,26e-01 · 3,89e-01 · 4,39e-01 · 4,73e-01 |
Første række er netværket ovenfor, og det lærer ikke langsomt — det har intet signal tilbage. Ved lag fire er aktiveringernes standardafvigelse underflowet til nul med fire decimaler. Hvert input producerer samme output, outputtet er en konstant, og gradienten af en konstant er ingenting. Vægtene blev initialiseret små "for en sikkerheds skyld", og småt var fatalt.
Anden række er den modsatte fejl, og den er værd at forstå, fordi den er kontraintuitiv. Aktiveringerne ser sunde ud — omkring 0,96 — men det er satureret, låst nær sin grænse, præcis det regime kapitel 5 målte som et tab af næsten ti tusind i gradient. Og alligevel er gradienterne enorme: 1.940 ved første lag. Begge ting er sande på én gang. Hvert baglæns trin ganger med , og med 128 inputs ved enhedsvarians har den faktor en gain på cirka , hvilket overdøver krympningen fra den saturerede . Gradienterne vokser geometrisk på vej tilbage. Det er exploding gradient, og det giver loss-værdier på nan inden for få trin i enhver reel træningskørsel.
Tredje række er det, du vil have: aktiveringer omtrent konstante i skala på tværs af dybde, gradienter omtrent konstante i skala på tværs af dybde. Intet dør, intet eksploderer.
Normalisering, og hvilken der overlevede
Link til afsnittet: Normalisering, og hvilken der overlevedeGod initialisering fikser skalaen ved trin nul. Den holder den ikke fast: vægtene flytter sig, og ved trin fem tusind gælder det omhyggelige variansargument ikke længere.
Normaliseringslag håndhæver skalaen løbende. Givet en vektor af aktiveringer trækker du et gennemsnit fra, dividerer med en standardafvigelse og anvender derefter en lært skala og et skift , så laget kan fortryde normaliseringen, hvis det viser sig at være det, det vil:
Det eneste reelle spørgsmål er hvad du tager gennemsnit over. Batch normalization3 tager og på tværs af batch-dimensionen, én statistik pr. feature. Layer normalization4 tager dem på tværs af features, én statistik pr. eksempel.
Det valg ser lille ud og afgør næsten alt længere nede:
BatchNorm gør hvert eksempels output afhængigt af de andre eksempler, der tilfældigvis var i dets batch. Under træning er det en mild regularisator. Ved inference er der ingen batch, så den må holde et løbende gennemsnit af statistikkerne indsamlet under træning — hvilket betyder, at laget opfører sig forskelligt i trænings- og evalueringsmode, og at glemme at skifte mode er en af de mest almindelige bugs i feltet. Det degraderer også med små batches, og det er klodset med sekvenser af variabel længde, fordi "gennemsnittet over batchen ved position 40" beregnes ud fra hvor mange sekvenser der tilfældigvis er så lange.
LayerNorm normaliserer hvert eksempel for sig. Ingen batch-afhængighed, ingen løbende statistikker, identisk adfærd under træning og inference, ligeglad med batch-størrelse, ligeglad med sekvenslængde. Hver eneste af de egenskaber er et krav snarere end en bekvemmelighed, når du genererer én token ad gangen for én bruger, hvilket er der, kapitel 13 ender.
Det er derfor, LayerNorm er den, du møder igen i kapitel 9 uændret: transformer-blokken bruger den, og den bruger den af årsagerne i højre kolonne, ikke fordi den virker bedre i abstrakt forstand.
At fikse én ting ad gangen, hvilket er den egentlige skill
Link til afsnittet: At fikse én ting ad gangen, hvilket er den egentlige skillFire kandidatfix til det døde netværk: Xavier-initialisering, LayerNorm, residual connections og Adam i stedet for SGD. Fristelsen er at anvende alle fire og komme videre. Gør det, og du vil aldrig vide, hvilken der betød noget, og næste gang det sker, har du ingen metode — kun et ritual.
Så anvend dem én ad gangen. Samme seed, samme data, samme arkitektur, 800 trin:
| hvad blev tilføjet | endelig loss | accuracy |
|---|---|---|
| intet | 0,6931 | 50,0 % |
| Xavier-initialisering | 0,5692 | 60,4 % |
| LayerNorm | 0,6230 | 61,5 % |
| residual connections | 0,6651 | 56,6 % |
| Adam | 0,6787 | 58,7 % |
| alle fire | 0,0000 | 100,0 % |
Læs den tabel, som du ville læse den kl. 2 om natten, og konklusionen er: intet virker alene, alt virker sammen, derfor er deep learning alkymi. Den konklusion er forkert, og at finde ud af hvorfor er det mest nyttige i dette kapitel.
Giv hver kørsel seks gange budgettet — 5.000 trin i stedet for 800 — og billedet ændrer sig fuldstændigt:
| hvad blev tilføjet | endelig loss @ 5000 | accuracy |
|---|---|---|
| intet | 0,6931 | 50,0 % |
| Xavier-initialisering | 0,0007 | 100,0 % |
| LayerNorm | 0,0002 | 100,0 % |
| residual connections | 0,6653 | 56,7 % |
| Adam | 0,6908 | 53,4 % |
| Xavier + Adam | 0,0000 | 100,0 % |
| Xavier + LayerNorm | 0,0001 | 100,0 % |
Nu er billedet skarpt, og det er en diagnose snarere end et ritual.
Initialisering alene fikser det. Normalisering alene fikser det. Hver adresserer den egentlige sygdom — at forward-signalet kollapser til nul — og begge er tilstrækkelige. Ved 800 trin lignede de blot delvis kredit, fordi de havde løst problemet og stadig var ved at kravle op igen.
Residual connections og Adam fikser det ikke, uanset budget. Ikke fordi de er dårlige, men fordi de behandler en anden sygdom. En residual connection giver gradienten en vej uden om et blokerende lag; det er meget værd, når gradienten er problemet, og intet værd, når forward-signalet allerede er nul, fordi en genvej uden om et dødt lag stadig bærer en død værdi. Adam skalerer hvert parameters trin efter dets egen gradienthistorik; det hjælper, når gradienter har vildt forskellige størrelser, og kan ikke genoplive et netværk, hvis output ikke afhænger af dets input.
Og "intet" er stadig præcis 0.6931 efter fem tusind trin. Ikke 0,6929. Det er ikke langsomt; det er dødt, og den skelnen er synlig på en måde, den ikke var før, fordi du har rækken, der siger, at et fix virker, at sammenligne med.
At gøre sig fortjent til PyTorch
Link til afsnittet: At gøre sig fortjent til PyTorchHerfra bruger kurset PyTorch. Det bør man gøre sig fortjent til, ikke bare annoncere, så her er præcis, hvad det gør, som du allerede ved, hvordan man gør.
En optimizer er en regel for at omdanne gradienter til parameteropdateringer. Almindelig gradient descent bruger gradienten. Momentum bruger et løbende gennemsnit af den, hvilket udglatter støjen og opbygger fart i retninger, der forbliver konsistente:
v = beta * v + p.grad
p -= lr * v Adam5 holder to løbende gennemsnit — af gradienten og af gradienten kvadreret — og dividerer det ene med kvadratroden af det andet, så hvert parameter får et trin skaleret til sin egen nylige gradientstørrelse:
m = b1 * m + (1 - b1) * g # mean of the gradient
v = b2 * v + (1 - b2) * g * g # mean of the squared gradient
m_hat = m / (1 - b1 ** t) # bias correction: both averages start at zero
v_hat = v / (1 - b2 ** t)
p -= lr * m_hat / (v_hat.sqrt() + eps) Ti linjer. Kør begge mod torch.optim på samme problem i 50 trin:
SGD+momentum by hand [2.7781870365142822, -1.0304985046386719]
torch [2.7781870365142822, -1.0304983854293823] max |diff| = 1.19e-07
Adam by hand [0.4893140196800232, -0.46317872405052185]
torch [0.48931416869163513, -0.46317875385284424] max |diff| = 1.49e-07Identisk til float32-præcision. torch.optim.Adam er de fem linjer plus årtiers omhu omkring edge cases og en C++-kerne. Det er den handel, du laver herfra: ikke magi i bytte for forståelse, men hastighed i bytte for linjer, du allerede har skrevet.
Hvorfor Adam findes: krumning
Link til afsnittet: Hvorfor Adam findes: krumningDen sædvanlige forklaring på Adam er "adaptive per-parameter learning rates", hvilket er en beskrivelse snarere end en årsag. Årsagen er geometri, og den kan måles.
Tag en loss, hvis krumning varierer mellem retninger: stejl i én, flad i en anden. SGD har én global learning rate, så den må vælge en værdi, der er lille nok til at være stabil i den stejleste retning — og den værdi er så alt for lille i den flade, hvor fremskridtet kravler. Det er det, der skaber det klassiske billede af gradient descent, der zigzagger ned gennem en smal dal.
To krumningsforhold, tre optimizers, 300 trin, og hver optimizer får den bedste learning rate fra et sweep, så ingen handicappes:
| krumningsforhold | SGD | SGD + momentum | Adam |
|---|---|---|---|
| 10 : 1 | fejl 0,000002 | fejl 0,000000 | fejl 0,000000 |
| 1000 : 1 | fejl 1,925485 | fejl 0,001432 | fejl 0,000000 |
| divergerede ved (1000:1) | 4 af 8 rates | 4 af 8 rates | 0 af 6 rates |
Ved et forhold på ti virker alt, og der er intet at diskutere. Ved tusind kan almindelig SGD ikke nå svaret ved nogen af de prøvede learning rates — dens bedste resultat er stadig en fejl på 1,93 — og den divergerer direkte ved halvdelen af rates. Adam lander præcis på målet og divergerer ved ingen af dem.
Den sidste kolonne er den praktiske grund til, at Adam er standarden. Det er ikke, at Adam finder bedre løsninger; på velkonditionerede problemer matcher eller slår tunet SGD den ofte. Det er, at Adam er langt mindre følsom over for den learning rate, du valgte, og virkelige netværk har krumningsforhold langt værre end tusind på tværs af deres millioner af parametre.
To stykker mere hører hjemme her, og begge er én linje. Gradient clipping skalerer gradientvektoren om, når dens norm overstiger en tærskel, hvilket gør rækken "loss springer pludseligt til en enorm værdi" i diagnosetabellen til en ikke-begivenhed. Og learning rate schedules: en kort warmup fra næsten nul over de første par hundrede trin, fordi Adams variansestimater er skrald, indtil de har set nogle gradienter, og et fuldt trin taget på skrald kan ødelægge en initialisering; derefter cosine decay mod nul, fordi det at afslutte en kørsel med samme trinstørrelse, som du startede med, betyder at jittere rundt om minimum i stedet for at falde til ro i det.
Anden halvdel: modellen der passer perfekt og forudsiger intet
Link til afsnittet: Anden halvdel: modellen der passer perfekt og forudsiger intetAlt indtil nu handlede om at få loss ned. Nu kommer den sværere halvdel, fordi loss, der går ned, ikke er målet — det er en proxy for målet, og proxyen fejler på en bestemt og berømt måde.
Tolv punkter fra en glat funktion med lidt støj. Fit polynomier af stigende grad:
| grad | train RMSE | test RMSE |
|---|---|---|
| 1 | 0,764499 | 0,6985 |
| 3 | 0,252605 | 0,3031 |
| 5 | 0,164437 | 0,1568 |
| 9 | 0,088960 | 0,2347 |
| 11 | 0,000000 | 1,2094 |
Grad 11 gennem 12 punkter passerer gennem hver eneste ét præcist — train-fejl nul til seks decimaler — og er otte gange værre end grad 5 på data, den ikke har set. Bed grad 3 og grad 11 om at forudsige ved , lige uden for træningsintervallet:
degree 3: predicts -1.053 (truth -0.012)
degree 11: predicts +61.224 (truth -0.012)Enogtres, hvor svaret er cirka nul. Modellen lærte ikke funktionen; den lærte de tolv punkter, og mellem dem gør den, hvad aritmetikken kræver.
Det er overfitting, og dets modsætning — grad 1, som slet ikke kan repræsentere kurven og er dårlig overalt — er underfitting. Den klassiske forklaring opdeler en models forventede fejl i tre dele: bias, fejlen fra at modellen er for rigid til at repræsentere sandheden; variance, fejlen fra at modellen er så fleksibel, at den jagter støjen i netop denne stikprøve; og irreducibel støj, som intet kan fikse. Simple modeller har bias, fleksible modeller har høj variance, og den klassiske forskrift er at finde sweet spot i midten — grad 5 i tabellen ovenfor.
Standardværktøjerne angriber alle variance-leddet:
- L2-regularisering (weight decay) lægger til loss, trækker vægte mod nul og gør funktionen glattere. I tabellen ovenfor gør grad 11's største koefficient skaden; at straffe størrelse afvæbner den.
- L1 lægger til i stedet. Forskellen er ikke kosmetisk: L2's gradient er proportional med vægten og krymper derfor, efterhånden som vægten gør, og nærmer sig nul uden at nå frem, mens L1's gradient er en konstant , der bliver ved med at skubbe hele vejen. L1 producerer derfor vægte, der er præcis nul — den vælger features. L2 producerer små vægte. Brug L2, når du vil have glathed, L1 når du vil have sparsity.
- Dropout7 nulstiller et tilfældigt subset af aktiveringer ved hvert træningstrin, så ingen enhed kan regne med, at en bestemt anden enhed er til stede.
- Early stopping holder øje med validation loss og stopper, når den vender opad.
- Data augmentation fremstiller flere træningseksempler fra dem, du har, hvilket angriber problemet ved kilden: overfitting er lige så meget mangel på data som overskud af parametre.
- Cross-validation splitter data på måder og træner gange, hvilket køber et pålideligt estimat af testfejl, når du har for lidt data til at afsætte et held-out set.
Double descent, eller hvorfor forrige afsnit ikke er hele historien
Link til afsnittet: Double descent, eller hvorfor forrige afsnit ikke er hele historienNu kommer det faktum, der bryder billedet.
Bias-variance-historien siger, at efter sweet spot betyder flere parametre dårligere generalisering. Moderne sprogmodeller har langt flere parametre, end de klassiske regler tillader for de data, de ser, og generaliserer fremragende. Begge udsagn er sande, og at forene dem er det mest nyttige i dette kapitel.
Fyrre træningspunkter, tyvedimensionelle inputs, tilfældige ReLU-features, og antallet af features swept fra 2 til 5.000 — med minimum-norm-løsningen valgt, når der er mange, der passer:
| train RMSE | test RMSE | |||
|---|---|---|---|---|
| 10 | 0,25 | 0,8822 | 1,2520 | 1,89 |
| 20 | 0,50 | 0,5962 | 1,1634 | 2,59 |
| 30 | 0,75 | 0,3896 | 1,5323 | 4,15 |
| 38 | 0,95 | 0,1769 | 3,7163 | 10,25 |
| 40 | 1,00 | 0,0000 | 5,8140 | 14,83 |
| 42 | 1,05 | 0,0000 | 3,1623 | 9,35 |
| 60 | 1,50 | 0,0000 | 1,1058 | 2,78 |
| 200 | 5,00 | 0,0000 | 0,6638 | 0,98 |
| 1500 | 37,50 | 0,0000 | 0,5859 | 0,33 |
| 5000 | 125,00 | 0,0000 | 0,5664 | 0,18 |
Læs det i tre dele. Op til holder den klassiske historie præcist: fejlen falder og begynder så at stige. Ved — interpolation threshold, hvor modellen har præcis nok parametre til at passere gennem hvert træningspunkt — topper testfejlen ved 5,81, fem gange værre end den lille model. Den top er den klassiske advarsel, og den er virkelig.
Så falder den igen. Og den bliver ved med at falde, forbi , forbi , hele vejen til , hvor testfejlen på 0,5664 er bedre end den bedste underparametriserede model nogensinde opnåede. En model med 5.000 parametre fittet til 40 punkter er den bedste model i tabellen.
Det er double descent,89 og mekanismen er synlig i sidste kolonne. Når først , er der uendeligt mange parameterindstillinger, der passer træningsdata præcist, og hvilken du får afhænger af, hvordan du vælger. Minimum-norm-løsningen vælger den mindste, og viser, hvad det betyder: den topper ved 14,83 præcis ved threshold — hvor der er præcis én interpolerende løsning, og du sidder fast med den, hvor ekstrem den end er — og falder derefter monotont, efterhånden som vokser, fordi flere parametre betyder flere interpolerende løsninger at vælge imellem, hvilket betyder, at den mindste tilgængelige bliver mindre. Ved er normen 0,18, firs gange mindre end ved threshold.
Så de ekstra parametre tilføjer ikke kompleksitet. De tilføjer valg, og udvælgelsesreglen bruger det valg på enkelhed. Regulariseringen ligger ikke i loss-funktionen; den ligger i algoritmen. Gradient descent fra en lille initialisering har en dokumenteret bias mod små-norm-løsninger, hvilket er grunden til, at denne adfærd viser sig i virkelige netværk trænet på den almindelige måde og ikke kun i lineær algebra ovenfor.
Den praktiske konsekvens, som kapitel 10 afhænger af: "modellen har flere parametre end data, så den vil overfitte" er ikke et gyldigt argument. Det var en god regel, da modeller levede til venstre for threshold. Alt interessant lever nu langt til højre for den, hvor reglen vender.
Hvor det går hen nu
Link til afsnittet: Hvor det går hen nuVærktøjerne i dette kapitel er nok til at træne et netværk, der virker på data, du kan lægge i en tabel: rækker af tal, en kolonne med labels.
Sprog er ikke det. Før en model kan forudsige næste ord, skal noget beslutte, hvad et "ord" overhovedet er — og svaret er hverken bogstaver eller ord, men et vocabulary, modellen lærer fra træningsdataenes rå bytes. Den beslutning, taget én gang før træningen starter, bestemmer hvor mange ting modellen kan sige, hvor meget en request koster, og hvorfor modeller, der kan bestå en juraeksamen, ikke pålideligt kan tælle bogstaverne i strawberry.
Kapitel 7 bygger en tokenizer.
Kilder og metode
Link til afsnittet: Kilder og metodeFor de residual connections, der bruges ovenfor, se He et al., Deep Residual Learning for Image Recognition (arXiv:1512.03385). Andrej Karpathys Building makemore Part 3: Activations & Gradients, BatchNorm gennemgår aktiveringshistogram-diagnostikken på en virkelig model og er den bedste hands-on behandling af første halvdel af dette kapitel. Yaser Abu-Mostafas Learning From Data-forelæsninger 8 og 11–13 giver den klassiske generaliseringsteori ordentligt, inklusive de dele, dette kapitel komprimerede til ét afsnit.
Referencer
Link til afsnittet: Referencer-
Glorot, X. og Bengio, Y. Understanding the difficulty of training deep feedforward neural networks. AISTATS (2010). Variansbevaringsargumentet gengivet i boksen ovenfor. ↩
-
He, K., Zhang, X., Ren, S. og Sun, J. Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification. arXiv:1502.01852 (2015). ↩
-
Ioffe, S. og Szegedy, C. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. arXiv:1502.03167 (2015). Bemærk, at forklaringen om "internal covariate shift" i titlen siden er blevet væsentligt anfægtet; laget virker, men den oprindelige forklaring på hvorfor er omstridt. ↩
-
Ba, J. L., Kiros, J. R. og Hinton, G. E. Layer Normalization. arXiv:1607.06450 (2016). ↩
-
Kingma, D. P. og Ba, J. Adam: A Method for Stochastic Optimization. arXiv:1412.6980 (2014). ↩
-
Loshchilov, I. og Hutter, F. Decoupled Weight Decay Regularization. arXiv:1711.05101 (2017). ↩
-
Srivastava, N., Hinton, G., Krizhevsky, A., Sutskever, I. og Salakhutdinov, R. Dropout: A Simple Way to Prevent Neural Networks from Overfitting. JMLR 15, s. 1929–1958 (2014). ↩
-
Belkin, M., Hsu, D., Ma, S. og Mandal, S. Reconciling modern machine-learning practice and the classical bias–variance trade-off. PNAS 116(32), s. 15849–15854 (2019). Artiklen, der gav fænomenet navn. ↩
-
Nakkiran, P., Kaplun, G., Bansal, Y., Yang, T., Barak, B. og Sutskever, I. Deep Double Descent: Where Bigger Models and More Data Hurt. arXiv:1912.02292 (2019). Viser effekten i virkelige deep networks og langs training time-aksen såvel som modelstørrelsesaksen. ↩