Ves al contingut
3/30Capítol 3 de 30

Pendent avall: gradient descent i els dos passos que tothom se salta

Calcula el límit exacte d’una taxa d’aprenentatge i mira com una cerca bruta en 3.600 direccions redescobreix el gradient.

En aquesta pàgina

El capítol anterior acabava amb una vall.

No una vall metafòrica: una corba real, la pèrdua representada contra un únic paràmetre, que baixava i tornava a pujar. I la pèrdua que hi havia sota no es va triar perquè fos endreçada: es va derivar d’una afirmació sobre el soroll en les mesures, i l’error quadràtic en va sortir com a conseqüència, no com a convenció.

Així doncs, tenim un paisatge amb un fons, i una raó per creure que el fons és el lloc correcte on ser. El que no tenim és una manera d’arribar-hi.

Aquest capítol en construeix una, i és l’algorisme que entrena tots els models de la resta d’aquest curs — tots, sense excepció, fins i tot els que tenen centenars de milers de milions de paràmetres. Cap en unes vint línies. Les dues parts difícils no són en aquestes vint línies, i són les dues coses que gairebé totes les explicacions se salten:

  • Per què el signe menys. L’actualització resta el gradient. Tots els tutorials ho escriuen; molt pocs diuen per què el gradient és la direcció que va amunt, que és l’únic fet que fa que el signe menys sigui alguna cosa més que un acte de fe.
  • Quina mida de pas. «Massa gran divergeix, massa petit és lent» és veritat i no serveix de gaire. Hi ha un nombre exacte, es pot calcular a partir de la pèrdua, i aquest capítol el calcula dues vegades: una per a una paràbola de joguina i una per a les dades reals.

La configuració, i per què no pots simplement buscar

Enllaç a la secció: La configuració, i per què no pots simplement buscar

Reformulat perquè aquest capítol s’aguanti sol: les vuit peces de la cinta transportadora del Capítol 1, però amb una pregunta diferent. No acceptar o rebutjar — això tornarà més endavant — sinó predir el pes d’una peça a partir de la seva amplada.

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

Les mesures estan centrades, exactament com al Capítol 1 i per una raó que tornarà amb interessos abans que s’acabi aquest capítol. El model és una recta, y^=ax+b\hat{y} = a x + b, i la pèrdua és l’error quadràtic mitjà que el capítol anterior va derivar:

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

Dos paràmetres. Per què no provar molts valors? Fem-ho de debò: una graella de a=0a = 0 a 55 i de b=5b = -5 a 55, en passos de 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

Mig milió d’avaluacions per fixar dos nombres amb dos decimals — i aquest segon és temps de rellotge en una màquina, de manera que una repetició pot caure entre tres i sis; el recompte d’avaluacions i el mínim són la part que es reprodueix. Gradient descent, al final d’aquest capítol, aconsegueix quatre decimals en vuit passos i la resposta completa float64 en trenta-sis.

Però la velocitat no és l’argument, i aquest és el punt que decideix tot el curs. La cerca en graella costa kPk^P avaluacions per a PP paràmetres amb kk valors cadascun. Amb mil valors per eix:

modelparàmetresavaluacions de graella
aquesta recta210610^{6}
la xarxa XOR del Capítol 59102710^{27}
una petita xarxa multicapa20.0001060,00010^{60{,}000}

La tercera fila no és un nombre gran, és un de sense sentit: hi ha aproximadament 108010^{80} àtoms a l’univers observable. La cerca no es torna més lenta a mesura que els models creixen; deixa d’existir. Tot el que ve a continuació existeix per culpa d’aquesta taula.

Fixa b=0b = 0 un moment perquè hi hagi un paràmetre i una corba, que és la imatge amb què et va deixar l’últim capítol. Agafa un punt de la corba, a=1a = 1, i pregunta: si moc aa una mica, una quantitat petita hh, quant es mou la pèrdua, per unitat de moviment?

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

