Hoppa till innehållet
3/30Kapitel 3 av 30

Nedför: gradient descent och de två steg alla hoppar över

Beräkna det exakta taket för learning rate och se en brute-force-sökning återupptäcka gradienten.

På den här sidan

Det förra kapitlet slutade med en dal.

Inte en metaforisk sådan: en faktisk kurva, loss plottad mot en enda parameter, som går ned och sedan upp igen. Och loss under den valdes inte för att den var prydlig — den härleddes från ett påstående om bruset i mätningarna, och kvadratfelet kom ut i andra änden som en följd snarare än en konvention.

Så vi har ett landskap med en botten, och ett skäl att tro att botten är rätt plats att vara på. Det vi inte har är ett sätt att ta oss dit.

Det här kapitlet bygger ett, och det är algoritmen som tränar varje model i resten av den här kursen — varenda en, utan undantag, upp till och med dem med hundratals miljarder parametrar. Den ryms på ungefär tjugo rader. De två svåra delarna finns inte i de där tjugo raderna, och de är de två saker nästan varje förklaring hoppar över:

  • Varför minustecknet. Uppdateringen subtraherar gradienten. Varje handledning skriver det; väldigt få säger varför gradienten är riktningen som går upp, vilket är det enda faktum som gör minustecknet till något annat än en trosakt.
  • Hur stort steg. ”För stort divergerar, för litet är långsamt” är sant och oanvändbart. Det finns ett exakt tal, det går att beräkna från loss, och det här kapitlet beräknar det två gånger — en gång för en leksaksparabel och en gång för de faktiska data.

Upplägget, och varför du inte bara kan söka

Länk till avsnittet: Upplägget, och varför du inte bara kan söka

Omformulerat så att kapitlet står på egna ben: de åtta delarna från transportbandet i kapitel 1, men med en annan fråga. Inte acceptera eller avvisa — det återkommer senare — utan förutsäg en dels vikt från dess bredd.

belt.pyPYTHON
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 g

Mätningarna är centrerade, precis som i kapitel 1 och av ett skäl som kommer tillbaka med ränta innan kapitlet är slut. Modellen är en linje, y^=ax+b\hat{y} = a x + b, och loss är det genomsnittliga kvadratfelet som förra kapitlet härledde:

L(a,b)=1ni=1n(axi+byi)2L(a, b) = \frac{1}{n} \sum_{i=1}^{n} \left(a x_i + b - y_i\right)^2

Två parametrar. Varför inte bara prova massor av värden? Låt oss faktiskt göra det — ett rutnät från a=0a = 0 till 55 och b=5b = -5 till 55, i steg om 0.010.01:

TEXT
grid 501 x 1001 = 501,501 evaluations in 3.67 s
  best found: a = 2.1000, b = -0.0000, L = 24.592450

En halv miljon utvärderingar för att låsa två tal till två decimaler — och den där sekunden är väggklocketid på en maskin, så en ny körning hamnar någonstans mellan tre och sex; utvärderingsantalet och minimumet är den del som reproduceras. Gradient descent, i slutet av kapitlet, får fyra decimaler på åtta steg och hela float64-svaret på trettiosex.

Men hastighet är inte argumentet, och det här är poängen som avgör hela kursen. Rutnätssökning kostar kPk^P utvärderingar för PP parametrar vid kk värden vardera. Med tusen värden per axel:

modelparametrarrutnätsutvärderingar
den här linjen210610^{6}
XOR-nätverket i kapitel 59102710^{27}
ett litet flerskiktsnätverk20 0001060,00010^{60{,}000}

Den tredje raden är inte ett stort tal, det är ett meningslöst tal — det finns ungefär 108010^{80} atomer i det observerbara universum. Sökning blir inte bara långsammare när modeller växer; den upphör att existera. Allt som följer finns på grund av den tabellen.

Fixera b=0b = 0 en stund så att det finns en parameter och en kurva, vilket är bilden det förra kapitlet lämnade dig med. Ta en punkt på den, a=1a = 1, och fråga: om jag knuffar aa med en liten mängd hh, hur mycket rör sig loss, per enhet knuff?

L(a+h)L(a)h\frac{L(a + h) - L(a)}{h}

Den kvoten är en höjd över längd — lutningen på den räta linjen genom två punkter på kurvan. När hh krymper glider de två punkterna ihop och linjen blir tangenten. Dess lutning är derivatan L(a)L'(a): takten med vilken loss förändras per enhets förändring i aa. Inte en approximation av något, och inte en oändligt liten storhet. En gräns av vanliga kvoter.

