Lejtmenet: gradient descent, és a két lépés, amit mindenki kihagy
Számold ki a tanulási ráta pontos felső határát, majd nézd meg, ahogy 3.600 irány brute-force keresése újra felfedezi a gradientet.
Ezen az oldalon
Az előző fejezet egy völggyel zárult.
Nem metaforikussal: egy tényleges görbével, ahol a veszteséget egyetlen paraméter függvényében ábrázoltuk, lefelé hajló, majd újra emelkedő formában. És az alatta lévő veszteséget nem azért választottuk, mert kényelmes volt — a mérések zajáról tett állításból vezettük le, és a négyzetes hiba következményként jött ki a végén, nem konvencióként.
Van tehát egy tájunk aljjal, és okunk azt hinni, hogy az alj a megfelelő hely. Ami nincs, az egy módszer, amellyel eljutunk oda.
Ez a fejezet megépít egyet, és ez az algoritmus tanítja be a kurzus további részében szereplő összes modellt — mindegyiket, kivétel nélkül, egészen a több száz milliárd paraméteresekig bezárólag. Nagyjából húsz sorban elfér. A két nehéz rész nincs benne abban a húsz sorban, és pontosan ez az a két dolog, amit szinte minden magyarázat kihagy:
- Miért a mínuszjel. A frissítés kivonja a gradientet. Minden tutorial leírja; nagyon kevés mondja el, miért a gradient az az irány, amely felfelé mutat — márpedig csak ez teszi a mínuszjelet bármi mássá, mint hittétellé.
- Mekkora legyen a lépés. A „túl nagy divergens, túl kicsi lassú” igaz és haszontalan. Van egy pontos szám, kiszámítható a veszteségből, és ez a fejezet kétszer is kiszámítja — egyszer egy játék-parabolára, egyszer pedig a tényleges adatokra.
A felállás, és miért nem lehet egyszerűen keresni
Link a szakaszhoz: A felállás, és miért nem lehet egyszerűen keresniÚjrafogalmazva, hogy ez a fejezet önmagában is megálljon: a 1. fejezet szállítószalagjáról származó nyolc alkatrész, de más kérdéssel. Nem elfogadni vagy elutasítani — az később visszatér —, hanem megjósolni egy alkatrész tömegét a szélességéből.
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 gA mérések középre vannak igazítva, pontosan úgy, mint az 1. fejezetben, és olyan okból, amely kamatostul visszatér, mielőtt ez a fejezet véget ér. A modell egy egyenes, , a veszteség pedig az előző fejezetben levezetett átlagos négyzetes hiba:
Két paraméter. Miért ne próbálnánk ki sok értéket? Tegyük is meg — egy rács és , illetve és között, -es lépésekkel:
grid 501 x 1001 = 501,501 evaluations in 3.67 s
best found: a = 2.1000, b = -0.0000, L = 24.592450Félmillió kiértékelés két szám két tizedesjegyre való belövéséhez — és az a másodperc falióra-idő egy gépen, ezért egy újrafuttatás három és hat között bárhol landolhat; a kiértékelések száma és a minimum az, ami reprodukálható. A gradient descent a fejezet végén nyolc lépésben négy tizedesjegyet kap, harminchatban pedig a teljes float64 választ.
De nem a sebesség az érv, és ez az a pont, amely az egész kurzust eldönti. A rácskeresés költsége kiértékelés paraméterre, tengelyenként értékkel. Tengelyenként ezer értékkel:
| modell | paraméterek | rácskiértékelések |
|---|---|---|
| ez az egyenes | 2 | |
| az 5. fejezet XOR-hálózata | 9 | |
| egy kis többrétegű hálózat | 20.000 |
A harmadik sor nem nagy szám, hanem értelmetlen — a megfigyelhető univerzumban nagyjából atom van. A keresés nem lassabb lesz, ahogy a modellek nőnek; megszűnik létezni. Minden, ami ezután jön, emiatt a táblázat miatt létezik.
A derivált egy mérés, amit el tudsz végezni
Link a szakaszhoz: A derivált egy mérés, amit el tudsz végezniRögzítsük értékét egy pillanatra, hogy egy paraméter és egy görbe maradjon — ez az a kép, amelyet az előző fejezet rád hagyott. Vegyünk rajta egy pontot, , és kérdezzük meg: ha értékét egy kis mennyiséggel elmozdítom, mennyit mozdul a veszteség, az elmozdítás egységére vetítve?
Ez az arány egy emelkedés osztva futással — a görbe két pontján átmenő egyenes meredeksége. Ahogy zsugorodik, a két pont összecsúszik, és az egyenes érintővé válik. Ennek meredeksége a derivált : az a ráta, amellyel a veszteség változik egységnyi változására. Nem valaminek a közelítése, és nem végtelenül kicsi mennyiség. Közönséges arányok határértéke.
Érdemes lefuttatni, mert a számok olyasmit mondanak, amit a definíció nem:
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-01Két dolog történik itt, és mindkettő teherhordó.
A hiba nem homályosan arányos értékével — pontosan . Oszd el értékét százzal, a hiba is százzal osztódik, minden alkalommal négy értékes jegyre. Ez a konstans nem dísz: a veszteség második deriváltjának fele, és annak az ötletnek az első megjelenése, amely két szakasszal később jön — hogy egy görbe egy pont közelében úgy néz ki, mint egy egyenes plusz egy -val arányos korrekció.
Aztán a minta megtörik. alatt a becslés rosszabb lesz, és értéknél már a második jegyben téved. Matematikailag semmi nem történt; az előző fejezet lebegőpontos doboza történt. és az első tíz számjegyükben egyeznek, kivonásuk elpusztítja ezeket a jegyeket, és a roncs nagyon kicsi számmal való osztása felerősíti, ami marad. Van egy legjobb — itt körülbelül , nagyjából a gépi epsilon négyzetgyöke —, és ennél kisebbre menni nem óvatosabb, hanem kevésbé az. Ezt jegyezd meg; a fejezet végén egy függvény ettől függ.
A pontos meredekség, kalkulusból és nem mérésből, . Így abbahagyhatjuk a mérést, és elkezdhetünk levezetni.
Kompozíció és a láncszabály
Link a szakaszhoz: Kompozíció és a láncszabályItt van az ötlet, amelyre a kurzus további része épül, egyszer, világosan kimondva.
Két függvény komponálása azt jelenti, hogy az egyiket a másikba etetjük: . Semmi több.
Egy mély hálózat nem olyan, mint egy kompozíció. Az az. Egy réteg egy függvény; rétegek egymásra rakása azok komponálása; a „mélység” a láncban lévő függvények száma. Amikor az 5. fejezet hálózatot épít, -t épít, és semmi mást. Ez azt jelenti, hogy a kalkulus számunkra legfontosabb szabálya az, amely egy kompozíciót differenciál:
A ráták szorzódnak. Ha háromszor olyan gyorsan változik, mint , és kétszer olyan gyorsan változik, mint , akkor hatszor olyan gyorsan változik, mint . Ez a teljes tartalom, és ezért szorzódik egy tíz rétegen visszafelé haladó jel tíz számmal — ezért szán a 6. fejezet egy szakaszt arra, mi történik, ha ezek a számok mind kicsit kisebbek egynél.
Használjuk a veszteségünkre. Írjuk fel a reziduálist , hogy . Minden függ -től a belső függvényen keresztül, amelynek deriváltja . Láncszabály, tagonként:
Ezek a kacskaringós szimbólumok parciális deriváltat jelölnek: egy változó szerint differenciálsz, minden mást konstansként kezelve. Semmi új nem történik — ugyanaz a határérték, mint korábban, csak egy tengely mentén véve. Gyűjtsd a parciális deriváltakat egy vektorba, és megkapod a gradientet:
A pontban ez a vektor . Két szám. A kérdés az, mit jelentenek, és ez az első lépés, amit mindenki kihagy.
Miért mutat a gradient felfelé
Link a szakaszhoz: Miért mutat a gradient felfeléA gradient a tengelyek menti meredekségek vektora. Ennyit bizonyítottunk. Nem nyilvánvaló — nem is kellene annak lennie —, hogy ezek vektorba rendezése bármilyen konkrét irányba mutató dolgot eredményez.
Definiáljuk tehát azt, amit valójában akarunk. Válassz egy egységvektort , egy irányt. Az iránymenti derivált az a ráta, amellyel a veszteség változik, miközben arra sétálsz:
A láncszabály ezt kiszámíthatóvá teszi. mentén sétálva rátával, pedig rátával változik, a hozzájárulások pedig összeadódnak:
A változás rátája bármely irányban a gradient és az adott irány skalárszorzata. És most a csattanó, ami egy sor geometria. A skalárszorzatot a vektorok közötti szöggel felírva,
mivel hossza 1. Az egyetlen dolog, amit irányítasz, , amely -nál a legnagyobb, és fél fordulatnál, foknál a legkisebb. Tehát:
- A legmeredekebb emelkedés maga mentén van, és a meredekség ott pontosan .
- A legmeredekebb ereszkedés mentén van, és a meredekség ott .
- A gradientre merőlegesen a veszteség egyáltalán nem változik. Ezért metszi egy szintvonalas térkép vonalait a gradient derékszögben.
Ez a mínuszjel. Nem konvenció, nem valaki által választott előjelcsere: a leggyorsabb csökkenés iránya a negatív gradient, mert fél fordulatnál minimális, és semmi másért.
Mivel ez minden irányra vonatkozó állítás, teszteljük minden irány ellen. Mintavételezzünk 3.600-at, tizedfokonként egyet, és mérjük meg mindet egy kis elmozdítással:
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 degreesEgy keresés, amely semmit sem tud a gradientekről, 3.600 irányon át a legmeredekebb emelkedést 154,0 foknál találja — a gradient saját irányában, a keresés 0,1 fokos felbontásán belül. És a meredekség, amelyet ott talál, 18,2337, hat értékes jegyre a gradient hossza. A tétel nem történet arról, mit jelentenek a gradientek; mérhető tény, és ez a mérés.
Miért segít tényleg egy kis lépés lefelé
Link a szakaszhoz: Miért segít tényleg egy kis lépés lefeléMost a második kihagyott lépés. Tudjuk, merre van lefelé. Ebből nem következik, hogy arra sétálva csökken a veszteség, mert a „lefelé” végtelenül kicsi elmozdításról szóló állítás, a lépés pedig nem végtelenül kicsi.
A híd a linearizálás. Egy sima függvény egy pont közelében az érintője plusz egy korrekció:
Ez az elsőrendű Taylor-kifejtés. Az elhagyott a görbület — ugyanaz a tag, amely a meredekségtáblázat becslését pontosan -val tévesztette el. Tegyük be a lépést, amelyet meg akarunk tenni, :
A veszteség -val csökken. Ennek minden része nemnegatív, tehát az ígéret valós — elég kicsi esetén, mert az elhanyagolt tag szerint nő, és végül felfalja. Ez a teljes elmélet. Íme az ígéret betartva, majd megszegve:
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.999938Olvasd lentről. Ahogy zsugorodik, a tényleges csökkenés konvergál az ígérthez — 0,99938-as, majd 0,99994-es arány —, vagyis Taylor tétele helyes. Olvasd fentről, és -nél a tényleges „csökkenés” negatív tizenhat. A lépés lefelé ment, a veszteség pedig nőtt.
A frissítési szabály tehát
és jár hozzá egy feltétel, amelyet senki nem mond ki: legyen elég kicsi. Elég kicsi pontosan mihez képest — ez a következő szakasz.
A learning rate-nek van felső határa, és kiszámítható
Link a szakaszhoz: A learning rate-nek van felső határa, és kiszámíthatóKezdjük a lehető legegyszerűbb völggyel, , ahol . A gradient descent egy lépése
A pozíció minden lépésben -tel szorzódik. Ez geometriai sorozat, a geometriai sorozatoknak pedig pontosan egy szabályuk van: akkor zsugorodnak, ha a szorzó abszolút értékben kisebb 1-nél, különben nőnek. Tehát , ami .
A határ pontosan -nál van. Nem „körülbelül 1”, nem „az 1 általában túl nagy”. -nél a szorzó , és a pont örökké és között pattog, se nem közeledik, se nem szökik el. Alatta konvergál; felette divergens. Az intervallum újra kettéhasad -nál, ahol a szorzó előjelet vált: alatta a közeledés monoton, felette a pont túllő, és felváltva kerül a másik oldalra, pontosan -nél pedig a szorzó 0, és egyetlen lépés a minimumra ér.
Négy rezsim, négy sor algebrából. Menj, és lépd át a határokat magad:
És most az érdekes:
Most az általános szabály, amely ugyanebből az érvből esik ki. A szorzó valójában volt, és egy minimum közelében egy többparaméteres veszteségnek irányonként van egy ilyen száma — a második deriváltak mátrixának sajátértékei. Minden iránynak egyszerre kell stabilnak lennie, ezért a plafont a legnagyobb állítja be:
esetén , a plafon 1, amit az imént levezettünk. A szalagunknál a második deriváltak mátrixa , ahol a bemenetek kétoszlopos mátrixa, sajátértékei pedig 2 és 14,89, ezért a plafon . Ez öt értékes jegyű előrejelzés. Teszteljük:
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 UPÖt tizedesjegynyi egyezés egy sor lineáris algebra és egy for ciklus százezer iterációja között.
És itt tér vissza az 1. fejezet. Fent minden a középre igazított méréseket használta. Futtasd ugyanezt a kódot nyers millimétereken és grammokon, és a sajátértékek 2 és 14,89 helyett 0,0298 és 998,1 lesznek. A plafon 0,134-ről 0,002004-re omlik össze — ugyanilyen pontosan, lr=0.002003-nél konvergálva és lr=0.002004-nél felrobbanva.
A plafonnál is rosszabb a sajátértékek közötti arány. A kondíciószám azt méri, mennyire nem kerek a völgy: egy hosszú, vékony árok olyan rátát kényszerít ki, amely elég kicsi a meredek falakhoz, majd az árok alján is ugyanilyen csigatempóban halad. A miénk középre igazítva 7,44-ről nyersen 33.452-re megy. A legjobb rátával, amelyet az egyes verziók elviselnek:
| jellemzők | kondíciószám | legjobb ráta | lépések az optimum 1%-án belülre |
|---|---|---|---|
| középre igazítva | 7,44 | 0,1184 | 10 |
| nyers milliméterek és grammok | 33.452 | 0,0020037 | 79.513 |
Ugyanazok az adatok, ugyanaz a kód, ugyanaz a válasz a végén — és nyolcezerszer annyi munka, mert senki nem vont ki átlagot. Az 1. fejezetben ugyanez a mulasztás hatezerszeres szorzóba került a perceptron epochjaiban, és ott a diagnózis geometriai volt: az adatok messze lebegtek az origótól. Itt ugyanez a geometria optimalizálási jelmezben, és ezért a bemenet-normalizálás nem higiéniai tanács, hanem aritmetika.1
Húsz sor
Link a szakaszhoz: Húsz sorA fentiekhez nem kellett könyvtár. Itt a teljes optimalizáló.
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.592448791134984A zárt alakú legkisebb négyzetes válasz erre a nyolc pontra , , veszteséggel. A ciklus nyolc értékes jegyre megtalálta anélkül, hogy tudta volna, létezik zárt alak — ami fontos, mert az 5. fejezettől kezdve nem lesz ilyen.
A pálya, mert a lényeg az, hogy nézzük:
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.592449A távolság nagy részét az első két lépés fedezi le, mert a gradient akkor a legnagyobb, amikor a legtávolabb vagy az aljtól, és zsugorodik, ahogy közeledsz. A gradient descent automatikusan lelassul egy minimum közelében. Ez egy feature, és a 6. fejezetben egyben probléma is.
Hol nulla még a meredekség
Link a szakaszhoz: Hol nulla még a meredekségAz eddigi érvben van egy lyuk. A lépés akkor áll meg, amikor , és ezt eddig „a minimumnak” neveztük. A nulla gradientű pont kritikus pont, és a minimum csak az egyik módja annak, hogy valami kritikus pont legyen:
- lokális minimum: minden irányban felfelé van, de nem feltétlenül ez a legalacsonyabb ilyen pont bárhol;
- lokális maximum: minden irányban lefelé van;
- nyeregpont: egyes irányokban felfelé, másokban lefelé van. A felületnél , ami az origóban nulla; ott a függvény a -tengely mentén minimum, a -tengely mentén pedig maximum ugyanabban az időben.
A gradient descent nem tudja megkülönböztetni ezeket, mert mindig csak a gradientet nézi, és a gradient mindháromnál nulla.
Az egyenesünknek egyetlen kritikus pontja van, és az a válasz — egy lineáris modell négyzetes hibájú vesztesége konvex, egyetlen tál, és a descent rajta nem hibázhatja el a globális minimumot. Ez a tulajdonság nem éli túl a kurzussal való találkozást. Egy neurális hálózat vesztesége nem konvex, és az 5. fejezettől kezdve „a minimum” nem létező dolog: sok van belőle, különböző mélységűek, és hogy melyiket kapod, attól függ, honnan indultál. Ez egy mondat, és egy mondat is marad, mert az elmélet nagy, a gyakorlati következmény pedig kicsi.
Az egész következményt egy görbén láthatod. Vedd -t, amelynek két különböző mélységű völgye van:
x = -1.046681 f(x) = -0.352386 minimum
x = 0.101031 f(x) = 0.005026 maximum
x = 0.945649 f(x) = -0.152639 minimumA sekély völgyben landolni veszteségben 56,7%-kal rosszabb, és az algoritmusnak nincs módja ezt tudni, mert egy völgy belsejéből minden irány felfelé van. Erre nincs javítás a gradient descentben, és nem is érkezik. Ami a gyakorlatban van, az a megállapítás, hogy ez sokkal kevésbé számít, mint amit ez a kép sugall — egy valódi hálózat nagyon magas dimenzióiban a legtöbb kritikus pont csapda helyett nyeregpontnak bizonyul,2 az 5. fejezet pedig megméri, milyen gyakran akad el ténylegesen egy kis hálózat.
Olcsóbb lépések: stochastic, minibatch, momentum
Link a szakaszhoz: Olcsóbb lépések: stochastic, minibatch, momentumA fenti grad-ban egy dolognak zavarnia kellene: minden lépéshez az egész adathalmazon összegez. Nyolc alkatrész semmi. Egymillió már egymillió gradient-számítás ahhoz, hogy a paraméterek egyszer mozduljanak.
A menekülőút az, hogy a gradient egy átlag, és egy átlag mintából becsülhető. Számold ki egy véletlen marékon — egy minibatchen —, és lépj arra. A becslés zajos; egyben torzítatlan is, és több száz olcsó, zajos lépés legyőz egy drága, pontos lépést. Százezer szintetikus alkatrészen, példánkénti gradienteket számolva lépések helyett:
| módszer | lépések az optimum 0,1%-án belülre | példánkénti gradientek |
|---|---|---|
| full batch | 7 | 700.000 |
| 32-es minibatch | 100 | 3.200 |
| egyszerre egy példa | 17.580 | 17.580 |
Kétszáztizenkilencszer kevesebb aritmetika ugyanoda jutni. És a szélsőség — egyszerre egy példa, Robbins és Monro eredeti stochastic approximációja3 — nem a győztes: ötször rosszabb, mint a 32-es batch, mert 32 példa szinte semmivel sem kerül többe egynél olyan hardveren, amely mátrixokat szoroz, miközben a zaj a batchméret négyzetgyökével esik. Ez a kompromisszum az oka, hogy minden training scriptben, amit valaha olvasni fogsz, lesz egy batch_size.
Momentum a másik olcsó javítás, és pontosan az árokra céloz. Rosszul kondicionált völgyben a lépések cikcakkban átszelik a keskeny irányt, miközben a hosszú irány mentén araszolnak. A momentum a múltbeli gradientek futóátlagát tartja, így az oszcilláló komponensek kioltják egymást, a következetes pedig felhalmozódik:4
Két extra sor. A nyers, nem középre igazított szalagon — kondíciószám 33.452, a legrosszabb esetünk — a sima descent által elviselhető legjobb rátán:
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%172-es szorzó két sornyi kódért. A 6. fejezet ezt Adammé alakítja; a mechanizmus már itt van.
Az ellenőrzés, amelyre az 5. fejezetben szükséged lesz
Link a szakaszhoz: Az ellenőrzés, amelyre az 5. fejezetben szükséged leszEbben a fejezetben minden gradientet kézzel vezettünk le, ezért lehet, hogy rosszak. A javítás a fejezet eleji meredekségtáblázat: mérd meg a deriváltat numerikusan, és hasonlítsd össze. Használd a central differenciát, , amely kioltja a vezető hibatagot, és ugyanarra a -ra sokkal pontosabb.
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)))Az összehasonlítás relatív formája számít: egy abszolút különbség katasztrófa egy méretű gradienten, és lényegtelen egy méretűn.
relative error: 1.8929136036763527e-11
with 2 dropped: 0.33333333331650744Az első sor a fent kézzel levezetett gradient. A második ugyanaz a függvény úgy, hogy az egyik komponensből kimaradt a 2-es faktor — egyetlen karakteres elírás —, és az ellenőrzés azonnal elkapja. Körülbelül alatt egyezés; felett bug. Tartsd meg ezt a függvényt: az 5. fejezet ezzel debugol egy automatikus differenciáló motort, és ez az egyetlen ok, amiért egy rossz gradient egyáltalán megtalálható.
Merre megyünk tovább
Link a szakaszhoz: Merre megyünk továbbEbben a fejezetben minden egy soha ki nem mondott feltételezésen nyugodott: hogy le tudod írni -t.
Egy kétparaméteres egyenesnél ez egy sornyi algebra volt. Szinte azonnal megszűnik annak lenni. Kérd meg egy szimbolikus algebrai rendszert, hogy adja meg egy hálózat veszteségének deriváltját egy egyetlen első rétegbeli súly szerint, egy egyetlen példára, és számold meg a válaszban az aritmetikai műveleteket:
| hálózat | műveletek egy parciális deriváltban |
|---|---|
| négy rejtett egység, egy réteg | 40 |
| négy rejtett egység, két réteg | 301 |
| négy rejtett egység, három réteg | 1.717 |
A harmadik sor egy 57 paraméteres hálózat — olyan kicsi, hogy a 6. fejezetben lábjegyzet lenne —, és a gradient kézi kiírása egyetlen training példára körülbelül 97.869 műveletet jelent. Nincs olyan jelölés, amely ezt megmenti. Ami megmenti, az a megfigyelés, hogy a kompozícióra alkalmazott láncszabálynak hatalmas szerkezete van, ugyanazok a köztes mennyiségek újra és újra megjelennek, és megfelelő sorrendben számolva az összes derivált megkapható nagyjából egy forward pass áráért. Ez az 5. fejezet.
De előbb van egy kisebb probléma, és közvetlenül előttünk vár.
Most már van egy gépünk, amely bármely differenciálható veszteségen lefelé gurul. Irányítsuk a szalag eredeti kérdésére — elfogadni vagy elutasítani, ahol a cél 1 vagy 0 —, tegyünk sigmoidot a kimenetre, hogy valószínűséget jósoljon, és minimalizáljuk a négyzetes hibát. Futni fog. De épp akkor alig mozdul majd, amikor a leginkább téved, és a gradient megmondja, miért:
| kimenet | predikció | igazság | gradient négyzetes hibával | gradient cross-entropyvel |
|---|---|---|---|---|
| 0.5000 | 1 | |||
| 0.1192 | 1 | |||
| 0.0025 | 1 | |||
| 1 |
Egy modell, amely magabiztosan, katasztrofálisan téved — 0,0000454-et jósol, amikor a válasz 1 —, négyzetes hibás gradientet produkál. Fogalma sincs, hogy bajban van. A másik oszlop, egy még le nem vezetett veszteségből, 1,0-t jelent: maximális sürgősséget, pontosan ott, ahol megérdemelt.
Ez veti fel a kérdést, amellyel a következő fejezet kezd. Az előző fejezet azt mondta, hogy a veszteség a zajról tett feltételezés, a négyzetes hiba pedig Gauss-zajt feltételez. Milyen zajmodellje van egy igen-vagy-nem válasznak — és milyen veszteség jön ki, ha ugyanazt a levezetést lefuttatod rajta?
Források és módszer
Link a szakaszhoz: Források és módszerA módszer mindezeknél régebbi: Cauchy 1847-ben az Académie des Sciences-nek írt jegyzetében írta le, egyenletrendszerek megoldásának módjaként úgy, hogy a négyzetes reziduálisok összegén sétálunk lefelé. E fejezet mellé szintén érdemes olvasni Sebastian Ruder An overview of gradient descent optimization algorithms című írását (arXiv:1609.04747), amely tizennégy olvasható oldalon visz végig a momentumtól Adamig; Nocedal és Wright Numerical Optimization című könyvének 3. fejezetét (2. kiadás, Springer, 2006), amelynek 3.3. tétele egy kvadratikuson a steepest descent konvergenciarátáját a kondíciószám függvényében adja meg — ez az elmélet amögött, hogy a kondicionáltság miért dönti el a lépésszámot, bár line searcht tárgyal, nem a fent mért fix lépésű plafont —, vagy Deisenroth, Faisal és Ong Mathematics for Machine Learning című könyvének §5.8 és §7.1 szakaszát ugyanehhez kevesebb apparátussal; Prince Understanding Deep Learning című könyvének §6.1 szakaszát és Goodfellow, Bengio és Courville Deep Learning című könyvének §4.3 szakaszát; a Dive into Deep Learning §12.1–12.3 szakaszait, ahol a minibatch elemzés több méréssel szerepel, mint amennyinek itt hely jut; valamint Géron Hands-On Machine Learning című könyvének 4. fejezetét (3. kiadás), amely a learning rate leggyakorlatiasabb tárgyalása mint hangolandó, nem pedig levezetendő dolog. Az MIT 6.390 jegyzetei a gradient descentet a klasszifikáció elé teszik, ahogy ez a kurzus is, és ugyanabból az okból.
Hivatkozások
Link a szakaszhoz: Hivatkozások-
LeCun, Y., Bottou, L., Orr, G. B. és Müller, K.-R. Efficient BackProp, in Neural Networks: Tricks of the Trade (Springer, 1998), 9–50. o. A 4.3. szakasz adja az ajánlást, az 5.1. szakasz pedig a fenti részletdobozban használt érvet: a bemenetek középre igazítása és skálázása megváltoztatja a második deriváltak mátrixának sajátértékeit, és ezért a lépések számát is, nem pusztán a numerikus kényelmet. ↩
-
Dauphin, Y. N., Pascanu, R., Gulcehre, C., Cho, K., Ganguli, S. és Bengio, Y. Identifying and attacking the saddle point problem in high-dimensional non-convex optimization, arXiv:1406.2572 (2014). Az érv szerint nagy dimenzióban a kritikus pontok túlnyomórészt nyeregpontok, nem lokális minimumok, mivel egy minimumhoz egyszerre több ezer irány mindegyikének felfelé kell görbülnie. ↩
-
Robbins, H. és Monro, S. A Stochastic Approximation Method. Annals of Mathematical Statistics 22(3), 400–407. o. (1951). A cikk, amely megállapította, hogy egy gradient zajos becslése is elég, ha a lépésméret a megfelelő módon zsugorodik. ↩
-
Polyak, B. T. Some methods of speeding up the convergence of iteration methods. USSR Computational Mathematics and Mathematical Physics 4(5), 1–17. o. (1964). A heavy-ball módszer, amely a fenti momentum frissítés, huszonkét évvel azelőtt, hogy a backpropagation elérte volna ezt a területet. ↩