Aquesta ràtio és un augment sobre recorregut: el pendent de la recta que passa per dos punts de la corba. A mesura que hh s’encongeix, els dos punts llisquen fins a ajuntar-se i la recta es converteix en la tangent. El seu pendent és la derivada L(a)L'(a): la taxa a què canvia la pèrdua per unitat de canvi en aa. No és una aproximació de res, ni una quantitat infinitament petita. És un límit de ràtios ordinàries.

Val la pena executar-ho, perquè els números diuen una cosa que la definició no diu:

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

Aquí passen dues coses, i totes dues sostenen l’edifici.

L’error no és vagament proporcional a hh: és exactament 7.445h7.445\,h. Divideix hh per cent, i l’error es divideix per cent, amb quatre xifres significatives cada vegada. Aquesta constant no és decoració: és la meitat de la segona derivada de la pèrdua, i és la primera aparició d’una idea que arribarà d’aquí a dues seccions: que una corba prop d’un punt s’assembla a una recta més una correcció proporcional a h2h^2.

I llavors el patró es trenca. Per sota de h=108h = 10^{-8} l’estimació empitjora, i a 101410^{-14} és errònia en la segona xifra. No ha passat res matemàtic; ha passat la capsa de coma flotant del capítol anterior. L(a+h)L(a+h) i L(a)L(a) coincideixen en els seus primers deu dígits, restar-los destrueix aquests dígits, i dividir les restes per un nombre minúscul amplifica el que queda. Hi ha un millor hh — aquí al voltant de 10810^{-8}, aproximadament l’arrel quadrada de l’èpsilon de la màquina — i fer-lo més petit no és ser més curós, sinó menys. Recorda-ho; una funció al final d’aquest capítol en depèn.

El pendent exacte, per càlcul i no per mesura, és 16.385-16.385. Així que podem deixar de mesurar i començar a derivar.

Aquesta és la idea sobre la qual es construeix la resta del curs, dita una vegada i de manera clara.

Compondre dues funcions és alimentar-ne una amb l’altra: (fg)(x)=f(g(x))(f \circ g)(x) = f(g(x)). Res més.

Una xarxa profunda no és com una composició. És una composició. Una capa és una funció; apilar capes és compondre-les; la «profunditat» és el nombre de funcions de la cadena. Quan el Capítol 5 construeix una xarxa, construeix f4f3f2f1f_4 \circ f_3 \circ f_2 \circ f_1 i res més. Això vol dir que la regla de càlcul més important, per als nostres propòsits, és la que deriva una composició:

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

Les taxes es multipliquen. Si gg canvia tres vegades més ràpid que xx, i ff canvia el doble de ràpid que gg, llavors ff canvia sis vegades més ràpid que xx. Aquest és tot el contingut, i és per això que un senyal que torna enrere a través de deu capes es multiplica per deu nombres — motiu pel qual el Capítol 6 dedica una secció a què passa quan tots aquests nombres són una mica menors que u.

Aplica-ho a la nostra pèrdua. Escriu el residual ri=axi+byir_i = a x_i + b - y_i, de manera que L=1nri2L = \frac{1}{n}\sum r_i^2. Cada rir_i depèn de aa a través de la funció interna axia x_i, la derivada de la qual és xix_i. Regla de la cadena, terme a terme:

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

Aquests símbols \partial arrissats marquen una derivada parcial: deriva respecte d’una variable i tracta tota la resta com a constant. No passa res de nou: és el mateix límit d’abans, pres al llarg d’un eix. Recull les parcials en un vector i tens el gradient:

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

Al punt (a,b)=(1,4)(a, b) = (1, 4) aquest vector és (16.385, 8.0)(-16.385,\ 8.0). Dos nombres. La pregunta és què volen dir, i aquest és el primer pas que tothom se salta.

El gradient és un vector de pendents al llarg dels eixos. Això és tot el que hem demostrat. No és obvi — no hauria de ser obvi — que muntar-los en un vector produeixi alguna cosa que apunti cap a cap lloc en particular.

Així que definim el que realment volem. Tria un vector unitari u\mathbf{u}, una direcció. La derivada direccional és la taxa a què canvia la pèrdua quan camines en aquella direcció:

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