Det är värt att köra, eftersom siffrorna säger något som definitionen inte gör:

slope.pyPYTHON
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}")
TEXT
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-01

Två saker händer här och båda är bärande.

Felet är inte vagt proportionellt mot hh — det är exakt 7.445h7.445\,h. Dela hh med hundra, så delas felet med hundra, till fyra signifikanta siffror varje gång. Den konstanten är inte dekoration: den är hälften av den andra derivatan av loss, och den är första framträdandet av en idé två avsnitt härifrån — att en kurva nära en punkt ser ut som en linje plus en korrigering proportionell mot h2h^2.

Och sedan bryts mönstret. Under h=108h = 10^{-8} blir uppskattningen sämre, och vid 101410^{-14} är den fel i andra siffran. Inget matematiskt hände; det förra kapitlets flyttalslåda gjorde det. L(a+h)L(a+h) och L(a)L(a) är överens i sina första tio siffror, att subtrahera dem förstör de siffrorna, och att dela spillrorna med ett pyttelitet tal förstorar det som finns kvar. Det finns ett bästa hh — här runt 10810^{-8}, ungefär kvadratroten av maskinepsilon — och att gå mindre är inte mer noggrant, det är mindre. Kom ihåg det; en funktion i slutet av kapitlet beror på det.

Den exakta lutningen, från analys snarare än mätning, är 16.385-16.385. Så vi kan sluta mäta och börja härleda.

Här är idén som resten av kursen bygger på, formulerad en gång, rakt på sak.

Att sätta samman två funktioner är att mata den ena in i den andra: (fg)(x)=f(g(x))(f \circ g)(x) = f(g(x)). Inget mer.

Ett djupt nätverk är inte som en sammansättning. Det är en. Ett lager är en funktion; att stapla lager är att sätta samman dem; ”djup” är antalet funktioner i kedjan. När kapitel 5 bygger ett nätverk bygger det f4f3f2f1f_4 \circ f_3 \circ f_2 \circ f_1 och inget annat. Vilket betyder att den viktigaste regeln i analysen, för våra syften, är den som deriverar en sammansättning:

ddxf(g(x))=f(g(x))g(x)\frac{d}{dx} f(g(x)) = f'(g(x)) \cdot g'(x)

Takter multipliceras. Om gg förändras tre gånger så snabbt som xx, och ff förändras dubbelt så snabbt som gg, då förändras ff sex gånger så snabbt som xx. Det är hela innehållet, och det är därför en signal som passerar bakåt genom tio lager multipliceras med tio tal — vilket är varför kapitel 6 ägnar ett avsnitt åt vad som händer när de talen alla är något mindre än ett.

Använd den på vår loss. Skriv residualen ri=axi+byir_i = a x_i + b - y_i, så att L=1nri2L = \frac{1}{n}\sum r_i^2. Varje rir_i beror på aa genom den inre funktionen axia x_i, vars derivata är xix_i. Kedjeregeln, term för term:

La=1ni2rixi,Lb=1ni2ri1\frac{\partial L}{\partial a} = \frac{1}{n}\sum_i 2 r_i \cdot x_i, \qquad \frac{\partial L}{\partial b} = \frac{1}{n}\sum_i 2 r_i \cdot 1

De där krulliga \partial-symbolerna markerar en partiell derivata: derivera med avseende på en variabel och behandla alla andra som konstanta. Inget nytt händer — det är samma gränsvärde som tidigare, taget längs en axel. Samla de partiella derivatorna i en vektor och du har gradienten:

L=(La, Lb)\nabla L = \left( \frac{\partial L}{\partial a},\ \frac{\partial L}{\partial b} \right)

I punkten (a,b)=(1,4)(a, b) = (1, 4) är den vektorn (16.385, 8.0)(-16.385,\ 8.0). Två tal. Frågan är vad de betyder, och detta är det första steget alla hoppar över.

Gradienten är en vektor av lutningar längs axlarna. Det är allt vi har bevisat. Det är inte uppenbart — det bör inte vara uppenbart — att om man sätter ihop dem till en vektor så pekar den någon särskild riktning.

Så definiera det vi faktiskt vill ha. Välj en enhetsvektor u\mathbf{u}, en riktning. Riktningsderivatan är takten med vilken loss förändras när du går åt det hållet:

DuL=limh0L(θ+hu)L(θ)hD_{\mathbf{u}} L = \lim_{h \to 0} \frac{L(\boldsymbol{\theta} + h\mathbf{u}) - L(\boldsymbol{\theta})}{h}

