In discesa: Gradient Descent e i due passaggi che tutti saltano
Calcola il limite esatto del learning rate, poi osserva una ricerca brute-force su 3.600 direzioni riscoprire il gradiente.
In questa pagina
Il capitolo precedente si era chiuso con una valle.
Non una valle metaforica: una curva vera, la loss tracciata rispetto a un singolo parametro, che scende e poi risale. E la loss sotto di essa non era stata scelta perché ordinata: era stata derivata da un'affermazione sul rumore nelle misurazioni, e l'errore quadratico era uscito dall'altra parte come conseguenza, non come convenzione.
Quindi abbiamo un paesaggio con un fondo, e un motivo per credere che il fondo sia il posto giusto in cui stare. Quello che non abbiamo è un modo per arrivarci.
Questo capitolo ne costruisce uno, ed è l'algoritmo che allena ogni modello nel resto di questo corso — tutti, senza eccezioni, fino a quelli con centinaia di miliardi di parametri inclusi. Sta in circa venti righe. Le due parti difficili non sono in quelle venti righe, e sono le due cose che quasi ogni spiegazione salta:
- Perché il segno meno. L'aggiornamento sottrae il gradiente. Ogni tutorial lo scrive; pochissimi spiegano perché il gradiente è la direzione che va su, l'unico fatto che rende il segno meno qualcosa di diverso da un atto di fede.
- Quanto grande un passo. «Troppo grande diverge, troppo piccolo è lento» è vero e inutile. Esiste un numero esatto, è calcolabile dalla loss, e questo capitolo lo calcola due volte: una per una parabola giocattolo e una per i dati reali.
L'impostazione, e perché non puoi semplicemente cercare
Link alla sezione: L'impostazione, e perché non puoi semplicemente cercareRiformulato perché questo capitolo stia in piedi da solo: gli otto pezzi dal nastro trasportatore del Capitolo 1, ma con una domanda diversa. Non accetta o rifiuta — quello tornerà più avanti — ma predire il peso di un pezzo dalla sua larghezza.
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 gLe misurazioni sono centrate, esattamente come nel Capitolo 1 e per un motivo che tornerà con gli interessi prima che questo capitolo finisca. Il modello è una retta, , e la loss è l'errore quadratico medio derivato nel capitolo precedente:
Due parametri. Perché non provare semplicemente tanti valori? Facciamolo davvero: una griglia da a e da a , con passi di :
grid 501 x 1001 = 501,501 evaluations in 3.67 s
best found: a = 2.1000, b = -0.0000, L = 24.592450Mezzo milione di valutazioni per fissare due numeri a due cifre decimali — e quel secondo è tempo di parete su una macchina, quindi una nuova esecuzione può finire ovunque tra tre e sei; il conteggio delle valutazioni e il minimo sono la parte che si riproduce. Gradient descent, alla fine di questo capitolo, ottiene quattro cifre decimali in otto passi e la risposta float64 completa in trentasei.
Ma la velocità non è l'argomento, e questo è il punto che decide tutto il corso. La ricerca su griglia costa valutazioni per parametri a valori ciascuno. Con mille valori per asse:
| modello | parametri | valutazioni della griglia |
|---|---|---|
| questa retta | 2 | |
| la rete XOR del Capitolo 5 | 9 | |
| una piccola rete multistrato | 20.000 |
La terza riga non è un numero grande, è un numero privo di significato: nell'universo osservabile ci sono circa atomi. La ricerca non diventa più lenta man mano che i modelli crescono; smette di esistere. Tutto ciò che segue esiste per via di quella tabella.
Una derivata è una misurazione che puoi fare
Link alla sezione: Una derivata è una misurazione che puoi fareFissa per un momento, così c'è un parametro e una curva, cioè l'immagine con cui ti ha lasciato il capitolo scorso. Prendi un punto su di essa, , e chiedi: se sposto di una piccola quantità , di quanto si muove la loss per unità di spostamento?
Quel rapporto è un rise over run: la pendenza della retta che passa per due punti della curva. Man mano che si riduce, i due punti scivolano insieme e la retta diventa la tangente. La sua pendenza è la derivata : il tasso a cui la loss cambia per unità di variazione in . Non un'approssimazione di qualcosa, e non una quantità infinitamente piccola. Un limite di rapporti ordinari.
Vale la pena eseguirla, perché i numeri dicono qualcosa che la definizione non dice:
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-01Qui succedono due cose, ed entrambe reggono il carico.
L'errore non è vagamente proporzionale a : è esattamente . Dividi per cento, l'errore si divide per cento, ogni volta a quattro cifre significative. Quella costante non è decorazione: è metà della seconda derivata della loss, ed è la prima apparizione di un'idea tra due sezioni: vicino a un punto, una curva assomiglia a una retta più una correzione proporzionale a .
E poi lo schema si rompe. Sotto la stima peggiora, e a è sbagliata già alla seconda cifra. Non è successo nulla di matematico; è successo il contenitore floating-point del capitolo scorso. e coincidono nelle prime dieci cifre, sottrarli distrugge quelle cifre, e dividere il relitto per un numero minuscolo amplifica ciò che resta. Esiste un migliore: qui attorno a , circa la radice quadrata dell'epsilon di macchina. Andare più piccolo non è più prudente, è meno. Ricordatelo; una funzione alla fine di questo capitolo dipende da questo.
La pendenza esatta, dal calcolo infinitesimale invece che dalla misurazione, è . Quindi possiamo smettere di misurare e iniziare a derivare.
Composizione, e la chain rule
Link alla sezione: Composizione, e la chain ruleEcco l'idea su cui è costruito il resto del corso, detta una volta, chiaramente.
Comporre due funzioni significa passare una dentro l'altra: . Nient'altro.
Una rete profonda non è come una composizione. È una composizione. Un layer è una funzione; impilare layer significa comporli; la «profondità» è il numero di funzioni nella catena. Quando il Capitolo 5 costruisce una rete, sta costruendo e nient'altro. Il che significa che la regola più importante del calcolo infinitesimale, per i nostri scopi, è quella che differenzia una composizione:
I tassi si moltiplicano. Se cambia tre volte più velocemente di , e cambia due volte più velocemente di , allora cambia sei volte più velocemente di . Questo è tutto il contenuto, ed è il motivo per cui un segnale che passa all'indietro attraverso dieci layer viene moltiplicato per dieci numeri: per questo il Capitolo 6 dedica una sezione a cosa succede quando quei numeri sono tutti leggermente minori di uno.
Usala sulla nostra loss. Scrivi il residuo , così che . Ogni dipende da tramite la funzione interna , la cui derivata è . Chain rule, termine per termine:
Quei simboli ricci indicano una derivata parziale: differenzi rispetto a una variabile e tratti ogni altra come una costante. Non succede nulla di nuovo: è lo stesso limite di prima, preso lungo un asse. Raccogli le derivate parziali in un vettore e ottieni il gradiente:
Nel punto quel vettore è . Due numeri. La domanda è cosa significhino, ed è il primo passaggio che tutti saltano.
Perché il gradiente punta in salita
Link alla sezione: Perché il gradiente punta in salitaIl gradiente è un vettore di pendenze lungo gli assi. Questo è tutto ciò che abbiamo dimostrato. Non è ovvio — non dovrebbe essere ovvio — che assemblarle in un vettore produca qualcosa che punta in una direzione particolare.
Quindi definiamo ciò che vogliamo davvero. Scegli un vettore unitario , una direzione. La derivata direzionale è il tasso a cui la loss cambia mentre cammini in quella direzione:
La chain rule lo trasforma in qualcosa di calcolabile. Camminare lungo cambia al tasso e al tasso , e i contributi si sommano:
Il tasso di variazione in qualunque direzione è il prodotto scalare del gradiente con quella direzione. E ora la battuta finale, che è una riga di geometria. Scrivendo il prodotto scalare con l'angolo tra i vettori,
poiché ha lunghezza 1. L'unica cosa che controlli è , che è massimo a e minimo a mezzo giro, gradi. Quindi:
- La salita più ripida è lungo stesso, e lì la pendenza è esattamente .
- La discesa più ripida è lungo , e lì la pendenza è .
- Perpendicolarmente al gradiente, la loss non cambia affatto. Ecco perché le linee di una mappa a curve di livello incrociano il gradiente ad angolo retto.
Questo è il segno meno. Non una convenzione, non un cambio di segno scelto da qualcuno: la direzione di diminuzione più rapida è il gradiente negativo perché è minimizzato a mezzo giro, e per nessun altro motivo.
Dato che questa è un'affermazione su tutte le direzioni, testiamola contro tutte le direzioni. Campiona 3.600 direzioni, una ogni decimo di grado, e misura ciascuna con un piccolo spostamento:
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 degreesUna ricerca che non sa nulla dei gradienti, su 3.600 direzioni, trova la salita più ripida a 154,0 gradi: la direzione stessa del gradiente, entro la risoluzione di 0,1 gradi della ricerca. E la pendenza che trova lì, 18,2337, è la lunghezza del gradiente a sei cifre. Il teorema non è una storia su cosa significano i gradienti; è un fatto misurabile, e questa è la misurazione.
Perché un piccolo passo in discesa aiuta davvero
Link alla sezione: Perché un piccolo passo in discesa aiuta davveroOra il secondo passaggio saltato. Sappiamo qual è la direzione verso il basso. Non ne segue che camminare in quella direzione abbassi la loss, perché «verso il basso» è un'affermazione su uno spostamento infinitesimale e un passo non è infinitesimale.
Il ponte è la linearizzazione. Vicino a un punto, una funzione liscia è la sua tangente più una correzione:
Questa è l'espansione di Taylor del primo ordine. Il termine scartato è la curvatura: lo stesso termine che rendeva la stima della tabella delle pendenze sbagliata di esattamente . Inserisci il passo che intendiamo fare, :
La loss scende di . Ogni parte di ciò è non negativa, quindi la promessa è reale — per un abbastanza piccolo, perché il termine trascurato cresce come e alla fine se la mangia. Questa è tutta la teoria. Ecco la promessa mantenuta, e poi infranta:
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.999938Leggila dal basso. Man mano che si riduce, il calo ottenuto converge verso quello promesso — rapporto 0,99938, poi 0,99994 — cioè il teorema di Taylor che fa il suo dovere. Leggila dall'alto e a il «calo» ottenuto è meno sedici. Il passo è andato in discesa e la loss è salita.
Quindi la regola di aggiornamento è
e porta con sé una condizione che nessuno enuncia: deve essere abbastanza piccolo. Abbastanza piccolo rispetto a cosa, esattamente, è la prossima sezione.
Il learning rate ha un limite, ed è calcolabile
Link alla sezione: Il learning rate ha un limite, ed è calcolabileParti dalla valle più semplice possibile, , dove . Un passo di gradient descent è
La posizione viene moltiplicata per a ogni passo. È una successione geometrica, e le successioni geometriche hanno una sola regola: si riducono quando il moltiplicatore è minore di 1 in valore assoluto e crescono altrimenti. Quindi , cioè .
Il confine è esattamente a . Non «attorno a 1», non «1 di solito è troppo grande». A il moltiplicatore è e il punto rimbalza per sempre tra e , senza avvicinarsi né scappare. Sotto, converge; sopra, diverge. L'intervallo si divide di nuovo a , dove il moltiplicatore cambia segno: sotto, l'avvicinamento è monotono; sopra, il punto supera il minimo e alterna i lati; ed esattamente a il moltiplicatore è 0 e un singolo passo atterra sul minimo.
Quattro regimi, da quattro righe di algebra. Vai e attraversa tu stesso i confini:
E ora quello interessante:
Ora la regola generale, che cade fuori dallo stesso argomento. Il moltiplicatore era in realtà , e vicino a un minimo una loss con più parametri ha un numero del genere per ogni direzione: gli autovalori della matrice delle seconde derivate. Ogni direzione deve essere stabile insieme alle altre, quindi il limite è fissato dal più grande:
Per , , limite 1, che è ciò che abbiamo appena derivato. Per il nostro nastro, la matrice delle seconde derivate è con la matrice a due colonne degli input, e i suoi autovalori sono 2 e 14,89, quindi il limite è . Questa è una previsione con cinque cifre significative. Testiamola:
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 UPCinque cifre decimali di accordo tra una riga di algebra lineare e centomila iterazioni di un loop for.
Ed ecco dove torna il Capitolo 1. Tutto quanto sopra ha usato misurazioni centrate. Esegui lo stesso identico codice su millimetri e grammi grezzi e gli autovalori sono 0,0298 e 998,1 invece di 2 e 14,89. Il limite crolla da 0,134 a 0,002004 — altrettanto esattamente, convergendo a lr=0.002003 ed esplodendo a lr=0.002004.
Peggio del limite è il rapporto tra gli autovalori. Il numero di condizionamento misura quanto la valle sia lontana dall'essere rotonda: una trincea lunga e sottile impone un tasso abbastanza piccolo per le pareti ripide, e poi il fondo della trincea viene percorso con lo stesso passo da lumaca. Il nostro passa da 7,44 centrato a 33.452 grezzo. Con il miglior tasso che ciascuna versione può prendere:
| feature | numero di condizionamento | miglior tasso | passi per arrivare entro l'1% dell'ottimo |
|---|---|---|---|
| centrate | 7,44 | 0,1184 | 10 |
| millimetri e grammi grezzi | 33.452 | 0,0020037 | 79.513 |
Stessi dati, stesso codice, stessa risposta alla fine — e ottomila volte il lavoro, perché nessuno ha sottratto una media. Nel Capitolo 1 la stessa omissione è costata al perceptron un fattore di seimila in epoche, e la diagnosi lì era geometrica: i dati galleggiavano lontano dall'origine. Qui è la stessa geometria con un costume da ottimizzazione, ed è per questo che la normalizzazione degli input non è un consiglio di igiene ma aritmetica.1
Venti righe
Link alla sezione: Venti righeNulla di quanto sopra aveva bisogno di una libreria. Ecco l'intero ottimizzatore.
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.592448791134984La soluzione dei minimi quadrati in forma chiusa per questi otto punti è , , con una loss di . Il loop l'ha trovata a otto cifre significative senza sapere che esiste una forma chiusa — il che conta, perché dal Capitolo 5 in poi non ce ne sarà una.
La traiettoria, perché guardarla è il punto:
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.592449La maggior parte della distanza viene coperta nei primi due passi, perché il gradiente è massimo quando sei più lontano dal fondo e si riduce man mano che ti avvicini. Gradient descent rallenta automaticamente vicino a un minimo. È una feature ed è anche, nel Capitolo 6, un problema.
Dove altro la pendenza è zero
Link alla sezione: Dove altro la pendenza è zeroL'argomento finora ha un buco. Il passo si ferma quando , e noi lo abbiamo chiamato «il minimo». Un punto con gradiente zero è un punto critico, ed essere un minimo è solo uno dei modi per esserlo:
- un minimo locale: in salita in ogni direzione, ma forse non il punto più basso tra tutti;
- un massimo locale: in discesa in ogni direzione;
- un punto di sella: in salita in alcune direzioni e in discesa in altre. La superficie ha , che è zero all'origine, dove la funzione è un minimo lungo l'asse e un massimo lungo l'asse allo stesso tempo.
Gradient descent non può distinguerli, perché guarda sempre e solo il gradiente, e il gradiente è zero in tutti e tre.
La nostra retta ha un solo punto critico ed è la risposta: una loss di errore quadratico su un modello lineare è convessa, una singola ciotola, e la discesa su di essa non può mancare il minimo globale. Questa proprietà non sopravvive al contatto con questo corso. La loss di una rete neurale non è convessa, e dal Capitolo 5 in poi «il minimo» non è una cosa che esiste: ce ne sono molti, di profondità diverse, e quale ottieni dipende da dove sei partito. Questa è una frase e resta una frase, perché la teoria è grande e la conseguenza pratica è piccola.
Puoi vedere l'intera conseguenza su una curva. Prendi , che ha due valli di profondità diverse:
x = -1.046681 f(x) = -0.352386 minimum
x = 0.101031 f(x) = 0.005026 maximum
x = 0.945649 f(x) = -0.152639 minimumAtterrare nella valle meno profonda è peggio del 56,7% in loss, e l'algoritmo non ha modo di saperlo, perché dall'interno di una valle ogni direzione è in salita. Non c'è riparazione per questo in gradient descent e non ne arriverà una. Quello che c'è, in pratica, è la scoperta che conta molto meno di quanto questa immagine suggerisca: nelle dimensioni molto alte di una rete reale, la maggior parte dei punti critici si rivela essere una sella invece che una trappola,2 e il Capitolo 5 misura quanto spesso una piccola rete si blocchi davvero.
Passi più economici: stocastico, minibatch, momentum
Link alla sezione: Passi più economici: stocastico, minibatch, momentumUna cosa di grad sopra dovrebbe infastidirti: somma sull'intero dataset a ogni passo. Otto pezzi sono nulla. Un milione significa un milione di calcoli di gradiente per muovere i parametri una volta.
La via d'uscita è che il gradiente è una media, e una media può essere stimata da un campione. Calcolalo su una manciata casuale — un minibatch — e fai un passo su quello. La stima è rumorosa; è anche non distorta, e centinaia di passi rumorosi economici battono un passo esatto costoso. Su centomila pezzi sintetici, contando i gradienti per esempio invece dei passi:
| metodo | passi per arrivare entro lo 0,1% dell'ottimo | gradienti per esempio |
|---|---|---|
| full batch | 7 | 700.000 |
| minibatch di 32 | 100 | 3.200 |
| un esempio alla volta | 17.580 | 17.580 |
Duecentodiciannove volte meno aritmetica per raggiungere lo stesso punto. E l'estremo — un esempio alla volta, l'approssimazione stocastica originale di Robbins e Monro3 — non è il vincitore: è cinque volte peggiore dei batch da 32, perché 32 esempi costano quasi nulla più di uno su hardware che moltiplica matrici, mentre il rumore cala con la radice quadrata della dimensione del batch. Questo trade-off è il motivo per cui ogni script di training che leggerai mai contiene un batch_size.
Momentum è l'altra correzione economica, e mira dritto alla trincea. In una valle mal condizionata i passi zigzagano attraverso la direzione stretta mentre strisciano lungo quella lunga. Momentum mantiene una media mobile dei gradienti passati, così le componenti oscillanti si annullano e quella coerente si accumula:4
Due righe in più. Sul nastro grezzo non centrato — numero di condizionamento 33.452, il caso peggiore che abbiamo — al miglior tasso che la discesa semplice può prendere:
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 fattore di 172 per due righe di codice. Il Capitolo 6 lo trasforma in Adam; il meccanismo è già qui.
Il controllo che ti servirà nel Capitolo 5
Link alla sezione: Il controllo che ti servirà nel Capitolo 5Ogni gradiente in questo capitolo è stato derivato a mano e quindi potrebbe essere sbagliato. La correzione è la tabella delle pendenze dall'inizio: misura numericamente la derivata e confronta. Usa la differenza centrale, , che annulla il termine di errore principale ed è molto più accurata per lo stesso .
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 del confronto conta: una differenza assoluta di è un disastro su un gradiente di dimensione e irrilevante su uno di dimensione .
relative error: 1.8929136036763527e-11
with 2 dropped: 0.33333333331650744La prima riga è il gradiente derivato a mano qui sopra. La seconda è la stessa funzione con il fattore 2 lasciato fuori da una componente — un refuso di un solo carattere — e il controllo lo intercetta immediatamente. Qualunque cosa sotto circa è accordo; qualunque cosa sopra è un bug. Tieni questa funzione: il Capitolo 5 la usa per fare debug di un motore di differenziazione automatica, ed è l'unico motivo per cui un gradiente sbagliato sia trovabile.
Dove si va da qui
Link alla sezione: Dove si va da quiTutto in questo capitolo si è retto su un'assunzione mai dichiarata: che tu possa scrivere .
Per una retta con due parametri, era una riga di algebra. Smette quasi subito di esserlo. Chiedi a un sistema di algebra simbolica la derivata della loss di una rete rispetto a un singolo peso del primo layer, per un singolo esempio, e conta l'aritmetica nella risposta:
| rete | operazioni in una derivata parziale |
|---|---|
| quattro unità nascoste, un layer | 40 |
| quattro unità nascoste, due layer | 301 |
| quattro unità nascoste, tre layer | 1.717 |
La terza riga è una rete con 57 parametri — una rete così piccola che nel Capitolo 6 sarebbe una nota a piè di pagina — e scrivere il suo gradiente a mano significa circa 97.869 operazioni per un esempio di training. Non esiste una notazione che salvi questo. A salvarlo è l'osservazione che la chain rule applicata a una composizione ha un'enorme struttura, che le stesse quantità intermedie compaiono più e più volte, e che calcolarle nell'ordine giusto dà tutte le derivate più o meno al prezzo di un forward pass. Questo è il Capitolo 5.
Ma prima c'è un problema più piccolo, e ci aspetta subito.
Ora abbiamo una macchina che rotolerà in discesa su qualunque loss differenziabile. Puntala alla domanda originale del nastro — accettare o rifiutare, un target che è 1 o 0 — metti una sigmoide sull'output così che predica una probabilità, e minimizza l'errore quadratico. Funzionerà. Ma si muoverà appena proprio quando è più in errore, e il gradiente spiega perché:
| output | predizione | verità | gradiente con errore quadratico | gradiente con cross-entropy |
|---|---|---|---|---|
| 0,5000 | 1 | |||
| 0,1192 | 1 | |||
| 0,0025 | 1 | |||
| 1 |
Un modello che è sicuro, catastroficamente sbagliato — predice 0,0000454 quando la risposta è 1 — produce un gradiente di errore quadratico pari a . Non ha idea di essere nei guai. L'altra colonna, da una loss che non abbiamo ancora derivato, riporta 1,0: urgenza massima, esattamente dove è meritata.
Il che solleva la domanda con cui si apre il prossimo capitolo. Il capitolo scorso diceva che una loss è un'assunzione sul rumore, e l'errore quadratico assume rumore gaussiano. Quale modello di rumore ha una risposta sì-o-no — e quale loss esce quando applichi la stessa derivazione?
Fonti e metodo
Link alla sezione: Fonti e metodoIl metodo è più antico di tutti questi: Cauchy lo descrisse in una nota all'Académie des Sciences nel 1847, come modo per risolvere sistemi di equazioni camminando in discesa sulla somma dei loro residui quadratici. Da leggere accanto a questo capitolo anche: An overview of gradient descent optimization algorithms di Sebastian Ruder (arXiv:1609.04747), che copre momentum fino ad Adam in quattordici pagine leggibili; il capitolo 3 di Numerical Optimization di Nocedal e Wright (2ª ed., Springer, 2006), il cui teorema 3.3 dà il tasso di convergenza della steepest descent su una quadratica in termini del numero di condizionamento — è la teoria dietro al motivo per cui il condizionamento decide il conteggio dei passi, anche se tratta la line search invece del limite a passo fisso misurato sopra — oppure §5.8 e §7.1 di Mathematics for Machine Learning di Deisenroth, Faisal e Ong per lo stesso terreno con meno apparato; §6.1 di Understanding Deep Learning di Prince e §4.3 di Deep Learning di Goodfellow, Bengio e Courville; Dive into Deep Learning §12.1–12.3, che contiene l'analisi del minibatch con più misurazioni di quante ce ne stiano qui; e il capitolo 4 di Hands-On Machine Learning di Géron (3ª ed.), il trattamento più pratico del learning rate come qualcosa che si regola invece di derivare. Gli appunti MIT 6.390 mettono gradient descent prima della classificazione, come fa questo corso e per lo stesso motivo.
Riferimenti
Link alla sezione: Riferimenti-
LeCun, Y., Bottou, L., Orr, G. B. e Müller, K.-R. Efficient BackProp, in Neural Networks: Tricks of the Trade (Springer, 1998), pp. 9–50. La sezione 4.3 dà la raccomandazione e la sezione 5.1 l'argomento usato nel riquadro di dettaglio sopra: centrare e scalare gli input cambia gli autovalori della matrice delle seconde derivate, e quindi il numero di passi, non solo il comfort numerico. ↩
-
Dauphin, Y. N., Pascanu, R., Gulcehre, C., Cho, K., Ganguli, S. e Bengio, Y. Identifying and attacking the saddle point problem in high-dimensional non-convex optimization, arXiv:1406.2572 (2014). L'argomento secondo cui in alte dimensioni i punti critici sono in stragrande maggioranza selle invece che minimi locali, poiché un minimo richiede che ognuna di migliaia di direzioni curvi verso l'alto contemporaneamente. ↩
-
Robbins, H. e Monro, S. A Stochastic Approximation Method. Annals of Mathematical Statistics 22(3), pp. 400–407 (1951). L'articolo che stabilì che una stima rumorosa di un gradiente è sufficiente, dato uno step size che si riduce nel modo giusto. ↩
-
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). Il metodo heavy-ball, che è l'aggiornamento momentum sopra, ventidue anni prima che backpropagation raggiungesse questo campo. ↩