La regla de la cadena ho converteix en alguna cosa computable. Caminar al llarg de u\mathbf{u} canvia aa a taxa u1u_1 i bb a taxa u2u_2, i les contribucions se sumen:

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}

La taxa de canvi en qualsevol direcció és el producte escalar del gradient amb aquella direcció. I ara el cop d’efecte, que és una línia de geometria. Escrivint el producte escalar amb l’angle ϕ\phi entre els vectors,

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

ja que u\mathbf{u} té longitud 1. L’únic que controles és cosϕ\cos\phi, que és màxim a ϕ=0\phi = 0 i mínim a mitja volta, ϕ=180\phi = 180 graus. Per tant:

  • L’ascens més pronunciat és al llarg de L\nabla L mateix, i el pendent allà és exactament L\lVert \nabla L \rVert.
  • El descens més pronunciat és al llarg de L-\nabla L, i el pendent allà és L-\lVert \nabla L \rVert.
  • Perpendicularment al gradient, la pèrdua no canvia gens. Per això les línies d’un mapa de contorns creuen el gradient en angle recte.

Aquest és el signe menys. No una convenció, no un canvi de signe que algú va triar: la direcció de disminució més ràpida és el gradient negatiu perquè cosϕ\cos\phi es minimitza a mitja volta, i per cap altra raó.

Com que és una afirmació sobre totes les direccions, provem-la contra totes les direccions. Mostreja’n 3.600, una per cada dècima de grau, i mesura’n cadascuna amb un petit desplaçament:

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

Una cerca que no sap res de gradients, sobre 3.600 direccions, troba la seva pujada més pronunciada a 154,0 graus: la direcció pròpia del gradient, dins de la resolució de 0,1 graus de la cerca. I el pendent que hi troba, 18,2337, és la longitud del gradient amb sis xifres. El teorema no és una història sobre què volen dir els gradients; és un fet mesurable, i aquesta n’és la mesura.

Ara el segon pas que se salta. Sabem quina direcció és avall. D’això no se’n segueix que caminar en aquella direcció redueixi la pèrdua, perquè «avall» és una afirmació sobre un desplaçament infinitesimal i un pas no és infinitesimal.

El pont és la linealització. Prop d’un punt, una funció suau és la seva tangent més una correcció:

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

Aquesta és l’expansió de Taylor de primer ordre. El O(δ2)O(\lVert\boldsymbol{\delta}\rVert^2) descartat és la curvatura: el mateix terme que feia que l’estimació de la taula de pendents s’equivoqués exactament en 7.445h7.445\,h. Posa-hi el pas que volem fer, δ=η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

La pèrdua cau en ηL2\eta \lVert \nabla L \rVert^2. Cada part d’això és no negativa, així que la promesa és real — per a un η\eta prou petit, perquè el terme negligït creix com η2\eta^2 i finalment se’l menja. Aquesta és tota la teoria. Aquí tens la promesa complerta, i després trencada:

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

Llegeix-ho des de baix. A mesura que η\eta s’encongeix, la caiguda obtinguda convergeix cap a la promesa — ràtio 0,99938, després 0,99994 —, que és el teorema de Taylor fent la seva feina. Llegeix-ho des de dalt i, a η=0.2\eta = 0.2, la «caiguda» obtinguda és negativa setze. El pas anava pendent avall i la pèrdua va pujar.

Així que la regla d’actualització és

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

i ve amb una condició que ningú no enuncia: que η\eta sigui prou petit. Prou petit comparat amb què, exactament, és la secció següent.

La taxa d’aprenentatge té un sostre, i es pot calcular

Enllaç a la secció: La taxa d’aprenentatge té un sostre, i es pot calcular

Comença amb la vall més simple que hi ha, f(x)=x2f(x) = x^2, on f(x)=2xf'(x) = 2x. Un pas de gradient descent és

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

La posició es multiplica per (12η)(1 - 2\eta) a cada pas. Això és una successió geomètrica, i les successions geomètriques tenen exactament una regla: s’encongeixen quan el multiplicador és menor que 1 en valor absolut i creixen altrament. Per tant 12η<1\lvert 1 - 2\eta \rvert < 1, que és 0<η<10 < \eta < 1.

