La vale: Gradient Descent și cei doi pași pe care îi sare toată lumea
Calculează plafonul exact al ratei de învățare, apoi vezi cum o căutare brută pe 3.600 de direcții redescoperă gradientul.
Pe această pagină
Capitolul precedent s-a încheiat cu o vale.
Nu una metaforică: o curbă reală, pierderea reprezentată în funcție de un singur parametru, coborând și apoi urcând la loc. Iar pierderea de sub ea nu a fost aleasă fiindcă era comodă — a fost derivată dintr-o afirmație despre zgomotul din măsurători, iar eroarea pătratică a ieșit la celălalt capăt ca o consecință, nu ca o convenție.
Așadar avem un peisaj cu un fund și un motiv să credem că fundul este locul potrivit. Ce nu avem este o cale de a ajunge acolo.
Capitolul acesta construiește una, iar acesta este algoritmul care antrenează fiecare model din restul cursului — absolut fiecare, fără excepție, până la și inclusiv cele cu sute de miliarde de parametri. Încape în aproximativ douăzeci de linii. Cele două părți grele nu sunt în acele douăzeci de linii și sunt cele două lucruri pe care aproape orice explicație le sare:
- De ce semnul minus. Actualizarea scade gradientul. Fiecare tutorial îl scrie; foarte puține spun de ce gradientul este direcția care merge în sus, singurul fapt care face ca semnul minus să fie altceva decât un act de credință.
- Cât de mare este pasul. „Prea mare diverge, prea mic este lent” este adevărat și inutil. Există un număr exact, se poate calcula din pierdere, iar capitolul acesta îl calculează de două ori — o dată pentru o parabolă de jucărie și o dată pentru datele reale.
Configurarea și de ce nu poți pur și simplu să cauți
Link către secțiunea: Configurarea și de ce nu poți pur și simplu să cauțiReformulat astfel încât capitolul să stea pe picioarele lui: cele opt piese de pe banda transportoare din Capitolul 1, dar cu o altă întrebare. Nu acceptă sau respinge — asta revine mai târziu — ci prezice greutatea unei piese din lățimea ei.
import numpy as np
WIDTH = np.array([18.0, 19.5, 20.2, 21.0, 24.0, 25.5, 23.0, 26.0])
WEIGHT = np.array([47.0, 52.0, 49.0, 55.0, 61.0, 66.0, 70.0, 58.0])
x = WIDTH - WIDTH.mean() # 22.15 mm
y = WEIGHT - WEIGHT.mean() # 57.25 gMăsurătorile sunt centrate, exact ca în Capitolul 1 și dintr-un motiv care revine cu dobândă înainte ca acest capitol să se termine. Modelul este o dreaptă, , iar pierderea este eroarea pătratică medie derivată în capitolul precedent:
Doi parametri. De ce să nu încercăm pur și simplu multe valori? Hai chiar să o facem — o grilă de la la și de la la , în pași de :
grid 501 x 1001 = 501,501 evaluations in 3.67 s
best found: a = 2.1000, b = -0.0000, L = 24.592450O jumătate de milion de evaluări ca să fixezi două numere la două zecimale — iar acea secundă este timpul de ceas pe o mașină, deci o rerulare ajunge oriunde între trei și șase; numărul de evaluări și minimul sunt partea care se reproduce. Gradient descent, la finalul acestui capitol, obține patru zecimale în opt pași și răspunsul float64 complet în treizeci și șase.
Dar viteza nu este argumentul, iar acesta este punctul care decide întregul curs. Căutarea pe grilă costă evaluări pentru parametri la valori fiecare. Cu o mie de valori pe axă:
| model | parametri | evaluări pe grilă |
|---|---|---|
| această dreaptă | 2 | |
| rețeaua XOR din Capitolul 5 | 9 | |
| o rețea multilayer mică | 20.000 |
Al treilea rând nu este un număr mare, este unul fără sens — există aproximativ atomi în universul observabil. Căutarea nu devine mai lentă pe măsură ce modelele cresc; încetează să mai existe. Tot ce urmează există din cauza acelui tabel.
O derivată este o măsurătoare pe care o poți face
Link către secțiunea: O derivată este o măsurătoare pe care o poți faceFixează pentru o clipă, astfel încât să existe un singur parametru și o singură curbă, imaginea cu care te-a lăsat capitolul trecut. Ia un punct de pe ea, , și întreabă: dacă împing ușor cu o cantitate mică , cât se mișcă pierderea, pe unitate de împingere?
Raportul acela este o creștere peste deplasare — panta dreptei care trece prin două puncte de pe curbă. Pe măsură ce se micșorează, cele două puncte alunecă unul spre celălalt și dreapta devine tangenta. Panta ei este derivata : rata cu care pierderea se schimbă pe unitate de schimbare în . Nu o aproximare a ceva și nu o cantitate infinit de mică. O limită a unor rapoarte obișnuite.
Merită rulat, fiindcă numerele spun ceva ce definiția nu spune:
def loss1(a):
return np.mean((a * x - y) ** 2)
for h in [1.0, 1e-2, 1e-4, 1e-6, 1e-8, 1e-10, 1e-12, 1e-14]:
q = (loss1(1.0 + h) - loss1(1.0)) / h
print(f"h = {h:<8.0e} slope estimate = {q:.10f} error = {abs(q + 16.385):.3e}")h = 1e+00 slope estimate = -8.9400000000 error = 7.445e+00
h = 1e-02 slope estimate = -16.3105500000 error = 7.445e-02
h = 1e-04 slope estimate = -16.3842555001 error = 7.445e-04
h = 1e-06 slope estimate = -16.3849925556 error = 7.444e-06
h = 1e-08 slope estimate = -16.3850003787 error = 3.787e-07
h = 1e-10 slope estimate = -16.3850444324 error = 4.443e-05
h = 1e-12 slope estimate = -16.3851154866 error = 1.155e-04
h = 1e-14 slope estimate = -17.0530256582 error = 6.680e-01Aici se întâmplă două lucruri și ambele susțin tot restul.
Eroarea nu este vag proporțională cu — este exact . Împarte la o sută, eroarea se împarte la o sută, la patru cifre semnificative de fiecare dată. Constanta aceea nu este decor: este jumătate din a doua derivată a pierderii și este prima apariție a unei idei de peste două secțiuni — că o curbă, aproape de un punct, arată ca o dreaptă plus o corecție proporțională cu .
Și apoi tiparul se rupe. Sub estimarea devine mai proastă, iar la este greșită la a doua cifră. Nu s-a întâmplat nimic matematic; s-a întâmplat cutia floating-point din capitolul trecut. și coincid în primele zece cifre, scăderea lor distruge acele cifre, iar împărțirea dezastrului la un număr minuscul amplifică ce rămâne. Există un cel mai bun — aici în jur de , aproximativ rădăcina pătrată a epsilonului mașinii — iar a merge mai jos nu înseamnă mai atent, ci mai puțin atent. Ține minte asta; o funcție de la finalul capitolului depinde de ea.
Panta exactă, din calcul, nu din măsurare, este . Deci putem opri măsurarea și putem începe derivarea.
Compoziția și regula lanțului
Link către secțiunea: Compoziția și regula lanțuluiIată ideea pe care se sprijină restul cursului, formulată o dată, simplu.
A compune două funcții înseamnă să o alimentezi pe una cu cealaltă: . Nimic mai mult.
O rețea profundă nu este ca o compoziție. Este una. Un strat este o funcție; stivuirea straturilor înseamnă compunerea lor; „adâncimea” este numărul de funcții din lanț. Când Capitolul 5 construiește o rețea, construiește și nimic altceva. Ceea ce înseamnă că, pentru scopurile noastre, cea mai importantă regulă a calculului este cea care derivează o compoziție:
Ratele se înmulțesc. Dacă se schimbă de trei ori mai repede decât , iar se schimbă de două ori mai repede decât , atunci se schimbă de șase ori mai repede decât . Acesta este tot conținutul și acesta este motivul pentru care un semnal care trece înapoi prin zece straturi este înmulțit cu zece numere — motiv pentru care Capitolul 6 petrece o secțiune pe ce se întâmplă când toate acele numere sunt puțin mai mici decât unu.
Folosește-o pe pierderea noastră. Scrie reziduul , astfel încât . Fiecare depinde de prin funcția internă , a cărei derivată este . Regula lanțului, termen cu termen:
Simbolurile acelea curbate marchează o derivată parțială: derivezi în raport cu o variabilă și le tratezi pe toate celelalte ca pe constante. Nu se întâmplă nimic nou — este aceeași limită ca înainte, luată de-a lungul unei axe. Adună derivatele parțiale într-un vector și ai gradientul:
În punctul , acel vector este . Două numere. Întrebarea este ce înseamnă ele, iar acesta este primul pas pe care îl sare toată lumea.
De ce gradientul arată în sus
Link către secțiunea: De ce gradientul arată în susGradientul este un vector de pante de-a lungul axelor. Atât am demonstrat. Nu este evident — nu ar trebui să fie evident — că asamblarea lor într-un vector produce ceva care arată într-o anumită direcție.
Așa că definim lucrul pe care chiar îl vrem. Alege un vector unitar , o direcție. Derivata direcțională este rata cu care pierderea se schimbă când mergi în direcția aceea:
Regula lanțului transformă asta în ceva calculabil. Mersul de-a lungul lui schimbă cu rata și cu rata , iar contribuțiile se adună:
Rata de schimbare în orice direcție este produsul scalar dintre gradient și acea direcție. Iar acum poanta, care este o singură linie de geometrie. Scriind produsul scalar cu unghiul dintre vectori,
fiindcă are lungimea 1. Singurul lucru pe care îl controlezi este , care este maxim la și minim la o jumătate de întoarcere, grade. Deci:
- Urcarea cea mai abruptă este de-a lungul lui însuși, iar panta de acolo este exact .
- Coborârea cea mai abruptă este de-a lungul lui , iar panta de acolo este .
- Perpendicular pe gradient, pierderea nu se schimbă deloc. De aceea liniile unei hărți de contur intersectează gradientul în unghi drept.
Acesta este semnul minus. Nu o convenție, nu o inversare de semn aleasă de cineva: direcția celei mai rapide scăderi este gradientul negativ fiindcă este minimizat la o jumătate de întoarcere și din niciun alt motiv.
Fiindcă aceasta este o afirmație despre toate direcțiile, testeaz-o pe toate direcțiile. Eșantionează 3.600 dintre ele, una la fiecare zecime de grad, și măsoar-o pe fiecare printr-o mică împingere:
theta = np.array([1.0, 4.0])
g = grad(theta)
print("gradient ", g)
print("its length ", np.linalg.norm(g))
print("its angle ", np.degrees(np.arctan2(g[1], g[0])) % 360, "degrees")
best = max(
((loss(theta + 1e-6 * u) - loss(theta - 1e-6 * u)) / 2e-6, np.degrees(ang))
for ang, u in (
(a, np.array([np.cos(a), np.sin(a)])) for a in np.arange(3600) * 2 * np.pi / 3600
)
)
print("steepest slope", best[0], "at", best[1], "degrees")gradient [-16.385 8. ]
its length 18.23371122399386
its angle 153.97598928042032 degrees
steepest slope 18.233709624837502 at 154.0 degreesO căutare care nu știe nimic despre gradient, pe 3.600 de direcții, își găsește cea mai abruptă urcare la 154,0 grade — direcția proprie a gradientului, în limita rezoluției de 0,1 grade a căutării. Iar panta pe care o găsește acolo, 18,2337, este lungimea gradientului la șase cifre. Teorema nu este o poveste despre ce înseamnă gradientele; este un fapt măsurabil, iar aceasta este măsurătoarea.
De ce un pas mic la vale chiar ajută
Link către secțiunea: De ce un pas mic la vale chiar ajutăAcum al doilea pas sărit. Știm încotro este jos. Nu rezultă că, mergând în acea direcție, pierderea scade, fiindcă „jos” este o afirmație despre o împingere infinitesimală, iar un pas nu este infinitesimal.
Puntea este liniarizarea. Aproape de un punct, o funcție netedă este tangenta ei plus o corecție:
Aceasta este dezvoltarea Taylor de ordinul întâi. Termenul eliminat este curbura — același termen care a făcut ca estimarea din tabelul pantelor să fie greșită exact cu . Pune pasul pe care intenționăm să îl facem, :
Pierderea scade cu . Fiecare parte a expresiei este nenegativă, deci promisiunea este reală — pentru un suficient de mic, fiindcă termenul neglijat crește ca și până la urmă îl înghite. Aceasta este toată teoria. Iată promisiunea respectată și apoi încălcată:
eta = 0.2 promised 66.49364500 delivered -16.01619240 ratio -0.240868
eta = 0.1 promised 33.24682250 delivered 12.61936315 ratio 0.379566
eta = 0.01 promised 3.32468225 delivered 3.11840766 ratio 0.937957
eta = 0.001 promised 0.33246822 delivered 0.33040548 ratio 0.993796
eta = 0.0001 promised 0.03324682 delivered 0.03322620 ratio 0.999380
eta = 1e-05 promised 0.00332468 delivered 0.00332448 ratio 0.999938Citește de jos în sus. Pe măsură ce se micșorează, scăderea livrată converge către cea promisă — raport 0,99938, apoi 0,99994 — adică teorema lui Taylor având dreptate. Citește de sus în jos și, la , „scăderea” livrată este minus șaisprezece. Pasul a mers la vale și pierderea a crescut.
Deci regula de actualizare este
și vine cu o condiție pe care nimeni nu o spune: trebuie să fie suficient de mic. Suficient de mic în comparație cu ce, mai exact, este secțiunea următoare.
Rata de învățare are un plafon și este calculabil
Link către secțiunea: Rata de învățare are un plafon și este calculabilÎncepe cu cea mai simplă vale posibilă, , unde . Un pas de gradient descent este
Poziția este înmulțită cu la fiecare pas. Aceasta este o progresie geometrică, iar progresiile geometrice au exact o regulă: se micșorează când multiplicatorul este mai mic decât 1 în valoare absolută și cresc altfel. Deci , adică .
Granița este la exact. Nu „în jur de 1”, nu „1 este de obicei prea mare”. La multiplicatorul este , iar punctul sare între și la nesfârșit, nici apropiindu-se, nici scăpând. Sub ea converge; peste ea diverge. Intervalul se împarte din nou la , unde multiplicatorul își schimbă semnul: sub acel punct apropierea este monotonă, peste el punctul depășește minimul și alternează părțile, iar exact la multiplicatorul este 0 și un singur pas aterizează pe minim.
Patru regimuri, din patru linii de algebră. Du-te și treci singur granițele:
Și acum cazul interesant:
Acum regula generală, care iese din același argument. Multiplicatorul era de fapt , iar aproape de un minim o pierdere cu mai mulți parametri are câte un astfel de număr pe direcție — valorile proprii ale matricei derivatelor de ordinul doi. Fiecare direcție trebuie să fie stabilă simultan, deci plafonul este stabilit de cea mai mare:
Pentru , , plafon 1, exact ce tocmai am derivat. Pentru banda noastră, matricea derivatelor de ordinul doi este cu matricea cu două coloane a intrărilor, iar valorile ei proprii sunt 2 și 14,89, deci plafonul este . Aceasta este o predicție cu cinci cifre semnificative. Testeaz-o:
lr=0.1343 -> L = 24.5924
lr=0.13431 -> L = 24.5924
lr=0.13432 -> L = 4707.8 BLEW UP
lr=0.13433 -> L = 4.00452e+16 BLEW UP
lr=0.1344 -> L = 1.18229e+107 BLEW UPCinci zecimale de acord între o linie de algebră liniară și o sută de mii de iterații ale unei bucle for.
Și aici revine Capitolul 1. Tot ce e mai sus a folosit măsurătorile centrate. Rulează codul identic pe milimetri și grame brute, iar valorile proprii sunt 0,0298 și 998,1 în loc de 2 și 14,89. Plafonul se prăbușește de la 0,134 la 0,002004 — la fel de exact, convergând la lr=0.002003 și explodând la lr=0.002004.
Mai rău decât plafonul este raportul dintre valorile proprii. Numărul de condiționare măsoară cât de departe de rotundă este valea: un șanț lung și subțire forțează o rată suficient de mică pentru pereții abrupți, iar apoi podeaua șanțului este parcursă cu aceeași târâre. Al nostru trece de la 7,44 centrat la 33.452 brut. Cu cea mai bună rată pe care o poate lua fiecare versiune:
| caracteristici | număr de condiționare | cea mai bună rată | pași până la 1% de optim |
|---|---|---|---|
| centrate | 7,44 | 0,1184 | 10 |
| milimetri și grame brute | 33.452 | 0,0020037 | 79.513 |
Aceleași date, același cod, același răspuns la final — și de opt mii de ori mai multă muncă, fiindcă nimeni nu a scăzut o medie. În Capitolul 1, aceeași omisiune a costat perceptronul un factor de șase mii în epoci, iar diagnosticul de acolo era geometric: datele pluteau departe de origine. Este aceeași geometrie aici, într-un costum de optimizare, și de aceea normalizarea input-ului nu este sfat de igienă, ci aritmetică.1
Douăzeci de linii
Link către secțiunea: Douăzeci de liniiNimic de mai sus nu a avut nevoie de o bibliotecă. Iată întregul optimizator.
def loss(theta):
a, b = theta
return np.mean((a * x + b - y) ** 2)
def grad(theta):
a, b = theta
residual = a * x + b - y
return np.array([np.mean(2 * residual * x), np.mean(2 * residual)])
def descend(theta, lr, steps):
theta = np.array(theta, dtype=float)
for _ in range(steps):
theta = theta - lr * grad(theta)
return theta
theta = descend([0.0, 0.0], lr=0.05, steps=60)
print(theta, loss(theta))[ 2.10040296e+00 -2.76445533e-15] 24.592448791134984Răspunsul în formă închisă al celor mai mici pătrate pentru aceste opt puncte este , , cu o pierdere de . Bucla l-a găsit la opt cifre semnificative fără să știe că există o formă închisă — ceea ce contează, fiindcă din Capitolul 5 mai departe nu va exista una.
Traiectoria, fiindcă scopul este să o vezi:
0 a=0.000000 b=0.000000 L=57.437500
1 a=1.563750 b=0.000000 L=26.736582
2 a=1.963288 b=-0.000000 L=24.732418
5 a=2.098116 b=-0.000000 L=24.592488
10 a=2.100400 b=-0.000000 L=24.592449
60 a=2.100403 b=-0.000000 L=24.592449Cea mai mare parte a distanței este acoperită în primii doi pași, fiindcă gradientul este cel mai mare când ești cel mai departe de fund și se micșorează pe măsură ce te apropii. Gradient descent încetinește automat lângă un minim. Este o facilitate și este, în Capitolul 6, și o problemă.
Unde mai este panta zero
Link către secțiunea: Unde mai este panta zeroArgumentul de până acum are o gaură. Pasul se oprește când , iar noi am tot numit asta „minimul”. Un punct cu gradient zero este un punct critic, iar a fi minim este doar una dintre modalitățile de a fi unul:
- un minim local: în urcare în toate direcțiile, dar posibil să nu fie cel mai jos astfel de punct de oriunde;
- un maxim local: în coborâre în toate direcțiile;
- un punct șa: în urcare în unele direcții și în coborâre în altele. Suprafața are , care este zero în origine, unde funcția este un minim de-a lungul axei și un maxim de-a lungul axei în același timp.
Gradient descent nu le poate deosebi, fiindcă se uită doar la gradient, iar gradientul este zero în toate trei.
Dreapta noastră are un singur punct critic și acesta este răspunsul — o pierdere cu eroare pătratică peste un model liniar este convexă, un singur bol, iar descent pe ea nu poate rata minimul global. Această proprietate nu supraviețuiește contactului cu acest curs. Pierderea unei rețele neuronale nu este convexă, iar din Capitolul 5 mai departe „minimul” nu este un lucru care există: sunt multe, de adâncimi diferite, iar care dintre ele îți iese depinde de unde ai pornit. Aceasta este o propoziție și rămâne o propoziție, fiindcă teoria este mare, iar consecința practică este mică.
Poți vedea întreaga consecință pe o singură curbă. Ia , care are două văi de adâncimi diferite:
x = -1.046681 f(x) = -0.352386 minimum
x = 0.101031 f(x) = 0.005026 maximum
x = 0.945649 f(x) = -0.152639 minimumA ateriza în valea superficială este cu 56,7% mai rău ca pierdere, iar algoritmul nu are de unde să știe, fiindcă din interiorul unei văi orice direcție este în urcare. Nu există reparație pentru asta în gradient descent și nici nu vine una. Ce există, în practică, este constatarea că lucrul acesta contează mult mai puțin decât sugerează imaginea — în dimensiunile foarte înalte ale unei rețele reale, majoritatea punctelor critice se dovedesc a fi șei, nu capcane,2 iar Capitolul 5 măsoară cât de des se blochează de fapt o rețea mică.
Pași mai ieftini: stochastic, minibatch, momentum
Link către secțiunea: Pași mai ieftini: stochastic, minibatch, momentumUn lucru despre grad de mai sus ar trebui să te deranjeze: însumează peste întregul set de date la fiecare pas. Opt piese nu înseamnă nimic. Un milion înseamnă un milion de calcule de gradient ca să miști parametrii o singură dată.
Scăparea este că gradientul este o medie, iar o medie poate fi estimată dintr-un eșantion. Calculeaz-o pe un pumn aleatoriu — un minibatch — și fă pasul pe aceea. Estimarea este zgomotoasă; este și ne-biasată, iar sute de pași zgomotoși ieftini bat un pas exact scump. Pe o sută de mii de piese sintetice, numărând gradiente pe exemplu, nu pași:
| metodă | pași până la 0,1% de optim | gradiente pe exemplu |
|---|---|---|
| full batch | 7 | 700.000 |
| minibatch de 32 | 100 | 3.200 |
| câte un exemplu | 17.580 | 17.580 |
De două sute nouăsprezece ori mai puțină aritmetică pentru a ajunge în același loc. Iar extrema — câte un exemplu, aproximarea stochastic originală a lui Robbins și Monro3 — nu este câștigătoarea: este de cinci ori mai proastă decât batch-urile de 32, fiindcă 32 de exemple nu costă aproape nimic mai mult decât unul pe hardware care înmulțește matrici, în timp ce zgomotul scade cu rădăcina pătrată a dimensiunii batch-ului. Acest compromis este motivul pentru care fiecare script de antrenare pe care îl vei citi vreodată are un batch_size în el.
Momentum este cealaltă remediere ieftină și țintește direct șanțul. Într-o vale prost condiționată, pașii fac zigzag peste direcția îngustă în timp ce se târăsc de-a lungul celei lungi. Momentum păstrează o medie curentă a gradientelor trecute, astfel încât componentele oscilante se anulează și cea consistentă se acumulează:4
Două linii în plus. Pe banda brută necentrată — număr de condiționare 33.452, cel mai rău caz pe care îl avem — la cea mai bună rată pe care o poate lua descent simplu:
momentum beta=0.0 -> 79,513 steps to 1%
momentum beta=0.9 -> 1,609 steps to 1%
momentum beta=0.99 -> 461 steps to 1%Un factor de 172 pentru două linii de cod. Capitolul 6 transformă asta în Adam; mecanismul este deja aici.
Verificarea de care vei avea nevoie în Capitolul 5
Link către secțiunea: Verificarea de care vei avea nevoie în Capitolul 5Fiecare gradient din acest capitol a fost derivat de mână și, prin urmare, putea fi greșit. Remediul este tabelul pantelor de la început: măsoară derivata numeric și compară. Folosește diferența centrală, , care anulează termenul principal de eroare și este mult mai precisă pentru același .
def numeric_grad(f, theta, h=1e-5):
theta = np.asarray(theta, dtype=float)
out = np.zeros_like(theta)
for i in range(theta.size):
bump = np.zeros_like(theta)
bump[i] = h
out[i] = (f(theta + bump) - f(theta - bump)) / (2 * h)
return out
def gradcheck(f, df, theta, h=1e-5):
analytic = np.asarray(df(theta), dtype=float)
numeric = numeric_grad(f, theta, h)
return np.max(np.abs(analytic - numeric) / np.maximum(1e-8, np.abs(analytic) + np.abs(numeric)))Forma relativă a comparației contează: o diferență absolută de este un dezastru pe un gradient de mărime și irelevantă pe unul de mărime .
relative error: 1.8929136036763527e-11
with 2 dropped: 0.33333333331650744Prima linie este gradientul derivat de mână de mai sus. A doua este aceeași funcție cu factorul 2 omis dintr-o componentă — o greșeală de un singur caracter — iar verificarea o prinde imediat. Orice sub aproximativ înseamnă acord; orice peste este un bug. Păstrează această funcție: Capitolul 5 o folosește pentru a depana un motor de diferențiere automată și este singurul motiv pentru care un gradient greșit poate fi găsit.
Încotro merge totul
Link către secțiunea: Încotro merge totulTotul în acest capitol s-a sprijinit pe o presupunere care nu a fost niciodată enunțată: că poți scrie .
Pentru o dreaptă cu doi parametri, asta a fost o linie de algebră. Încetează să mai fie una aproape imediat. Cere unui sistem de algebră simbolică derivata pierderii unei rețele în raport cu o singură pondere din primul strat, pentru un singur exemplu, și numără aritmetica din răspuns:
| rețea | operații într-o derivată parțială |
|---|---|
| patru unități ascunse, un strat | 40 |
| patru unități ascunse, două straturi | 301 |
| patru unități ascunse, trei straturi | 1.717 |
Al treilea rând este o rețea cu 57 de parametri — o rețea atât de mică încât ar fi o notă de subsol în Capitolul 6 — iar scrierea gradientului ei de mână înseamnă aproximativ 97.869 de operații pentru un singur exemplu de antrenare. Nu există notație care să salveze asta. Ce o salvează este observația că regula lanțului aplicată unei compoziții are o structură enormă, că aceleași cantități intermediare apar iar și iar, iar calcularea lor în ordinea potrivită obține toate derivatele la aproximativ prețul unui forward pass. Acesta este Capitolul 5.
Dar mai întâi există o problemă mai mică, care așteaptă imediat.
Avem acum o mașină care va rostogoli la vale pe orice pierdere diferențiabilă. Îndreapt-o către întrebarea originală a benzii — acceptă sau respinge, o țintă care este 1 sau 0 — pune un sigmoid pe ieșire ca să prezică o probabilitate și minimizează eroarea pătratică. Va rula. Dar abia se va mișca tocmai când greșește cel mai mult, iar gradientul spune de ce:
| ieșire | predicție | adevăr | gradient cu eroare pătratică | gradient cu cross-entropy |
|---|---|---|---|---|
| 0.5000 | 1 | |||
| 0.1192 | 1 | |||
| 0.0025 | 1 | |||
| 1 |
Un model care greșește încrezător, catastrofal — prezicând 0,0000454 când răspunsul este 1 — produce un gradient cu eroare pătratică de . Nu are idee că are probleme. Cealaltă coloană, dintr-o pierdere pe care încă nu am derivat-o, raportează 1,0: urgență maximă, exact acolo unde este meritată.
Ceea ce ridică întrebarea cu care se deschide capitolul următor. Capitolul trecut a spus că o pierdere este o presupunere despre zgomot, iar eroarea pătratică presupune zgomot gaussian. Ce model de zgomot are un răspuns da-sau-nu — și ce pierdere iese când rulezi aceeași derivare pe el?
Surse și metodă
Link către secțiunea: Surse și metodăMetoda este mai veche decât toate acestea: Cauchy a descris-o într-o notă către Académie des Sciences în 1847, ca mod de a rezolva sisteme de ecuații mergând la vale pe suma reziduurilor lor pătratice. Merită citite alături de acest capitol și: An overview of gradient descent optimization algorithms de Sebastian Ruder (arXiv:1609.04747), care acoperă momentum până la Adam în paisprezece pagini lizibile; capitolul 3 din Numerical Optimization de Nocedal și Wright (ed. a 2-a, Springer, 2006), a cărui teoremă 3.3 dă rata de convergență a steepest descent pe o cuadratică în funcție de numărul de condiționare — teoria din spatele motivului pentru care condiționarea decide numărul de pași, deși tratează line search, nu plafonul cu pas fix măsurat mai sus; sau §5.8 și §7.1 din Mathematics for Machine Learning de Deisenroth, Faisal și Ong pentru același teren cu mai puțină mașinărie; §6.1 din Understanding Deep Learning de Prince și §4.3 din Deep Learning de Goodfellow, Bengio și Courville; Dive into Deep Learning §12.1–12.3, care are analiza minibatch cu mai multe măsurători decât încape aici; și capitolul 4 din Hands-On Machine Learning de Géron (ed. a 3-a), cel mai practic tratament al ratei de învățare ca lucru pe care îl ajustezi, nu îl derivezi. Notele MIT 6.390 pun gradient descent înaintea clasificării, așa cum face acest curs și din același motiv.
Referințe
Link către secțiunea: Referințe-
LeCun, Y., Bottou, L., Orr, G. B. și Müller, K.-R. Efficient BackProp, în Neural Networks: Tricks of the Trade (Springer, 1998), pp. 9–50. Secțiunea 4.3 dă recomandarea, iar secțiunea 5.1 argumentul folosit în caseta de detalii de mai sus: centrarea și scalarea intrărilor schimbă valorile proprii ale matricei derivatelor de ordinul doi și, prin urmare, numărul de pași, nu doar confortul numeric. ↩
-
Dauphin, Y. N., Pascanu, R., Gulcehre, C., Cho, K., Ganguli, S. și Bengio, Y. Identifying and attacking the saddle point problem in high-dimensional non-convex optimization, arXiv:1406.2572 (2014). Argumentul că în dimensiuni înalte punctele critice sunt covârșitor șei, nu minime locale, deoarece un minim cere ca fiecare dintre miile de direcții să se curbeze în sus simultan. ↩
-
Robbins, H. și Monro, S. A Stochastic Approximation Method. Annals of Mathematical Statistics 22(3), pp. 400–407 (1951). Lucrarea care a stabilit că o estimare zgomotoasă a unui gradient este suficientă, dacă dimensiunea pasului scade în modul potrivit. ↩
-
Polyak, B. T. Some methods of speeding up the convergence of iteration methods. USSR Computational Mathematics and Mathematical Physics 4(5), pp. 1–17 (1964). Metoda heavy-ball, care este actualizarea cu momentum de mai sus, cu douăzeci și doi de ani înainte ca backpropagation să ajungă în acest domeniu. ↩