Kedjeregeln gör detta beräkningsbart. Att gå längs u\mathbf{u} förändrar aa med takt u1u_1 och bb med takt u2u_2, och bidragen adderas:

DuL=Lau1+Lbu2=LuD_{\mathbf{u}} L = \frac{\partial L}{\partial a} u_1 + \frac{\partial L}{\partial b} u_2 = \nabla L \cdot \mathbf{u}

Förändringstakten i vilken riktning som helst är skalärprodukten av gradienten med den riktningen. Och nu poängen, som är en rad geometri. Skriv skalärprodukten med vinkeln ϕ\phi mellan vektorerna,

Lu=Lucosϕ=Lcosϕ\nabla L \cdot \mathbf{u} = \lVert \nabla L \rVert \, \lVert \mathbf{u} \rVert \cos\phi = \lVert \nabla L \rVert \cos\phi

eftersom u\mathbf{u} har längd 1. Det enda du styr är cosϕ\cos\phi, som är störst vid ϕ=0\phi = 0 och minst ett halvt varv bort, ϕ=180\phi = 180 grader. Alltså:

  • Den brantaste uppstigningen är längs L\nabla L själv, och lutningen där är exakt L\lVert \nabla L \rVert.
  • Den brantaste nedstigningen är längs L-\nabla L, och lutningen där är L-\lVert \nabla L \rVert.
  • Vinkelrätt mot gradienten förändras loss inte alls. Det är därför en nivåkurvas linjer korsar gradienten i räta vinklar.

Det är minustecknet. Inte en konvention, inte ett teckenbyte som någon valde: riktningen för snabbast minskning är den negativa gradienten eftersom cosϕ\cos\phi minimeras vid ett halvt varv, och av ingen annan anledning.

Eftersom detta är ett påstående om alla riktningar, testa det mot alla riktningar. Sampla 3 600 av dem, en per tiondels grad, och mät var och en genom att knuffa:

directions.pyPYTHON
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")
TEXT
gradient       [-16.385   8.   ]
its length     18.23371122399386
its angle      153.97598928042032 degrees
steepest slope 18.233709624837502 at 154.0 degrees

En sökning som inte vet något om gradienter, över 3 600 riktningar, hittar sin brantaste stigning vid 154,0 grader — gradientens egen riktning, inom sökningens upplösning på 0,1 grad. Och lutningen den hittar där, 18,2337, är gradientens längd till sex siffror. Satsen är inte en berättelse om vad gradienter betyder; den är ett mätbart faktum, och detta är mätningen.

Varför ett litet steg nedför faktiskt hjälper

Länk till avsnittet: Varför ett litet steg nedför faktiskt hjälper

Nu det andra överhoppade steget. Vi vet vilken väg som är ned. Det följer inte att det sänker loss att gå åt det hållet, eftersom ”ned” är ett påstående om en infinitesimal knuff och ett steg inte är infinitesimalt.

Bryggan är linearisering. Nära en punkt är en slät funktion sin tangent plus en korrigering:

L(θ+δ)=L(θ)+Lδ+O(δ2)L(\boldsymbol{\theta} + \boldsymbol{\delta}) = L(\boldsymbol{\theta}) + \nabla L \cdot \boldsymbol{\delta} + O(\lVert\boldsymbol{\delta}\rVert^2)

Det är första ordningens Taylorutveckling. Den bortkastade O(δ2)O(\lVert\boldsymbol{\delta}\rVert^2) är krökningen — samma term som gjorde lutningstabellens uppskattning fel med exakt 7.445h7.445\,h. Sätt in steget vi tänker ta, δ=ηL\boldsymbol{\delta} = -\eta \nabla L:

L(θηL)L(θ)ηL2L(\boldsymbol{\theta} - \eta \nabla L) \approx L(\boldsymbol{\theta}) - \eta \lVert \nabla L \rVert^2

Loss sjunker med ηL2\eta \lVert \nabla L \rVert^2. Varje del av det är icke-negativ, så löftet är verkligt — för ett tillräckligt litet η\eta, eftersom den försummade termen växer som η2\eta^2 och till slut äter upp det. Det är hela teorin. Här hålls löftet, och bryts sedan:

TEXT
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.999938

Läs det nedifrån. När η\eta krymper konvergerar det levererade fallet mot det utlovade — kvot 0,99938, sedan 0,99994 — vilket är Taylors sats som har rätt. Läs det uppifrån och vid η=0.2\eta = 0.2 är det levererade ”fallet” minus sexton. Steget gick nedför och loss gick upp.