La frontera és a η=1\eta = 1 exactament. No «al voltant d’1», no «1 normalment és massa gran». A η=1\eta = 1 el multiplicador és 1-1 i el punt rebota entre xx i x-x per sempre, sense acostar-se ni escapar-se. Per sota, convergeix; per sobre, divergeix. L’interval es torna a partir a η=0.5\eta = 0.5, on el multiplicador canvia de signe: per sota d’això l’aproximació és monòtona, per sobre el punt se sobrepassa i alterna costats, i exactament a 0.50.5 el multiplicador és 0 i un sol pas aterra al mínim.

Quatre règims, a partir de quatre línies d’àlgebra. Ves i travessa tu mateix les fronteres:

14 passos, acaba a x = -0.0836.

Mostra les dades en una taula
Pasxf(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⁩
Descens del gradient, interactiu

Catorze passos a una taxa de 0,1, des de x=1.9x = -1.9, acabant a 0.0836-0.0836. Porta la taxa a 0,5 i el primer pas ja aterra al fons. Porta-la a 0,9 i acaba al mateix 0.0836-0.0836 que 0,1 — mateixa distància, estil oposat, perquè 12η\lvert 1 - 2\eta \rvert és 0,8 en tots dos casos —, però hi arriba fent ziga-zagues a través de la vall en lloc de baixar caminant per un costat.

I ara l’interessant:

14 passos, acaba a x = -1.9000.

Mostra les dades en una taula
Pasxf(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⁩
Descens del gradient, interactiu

Exactament a la frontera. Catorze passos a una taxa d’1, i acaba a 1.9-1.9: precisament on havia començat, sense haver fet res més que rebotar. Una mica més amunt i els rebots creixen en lloc de mantenir-se; a 1,2 surt del gràfic en quatre passos. Una taxa massa gran no convergeix lentament. No convergeix.

Ara la regla general, que surt del mateix argument. El multiplicador 12η1 - 2\eta era realment 1ηf1 - \eta f'', i prop d’un mínim una pèrdua amb múltiples paràmetres té un nombre així per a cada direcció: els valors propis de la matriu de segones derivades. Totes les direccions han de ser estables alhora, així que el sostre el fixa el més gran:

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

Per a f(x)=x2f(x) = x^2, f=2f'' = 2, sostre 1, que és el que acabem de derivar. Per a la nostra cinta, la matriu de segones derivades és 2nAA\frac{2}{n} A^{\top} A amb AA la matriu de dues columnes d’entrades, i els seus valors propis són 2 i 14,89, així que el sostre és 2/14.89=0.134322 / 14.89 = 0.13432. És una predicció amb cinc xifres significatives. Provem-la:

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

Cinc decimals de concordança entre una línia d’àlgebra lineal i cent mil iteracions d’un bucle for.

I aquí és on torna el Capítol 1. Tot el que hi ha a sobre ha fet servir les mesures centrades. Executa el mateix codi amb mil·límetres i grams en brut i els valors propis són 0,0298 i 998,1 en lloc de 2 i 14,89. El sostre cau de 0,134 a 0,002004 — amb la mateixa exactitud, convergint a lr=0.002003 i explotant a lr=0.002004.

Pitjor que el sostre és la ràtio entre els valors propis. El nombre de condició mesura com de lluny d’una forma rodona és la vall: una rasa llarga i prima força una taxa prou petita per a les parets abruptes, i llavors el terra de la rasa es recorre amb el mateix pas de cargol. El nostre passa de 7,44 centrat a 33.452 en brut. Amb la millor taxa que pot prendre cada versió:

característiquesnombre de condiciómillor taxapassos fins a quedar a l’1% de l’òptim
centrades7,440,118410
mil·límetres i grams en brut33.4520,002003779.513

Mateixes dades, mateix codi, mateixa resposta al final — i vuit mil vegades més feina, perquè ningú no va restar una mitjana. Al Capítol 1 la mateixa omissió li va costar al perceptró un factor de sis mil en èpoques, i el diagnòstic allà era geomètric: les dades flotaven lluny de l’origen. És la mateixa geometria aquí amb disfressa d’optimització, i és per això que la normalització de les entrades no és un consell d’higiene, sinó aritmètica.1

Res del que hi ha a sobre necessitava una biblioteca. Aquí tens tot l’optimitzador.

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

La resposta de mínims quadrats en forma tancada per a aquests vuit punts és a=2.100403a = 2.100403, b=0b = 0, amb una pèrdua de 24.59244924.592449. El bucle l’ha trobada amb vuit xifres significatives sense saber que existeix una forma tancada — cosa que importa, perquè a partir del Capítol 5 no n’hi haurà cap.

La trajectòria, perquè mirar-la és el punt:

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

La major part de la distància es cobreix en els dos primers passos, perquè el gradient és més gran quan ets més lluny del fons i s’encongeix a mesura que t’hi acostes. Gradient descent s’alenteix automàticament prop d’un mínim. Això és una virtut i també, al Capítol 6, un problema.

L’argument fins ara té un forat. El pas s’atura quan L=0\nabla L = \mathbf{0}, i n’hem estat dient «el mínim». Un punt amb gradient zero és un punt crític, i ser un mínim és només una de les maneres de ser-ho:

  • un mínim local: pujada en totes les direccions, però potser no el punt més baix d’aquesta mena enlloc;
  • un màxim local: baixada en totes les direccions;
  • un punt de sella: pujada en algunes direccions i baixada en d’altres. La superfície f(x,y)=x2y2f(x,y) = x^2 - y^2f=(2x,2y)\nabla f = (2x, -2y), que és zero a l’origen, on la funció és un mínim al llarg de l’eix xx i un màxim al llarg de l’eix yy alhora.

Gradient descent no els pot distingir, perquè només mira el gradient, i el gradient és zero en tots tres.

La nostra recta té un únic punt crític i és la resposta: una pèrdua d’error quadràtic sobre un model lineal és convexa, un únic bol, i el descens no pot fallar a trobar-ne el mínim global. Aquesta propietat no sobreviu al contacte amb aquest curs. La pèrdua d’una xarxa neuronal no és convexa, i a partir del Capítol 5 «el mínim» no és una cosa que existeixi: n’hi ha molts, de profunditats diferents, i quin obtens depèn d’on has començat. Això és una frase i es queda en una frase, perquè la teoria és gran i la conseqüència pràctica és petita.

Pots veure tota la conseqüència en una sola corba. Pren f(x)=x44x22+x10f(x) = \tfrac{x^4}{4} - \tfrac{x^2}{2} + \tfrac{x}{10}, que té dues valls de profunditats diferents:

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 passos, acaba a x = 0.9456.

Mostra les dades en una taula
Pasxf(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⁩
Descens del gradient, interactiu

Quaranta passos des de x=0.11x = 0.11, establint-se a 0.94560.9456: la més superficial de les dues valls. Ara mou el punt inicial una mica a l’esquerra, fins a 0.100.10. Mateixa taxa, mateixos quaranta passos, i s’estableix a 1.0461-1.0461 en canvi, on la pèrdua és 0,199747 més baixa. La divisòria d’aigües és el llom a 0.1010310.101031, i tota la diferència entre les dues respostes és de quin costat has començat per casualitat.

Caure a la vall superficial és un 56,7% pitjor en pèrdua, i l’algorisme no té cap manera de saber-ho, perquè des de dins d’una vall totes les direccions són de pujada. No hi ha cap reparació per a això en gradient descent i no n’arribarà cap. El que sí que hi ha, a la pràctica, és la troballa que importa molt menys del que aquesta imatge suggereix: en les dimensions molt altes d’una xarxa real, la majoria de punts crítics resulten ser selles més que trampes,2 i el Capítol 5 mesura amb quina freqüència una xarxa petita s’hi queda realment encallada.

Passos més barats: estocàstic, minibatch, momentum

Enllaç a la secció: Passos més barats: estocàstic, minibatch, momentum

Una cosa de grad a sobre t’hauria d’inquietar: suma sobre tot el dataset a cada pas. Vuit peces no són res. Un milió és un milió de càlculs de gradient per moure els paràmetres una vegada.

L’escapatòria és que el gradient és una mitjana, i una mitjana es pot estimar a partir d’una mostra. Calcula’l sobre un grapat aleatori — un minibatch — i fes el pas amb això. L’estimació és sorollosa; també és no esbiaixada, i centenars de passos sorollosos barats guanyen un de sol d’exacte i car. Sobre cent mil peces sintètiques, comptant gradients per exemple en lloc de passos:

mètodepassos fins a quedar a un 0,1% de l’òptimgradients per exemple
full batch7700.000
minibatch de 321003.200
un exemple cada vegada17.58017.580

Dues-centes dinou vegades menys aritmètica per arribar al mateix lloc. I l’extrem — un exemple cada vegada, l’aproximació estocàstica original de Robbins i Monro3no és el guanyador: és cinc vegades pitjor que lots de 32, perquè 32 exemples costen gairebé el mateix que un en hardware que multiplica matrius, mentre que el soroll cau amb l’arrel quadrada de la mida del lot. Aquest compromís és per què cada script d’entrenament que llegiràs mai té un batch_size.

Momentum és l’altra solució barata, i apunta directament a la rasa. En una vall mal condicionada, els passos fan ziga-zaga a través de la direcció estreta mentre s’arrosseguen per la llarga. Momentum manté una mitjana acumulada dels gradients passats, de manera que els components oscil·lants es cancel·len i el consistent s’acumula:4

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

Dues línies extres. A la cinta en brut sense centrar — nombre de condició 33.452, el pitjor cas que tenim —, amb la millor taxa que pot prendre el descens simple:

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%

Un factor de 172 per dues línies de codi. El Capítol 6 converteix això en Adam; el mecanisme ja és aquí.

La comprovació que necessitaràs al Capítol 5

Enllaç a la secció: La comprovació que necessitaràs al Capítol 5

Tots els gradients d’aquest capítol s’han derivat a mà i, per tant, podrien ser erronis. La solució és la taula de pendents del principi: mesura la derivada numèricament i compara. Fes servir la diferència central, L(θ+h)L(θh)2h\frac{L(\theta+h) - L(\theta-h)}{2h}, que cancel·la el terme d’error principal i és molt més precisa per al mateix 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)))

La forma relativa de la comparació importa: una diferència absoluta de 10410^{-4} és un desastre en un gradient de mida 10310^{-3} i irrellevant en un de mida 10610^{6}.

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

La primera línia és el gradient derivat a mà de més amunt. La segona és la mateixa funció amb el factor 2 omès en un component — una errada d’un sol caràcter —, i la comprovació l’atrapa immediatament. Qualsevol cosa per sota d’aproximadament 10710^{-7} és concordança; qualsevol cosa per sobre de 10410^{-4} és un bug. Guarda aquesta funció: el Capítol 5 la fa servir per depurar un motor de diferenciació automàtica, i és l’única raó per la qual es pot trobar un gradient equivocat.

Tot aquest capítol descansava sobre una suposició que no s’ha enunciat mai: que pots escriure L/θ\partial L / \partial \theta.

Per a una recta amb dos paràmetres, això era una línia d’àlgebra. Deixa de ser-ho gairebé de seguida. Demana a un sistema d’àlgebra simbòlica la derivada de la pèrdua d’una xarxa respecte d’un sol pes de la primera capa, per a un sol exemple, i compta l’aritmètica de la resposta:

xarxaoperacions en una derivada parcial
quatre unitats ocultes, una capa40
quatre unitats ocultes, dues capes301
quatre unitats ocultes, tres capes1.717