Alltså är uppdateringsregeln

θθηL(θ)\boldsymbol{\theta} \leftarrow \boldsymbol{\theta} - \eta \nabla L(\boldsymbol{\theta})

och den kommer med ett villkor som ingen säger, nämligen att η\eta är tillräckligt litet. Tillräckligt litet jämfört med vad, exakt, är nästa avsnitt.

Learning rate har ett tak, och det kan beräknas

Länk till avsnittet: Learning rate har ett tak, och det kan beräknas

Börja med den enklaste dalen som finns, f(x)=x2f(x) = x^2, där f(x)=2xf'(x) = 2x. Ett steg med gradient descent är

xxη2x=x(12η)x \leftarrow x - \eta \cdot 2x = x\,(1 - 2\eta)

Positionen multipliceras med (12η)(1 - 2\eta) varje steg. Det är en geometrisk följd, och geometriska följder har exakt en regel: de krymper när multiplikatorn är mindre än 1 i absolutvärde och växer annars. Alltså 12η<1\lvert 1 - 2\eta \rvert < 1, vilket är 0<η<10 < \eta < 1.

Gränsen ligger vid η=1\eta = 1 exakt. Inte ”runt 1”, inte ”1 är vanligtvis för stort”. Vid η=1\eta = 1 är multiplikatorn 1-1 och punkten studsar mellan xx och x-x för alltid, utan att närma sig eller fly. Under den, konvergens; över den, divergens. Intervallet delas igen vid η=0.5\eta = 0.5, där multiplikatorn byter tecken: under det är närmandet monotont, över det skjuter punkten över och växlar sida, och vid exakt 0.50.5 är multiplikatorn 0 och ett enda steg landar på minimumet.

Fyra regimer, från fyra rader algebra. Gå och korsa gränserna själv:

14 steg, slutar vid x = -0.0836.

Se data som tabell
Stegxf(x)
0⁨-1.9000⁩⁨3.6100⁩
1⁨-1.5200⁩⁨2.3104⁩
2⁨-1.2160⁩⁨1.4787⁩
3⁨-0.9728⁩⁨0.9463⁩
4⁨-0.7782⁩⁨0.6057⁩
5⁨-0.6226⁩⁨0.3876⁩
6⁨-0.4981⁩⁨0.2481⁩
7⁨-0.3985⁩⁨0.1588⁩
8⁨-0.3188⁩⁨0.1016⁩
9⁨-0.2550⁩⁨0.0650⁩
10⁨-0.2040⁩⁨0.0416⁩
11⁨-0.1632⁩⁨0.0266⁩
12⁨-0.1306⁩⁨0.0170⁩
13⁨-0.1045⁩⁨0.0109⁩
14⁨-0.0836⁩⁨0.0070⁩
Gradientnedstigning, interaktiv

Fjorton steg med en rate på 0,1, från x=1.9x = -1.9, som slutar vid 0.0836-0.0836. Tryck upp rate till 0,5 och allra första steget landar på botten. Tryck den till 0,9 och det slutar vid samma 0.0836-0.0836 som 0,1 gjorde — samma avstånd, motsatt stil, eftersom 12η\lvert 1 - 2\eta \rvert är 0,8 för båda — men det tar sig dit genom att zickzacka över dalen i stället för att gå ned längs ena sidan.

Och nu den intressanta:

14 steg, slutar vid x = -1.9000.

Se data som tabell
Stegxf(x)
0⁨-1.9000⁩⁨3.6100⁩
1⁨1.9000⁩⁨3.6100⁩
2⁨-1.9000⁩⁨3.6100⁩
3⁨1.9000⁩⁨3.6100⁩
4⁨-1.9000⁩⁨3.6100⁩
5⁨1.9000⁩⁨3.6100⁩
6⁨-1.9000⁩⁨3.6100⁩
7⁨1.9000⁩⁨3.6100⁩
8⁨-1.9000⁩⁨3.6100⁩
9⁨1.9000⁩⁨3.6100⁩
10⁨-1.9000⁩⁨3.6100⁩
11⁨1.9000⁩⁨3.6100⁩
12⁨-1.9000⁩⁨3.6100⁩
13⁨1.9000⁩⁨3.6100⁩
14⁨-1.9000⁩⁨3.6100⁩
Gradientnedstigning, interaktiv

Exakt på gränsen. Fjorton steg med en rate på 1, och det slutar vid 1.9-1.9: precis där det började, efter att inte ha gjort något annat än att studsa. En knuff högre och studsandet växer i stället för att hålla sig; vid 1,2 är det utanför diagrammet på fyra steg. En rate som är för stor konvergerar inte långsamt. Den konvergerar inte.

Nu den allmänna regeln, som faller ut ur samma argument. Multiplikatorn 12η1 - 2\eta var egentligen 1ηf1 - \eta f'', och nära ett minimum har en loss med flera parametrar ett sådant tal per riktning — egenvärdena för matrisen av andraderivator. Varje riktning måste vara stabil samtidigt, så taket sätts av den största:

η<2λmax\eta < \frac{2}{\lambda_{\max}}

För f(x)=x2f(x) = x^2, f=2f'' = 2, tak 1, vilket är vad vi just härledde. För vårt band är andraderivatmatrisen 2nAA\frac{2}{n} A^{\top} A med AA som tvåkolumnsmatrisen av inputs, och dess egenvärden är 2 och 14,89, så taket är 2/14.89=0.134322 / 14.89 = 0.13432. Det är en förutsägelse med fem signifikanta siffror i sig. Testa den:

TEXT
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

Fem decimalers överensstämmelse mellan en rad linjär algebra och hundratusen iterationer av en for-loop.

Och här kommer kapitel 1 tillbaka. Allt ovan använde de centrerade mätningarna. Kör identisk kod på råa millimeter och gram och egenvärdena är 0,0298 och 998,1 i stället för 2 och 14,89. Taket kollapsar från 0,134 till 0,002004 — lika exakt, med konvergens vid lr=0.002003 och explosion vid lr=0.002004.

Värre än taket är kvoten mellan egenvärdena. Konditionstalet mäter hur långt ifrån rund dalen är: ett långt, smalt dike tvingar fram en rate som är liten nog för de branta väggarna, och sedan gås dikets golv i samma krypfart. Vårt går från 7,44 centrerat till 33 452 rått. Med den bästa rate varje version kan ta:

featureskonditionstalbästa ratesteg till inom 1 % av optimum
centrerade7,440,118410
råa millimeter och gram33 4520,002003779 513

Samma data, samma kod, samma svar i slutet — och åtta tusen gånger arbetet, för att ingen subtraherade ett medelvärde. I kapitel 1 kostade samma utelämnande perceptronen en faktor sex tusen i epoker, och diagnosen där var geometrisk: data svävade långt från origo. Det är samma geometri här i optimeringskostym, och det är därför input-normalisering inte är hygienråd utan aritmetik.1

Inget ovan behövde ett bibliotek. Här är hela optimeraren.

descent.pyPYTHON
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))
TEXT
[ 2.10040296e+00 -2.76445533e-15] 24.592448791134984

Det slutna least-squares-svaret för dessa åtta punkter är a=2.100403a = 2.100403, b=0b = 0, med en loss på 24.59244924.592449. Loopen hittade det till åtta signifikanta siffror utan att veta att en sluten form finns — vilket spelar roll, eftersom från kapitel 5 och framåt kommer det inte att finnas någon.

Banan, eftersom poängen är att se den:

TEXT
   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.592449

Det mesta av avståndet täcks under de första två stegen, eftersom gradienten är störst när du är längst från botten och krymper när du närmar dig. Gradient descent saktar automatiskt ned nära ett minimum. Det är en feature och det är också, i kapitel 6, ett problem.

Argumentet hittills har ett hål. Steget stannar när L=0\nabla L = \mathbf{0}, och vi har kallat det ”minimumet”. En punkt med noll gradient är en kritisk punkt, och att vara ett minimum är bara ett av sätten att vara en sådan:

  • ett lokalt minimum: uppför i varje riktning, men kanske inte den lägsta sådana punkten någonstans;
  • ett lokalt maximum: nedför i varje riktning;
  • en sadelpunkt: uppför i vissa riktningar och nedför i andra. Ytan f(x,y)=x2y2f(x,y) = x^2 - y^2 har f=(2x,2y)\nabla f = (2x, -2y), som är noll i origo, där funktionen är ett minimum längs xx-axeln och ett maximum längs yy-axeln samtidigt.

Gradient descent kan inte skilja dem åt, eftersom den bara någonsin tittar på gradienten, och gradienten är noll vid alla tre.