La tercera fila és una xarxa amb 57 paràmetres — una xarxa tan petita que seria una nota al peu al Capítol 6 —, i escriure’n el gradient a mà vol dir unes 97.869 operacions per a un exemple d’entrenament. No hi ha cap notació que ho rescati. El que ho rescata és l’observació que la regla de la cadena aplicada a una composició té una estructura enorme, que les mateixes quantitats intermèdies apareixen una vegada i una altra, i que calcular-les en l’ordre correcte obté totes les derivades per aproximadament el preu d’una passada endavant. Això és el Capítol 5.

Però abans hi ha un problema més petit, i espera just a continuació.

Ara tenim una màquina que rodarà pendent avall sobre qualsevol pèrdua diferenciable. Apunta-la a la pregunta original de la cinta — acceptar o rebutjar, un objectiu que és 1 o 0 —, posa una sigmoide a la sortida perquè predigui una probabilitat, i minimitza l’error quadràtic. Funcionarà. També gairebé no es mourà quan estigui més equivocada, i el gradient diu per què:

sortida zzprediccióveritatgradient amb error quadràticgradient amb entropia creuada
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

Un model que està confiadament, catastròficament equivocat — predient 0,0000454 quan la resposta és 1 — produeix un gradient d’error quadràtic de 9×1059 \times 10^{-5}. No té ni idea que està en problemes. L’altra columna, d’una pèrdua que encara no hem derivat, informa d’1,0: urgència màxima, exactament on s’ho mereix.