Vår linje har en kritisk punkt och den är svaret — en kvadratfels-loss över en linjär model är konvex, en enda skål, och descent på den kan inte misslyckas med att hitta det globala minimumet. Den egenskapen överlever inte kontakten med den här kursen. Loss för ett neuralt nätverk är inte konvex, och från kapitel 5 och framåt är ”minimumet” inte något som finns: det finns många, med olika djup, och vilket du får beror på var du startade. Det är en mening och förblir en mening, eftersom teorin är stor och den praktiska konsekvensen liten.

Du kan se hela konsekvensen på en kurva. Ta f(x)=x44x22+x10f(x) = \tfrac{x^4}{4} - \tfrac{x^2}{2} + \tfrac{x}{10}, som har två dalar med olika djup:

TEXT
   x =  -1.046681   f(x) =  -0.352386   minimum
   x =   0.101031   f(x) =   0.005026   maximum
   x =   0.945649   f(x) =  -0.152639   minimum

40 steg, slutar vid x = 0.9456.

Se data som tabell
Stegxf(x)
0⁨0.1100⁩⁨0.0050⁩
1⁨0.1122⁩⁨0.0050⁩
2⁨0.1149⁩⁨0.0049⁩
3⁨0.1182⁩⁨0.0049⁩
4⁨0.1223⁩⁨0.0048⁩
5⁨0.1275⁩⁨0.0047⁩
6⁨0.1338⁩⁨0.0045⁩
7⁨0.1416⁩⁨0.0042⁩
8⁨0.1513⁩⁨0.0038⁩
9⁨0.1633⁩⁨0.0032⁩
10⁨0.1781⁩⁨0.0022⁩
11⁨0.1962⁩⁨0.0007⁩
12⁨0.2183⁩⁨-0.0014⁩
13⁨0.2453⁩⁨-0.0046⁩
14⁨0.2779⁩⁨-0.0093⁩
15⁨0.3170⁩⁨-0.0160⁩
16⁨0.3633⁩⁨-0.0253⁩
17⁨0.4172⁩⁨-0.0377⁩
18⁨0.4783⁩⁨-0.0535⁩
19⁨0.5455⁩⁨-0.0721⁩
20⁨0.6163⁩⁨-0.0922⁩
21⁨0.6869⁩⁨-0.1116⁩
22⁨0.7526⁩⁨-0.1277⁩
23⁨0.8092⁩⁨-0.1393⁩
24⁨0.8540⁩⁨-0.1463⁩
25⁨0.8868⁩⁨-0.1499⁩
26⁨0.9091⁩⁨-0.1516⁩
27⁨0.9236⁩⁨-0.1522⁩
28⁨0.9325⁩⁨-0.1525⁩
29⁨0.9379⁩⁨-0.1526⁩
30⁨0.9411⁩⁨-0.1526⁩
31⁨0.9430⁩⁨-0.1526⁩
32⁨0.9441⁩⁨-0.1526⁩
33⁨0.9448⁩⁨-0.1526⁩
34⁨0.9451⁩⁨-0.1526⁩
35⁨0.9454⁩⁨-0.1526⁩
36⁨0.9455⁩⁨-0.1526⁩
37⁨0.9455⁩⁨-0.1526⁩
38⁨0.9456⁩⁨-0.1526⁩
39⁨0.9456⁩⁨-0.1526⁩
40⁨0.9456⁩⁨-0.1526⁩
Gradientnedstigning, interaktiv

Fyrtio steg från x=0.11x = 0.11, som lägger sig vid 0.94560.9456 — den grundare av de två dalarna. Flytta nu startpunkten ett hack åt vänster, till 0.100.10. Samma rate, samma fyrtio steg, och den lägger sig vid 1.0461-1.0461 i stället, där loss är 0.199747 lägre. Vattendelaren är puckeln vid 0.1010310.101031, och hela skillnaden mellan de två svaren är vilken sida av den du råkade starta på.

Att landa i den grunda dalen är 56,7 % sämre i loss, och algoritmen har inget sätt att veta det, eftersom från insidan av en dal är varje riktning uppför. Det finns ingen reparation för detta i gradient descent och ingen är på väg. Det som finns i praktiken är fyndet att det spelar mycket mindre roll än den här bilden antyder — i de mycket höga dimensionerna hos ett verkligt nätverk visar sig de flesta kritiska punkter vara sadlar snarare än fällor,2 och kapitel 5 mäter hur ofta ett litet nätverk faktiskt fastnar.

Billigare steg: stokastisk, minibatch, momentum

Länk till avsnittet: Billigare steg: stokastisk, minibatch, momentum

En sak med grad ovan borde störa dig: den summerar över hela datasetet för varje steg. Åtta delar är ingenting. En miljon är en miljon gradientberäkningar för att flytta parametrarna en gång.