Això planteja la pregunta amb què s’obre el capítol següent. L’últim capítol deia que una pèrdua és una suposició sobre el soroll, i l’error quadràtic assumeix soroll gaussià. Quin model de soroll té una resposta de sí o no — i quina pèrdua en surt quan hi apliques la mateixa derivació?


El mètode és més antic que tot això: Cauchy el va descriure en una nota a l’Académie des Sciences el 1847, com una manera de resoldre sistemes d’equacions caminant pendent avall sobre la suma dels seus residuals quadràtics. També val la pena llegir, al costat d’aquest capítol: An overview of gradient descent optimization algorithms de Sebastian Ruder (arXiv:1609.04747), que cobreix momentum fins a Adam en catorze pàgines llegibles; el capítol 3 de Numerical Optimization de Nocedal i Wright (2a ed., Springer, 2006), el teorema 3.3 del qual dona la taxa de convergència del descens més pronunciat sobre una quadràtica en termes del nombre de condició — és la teoria que hi ha darrere de per què el condicionament decideix el recompte de passos, tot i que tracta la cerca de línia en lloc del sostre de 2/λmax2/\lambda_{\max} amb pas fix mesurat més amunt —, o §5.8 i §7.1 de Mathematics for Machine Learning de Deisenroth, Faisal i Ong per al mateix terreny amb menys maquinària; §6.1 de Understanding Deep Learning de Prince i §4.3 de Deep Learning de Goodfellow, Bengio i Courville; Dive into Deep Learning §12.1–12.3, que té l’anàlisi de minibatch amb més mesures de les que caben aquí; i el capítol 4 de Hands-On Machine Learning de Géron (3a ed.), el tractament més pràctic de la taxa d’aprenentatge com una cosa que ajustes en lloc de derivar. Les notes del MIT 6.390 posen gradient descent abans de la classificació, com fa aquest curs i pel mateix motiu.

  1. LeCun, Y., Bottou, L., Orr, G. B. and Müller, K.-R. Efficient BackProp, a Neural Networks: Tricks of the Trade (Springer, 1998), pp. 9–50. La secció 4.3 dona la recomanació i la secció 5.1 l’argument utilitzat al requadre de detall de més amunt: centrar i escalar les entrades canvia els valors propis de la matriu de segones derivades i, per tant, el nombre de passos, no només la comoditat numèrica.

  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). L’argument que en altes dimensions els punts crítics són aclaparadorament selles més que mínims locals, ja que un mínim exigeix que totes i cadascuna de milers de direccions corbin cap amunt alhora.

  3. Robbins, H. and Monro, S. A Stochastic Approximation Method. Annals of Mathematical Statistics 22(3), pp. 400–407 (1951). L’article que va establir que una estimació sorollosa d’un gradient és suficient, donada una mida de pas que s’encongeixi de la manera correcta.

  4. 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). El mètode de la bola pesada, que és l’actualització momentum de més amunt, vint-i-dos anys abans que backpropagation arribés a aquest camp.

A punt per deixar que triï LIA?

Crea amb tots els models d'IA en un sol lloc — comença gratis avui mateix.