Utvägen är att gradienten är ett genomsnitt, och ett genomsnitt kan uppskattas från ett sample. Beräkna den på en slumpmässig handfull — en minibatch — och ta steget på den. Uppskattningen är brusig; den är också unbiased, och hundratals billiga brusiga steg slår ett dyrt exakt steg. På hundratusen syntetiska delar, räknat per-exempel-gradienter snarare än steg:

metodsteg till inom 0,1 % av optimumper-exempel-gradienter
full batch7700 000
minibatch på 321003 200
ett exempel åt gången17 58017 580

Tvåhundranitton gånger mindre aritmetik för att nå samma plats. Och extremen — ett exempel åt gången, den ursprungliga stokastiska approximationen av Robbins och Monro3 — är inte vinnaren: den är fem gånger sämre än batcher på 32, eftersom 32 exempel kostar nästan ingenting mer än ett på hårdvara som multiplicerar matriser, medan bruset faller med kvadratroten av batchstorleken. Den avvägningen är varför varje träningsskript du någonsin läser har en batch_size i sig.

Momentum är den andra billiga fixen, och den är riktad rakt mot diket. I en dåligt konditionerad dal zickzackar stegen över den smala riktningen medan de kryper längs den långa. Momentum håller ett löpande medelvärde av tidigare gradienter, så de oscillerande komponenterna tar ut varandra och den konsekventa ackumuleras:4

vβv+L(θ),θθηv\mathbf{v} \leftarrow \beta \mathbf{v} + \nabla L(\boldsymbol{\theta}), \qquad \boldsymbol{\theta} \leftarrow \boldsymbol{\theta} - \eta \mathbf{v}

Två extra rader. På det råa ocentrerade bandet — konditionstal 33 452, vårt värsta fall — vid den bästa rate vanlig descent kan ta:

TEXT
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%

En faktor 172 för två rader kod. Kapitel 6 gör detta till Adam; mekanismen finns redan här.

Varje gradient i det här kapitlet härleddes för hand och kunde därför vara fel. Fixen är lutningstabellen från början: mät derivatan numeriskt och jämför. Använd den centrala differensen, L(θ+h)L(θh)2h\frac{L(\theta+h) - L(\theta-h)}{2h}, som tar bort den ledande feltermen och är mycket mer exakt för samma hh.

gradcheck.pyPYTHON
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)))

Den relativa formen på jämförelsen spelar roll: en absolut skillnad på 10410^{-4} är en katastrof på en gradient av storlek 10310^{-3} och irrelevant på en av storlek 10610^{6}.

TEXT
relative error: 1.8929136036763527e-11
with 2 dropped: 0.33333333331650744

Den första raden är den handhärledda gradienten ovan. Den andra är samma funktion med faktorn 2 utelämnad i en komponent — ett skrivfel på ett enda tecken — och kontrollen fångar det direkt. Allt under ungefär 10710^{-7} är överensstämmelse; allt över 10410^{-4} är en bugg. Behåll den här funktionen: kapitel 5 använder den för att felsöka en automatic differentiation-motor, och den är den enda anledningen till att en felaktig gradient över huvud taget går att hitta.

Allt i det här kapitlet vilade på ett antagande som aldrig uttalades: att du kan skriva ned L/θ\partial L / \partial \theta.

För en linje med två parametrar var det en rad algebra. Det slutar vara det nästan omedelbart. Be ett symboliskt algebrasystem om derivatan av ett nätverks loss med avseende på en enda vikt i första lagret, för ett enda exempel, och räkna aritmetiken i svaret:

nätverkoperationer i en partiell derivata
fyra dolda enheter, ett lager40
fyra dolda enheter, två lager301
fyra dolda enheter, tre lager1 717

Den tredje raden är ett nätverk med 57 parametrar — ett nätverk så litet att det skulle vara en fotnot i kapitel 6 — och att skriva ut dess gradient för hand betyder ungefär 97 869 operationer för ett tränings­exempel. Det finns ingen notation som räddar detta. Det som räddar det är observationen att kedjeregeln tillämpad på en sammansättning har enorm struktur, att samma mellanliggande storheter dyker upp om och om igen, och att om man beräknar dem i rätt ordning får man alla derivatorna för ungefär priset av en forward pass. Det är kapitel 5.

Men det finns ett mindre problem först, och det väntar omedelbart.

Vi har nu en maskin som rullar nedför på vilken deriverbar loss som helst. Rikta den mot bandets ursprungliga fråga — acceptera eller avvisa, ett target som är 1 eller 0 — sätt en sigmoid på output så att den förutsäger en sannolikhet, och minimera kvadratfel. Den kommer att köras. Den kommer också knappt att röra sig när den har som mest fel, och gradienten säger varför:

output zzpredictionsanninggradient med kvadratfelgradient med cross-entropy
000.500012.5×1012.5 \times 10^{-1}5.0×1015.0 \times 10^{-1}
2-20.119211.850×1011.850 \times 10^{-1}8.808×1018.808 \times 10^{-1}
6-60.002514.921×1034.921 \times 10^{-3}9.975×1019.975 \times 10^{-1}
10-104.54×1054.54 \times 10^{-5}19.079×1059.079 \times 10^{-5}1.0001.000

En model som har självsäkert, katastrofalt fel — förutsäger 0,0000454 när svaret är 1 — producerar en kvadratfels-gradient på 9×1059 \times 10^{-5}. Den har ingen aning om att den är i trubbel. Den andra kolumnen, från en loss vi inte har härlett än, rapporterar 1,0: maximal brådska, exakt där den är förtjänt.

Vilket väcker frågan nästa kapitel öppnar med. Förra kapitlet sade att en loss är ett antagande om bruset, och kvadratfel antar Gaussiskt brus. Vilken brusmodell har ett ja-eller-nej-svar — och vilken loss kommer ut när du kör samma härledning på den?


Metoden är äldre än alla dessa: Cauchy beskrev den i en not till Académie des Sciences 1847, som ett sätt att lösa ekvationssystem genom att gå nedför på summan av deras kvadrerade residualer. Också värt att läsa vid sidan av det här kapitlet: Sebastian Ruders An overview of gradient descent optimization algorithms (arXiv:1609.04747), som täcker momentum till Adam på fjorton läsbara sidor; kapitel 3 i Nocedal och Wrights Numerical Optimization (2:a uppl., Springer, 2006), vars sats 3.3 ger konvergenshastigheten för steepest descent på en kvadratisk funktion i termer av konditionstalet — det är teorin bakom varför konditionering avgör stegantalet, även om den behandlar line search snarare än det fixed-step 2/λmax2/\lambda_{\max}-tak som mättes ovan, eller §5.8 och §7.1 i Deisenroth, Faisal och Ongs Mathematics for Machine Learning för samma mark med mindre maskineri; §6.1 i Princes Understanding Deep Learning och §4.3 i Goodfellow, Bengio och Courvilles Deep Learning; Dive into Deep Learning §12.1–12.3, som har minibatch-analysen med fler mätningar än det finns plats för här; och kapitel 4 i Géron, Hands-On Machine Learning (3:e uppl.), den mest praktiska behandlingen av learning rate som något du justerar snarare än härleder. MIT 6.390-anteckningarna placerar gradient descent före klassificering, precis som den här kursen gör och av samma skäl.

  1. LeCun, Y., Bottou, L., Orr, G. B. and Müller, K.-R. Efficient BackProp, i Neural Networks: Tricks of the Trade (Springer, 1998), s. 9–50. Avsnitt 4.3 ger rekommendationen och avsnitt 5.1 argumentet som används i detaljrutan ovan: att centrera och skala inputs ändrar egenvärdena för andraderivatmatrisen, och därmed antalet steg, inte bara den numeriska bekvämligheten.

  2. Dauphin, Y. N., Pascanu, R., Gulcehre, C., Cho, K., Ganguli, S. and Bengio, Y. Identifying and attacking the saddle point problem in high-dimensional non-convex optimization, arXiv:1406.2572 (2014). Argumentet att kritiska punkter i höga dimensioner till överväldigande del är sadlar snarare än lokala minima, eftersom ett minimum kräver att varenda en av tusentals riktningar kröker uppåt samtidigt.

  3. Robbins, H. and Monro, S. A Stochastic Approximation Method. Annals of Mathematical Statistics 22(3), s. 400–407 (1951). Artikeln som etablerade att en brusig uppskattning av en gradient räcker, givet en steglängd som krymper på rätt sätt.

  4. Polyak, B. T. Some methods of speeding up the convergence of iteration methods. USSR Computational Mathematics and Mathematical Physics 4(5), s. 1–17 (1964). Heavy-ball-metoden, som är momentum-uppdateringen ovan, tjugotvå år innan backpropagation nådde det här fältet.

Redo att låta LIA välja åt dig?

Bygg med alla AI-modeller på ett ställe – kom igång gratis i dag.