Salta al contenuto
Note per Studenti Addestramento delle reti neurali - backpropagation e ottimizzatori

Addestramento delle reti neurali - backpropagation e ottimizzatori

In questa pagina 10

La rete di Reti neurali - neuroni e funzioni di attivazioneUn neurone calcola $\hat y=g(w_0+w^\top x)$: somma pesata degli ingressi più bias, poi una funzione di attivazione $g$ non lineare (Perceptron a soglia, sigmoide, tanh, ReLU e varianti). Senza non linearità ogni rete è equivalente a un solo modello lineare. Una rete feed-forward impila strati di neuroni: $a^{(k)}=g(W^{(k)}a^{(k-1)}+b^{(k)})$; con uno strato nascosto è già un approssimatore universale, ma più strati rappresentano funzioni complesse con molti meno neuroni e imparano feature gerarchiche (bordi, parti, oggetti). Lo strato di uscita e la loss si scelgono dal compito: lineare+MSE (regressione), sigmoide+cross-entropy binaria, softmax+cross-entropy (multiclasse). Il numero di parametri di uno strato denso è $n_{in}n_{out}+n_{out}$. Nel lab (Keras, MNIST) una rete 784-512-10 ha 407 050 parametri e supera il 98% di accuratezza.Reti neurali - neuroni e funzioni di attivazione → ha migliaia o milioni di pesi WW (tutti i pesi e i bias raccolti in un vettore). Addestrarla vuol dire trovare i valori di WW per cui le previsioni sul training set sono buone. Il metodo è sempre lo stesso: una funzione di perdita misura l'errore, il suo gradiente indica come cambiare i pesi, si fa un piccolo passo in quella direzione e si ripete.

1. La loss empirica

Definizione (loss e loss empirica). La loss L(f(x(i);W),y(i))\mathcal L(f(x^{(i)};W),y^{(i)}) è il costo associato alla previsione f(x(i);W)f(x^{(i)};W) quando il valore vero è y(i)y^{(i)}. La loss empirica (detta anche funzione obiettivo, funzione di costo, rischio empirico) è la media sul dataset: J(W)=1n∑i=1nL(f(x(i);W), y(i)).J(W)=\frac1n\sum_{i=1}^{n}\mathcal L\big(f(x^{(i)};W),\,y^{(i)}\big).

Le due principali, già viste per l'uscita della rete:

  • regressione, errore quadratico medio: J(W)=1n∑i(y(i)−f(x(i);W))2J(W)=\frac1n\sum_i\big(y^{(i)}-f(x^{(i)};W)\big)^2;
  • classificazione, cross-entropy: J(W)=−1n∑i[y(i)log⁡f(x(i);W)+(1−y(i))log⁡(1−f(x(i);W))]J(W)=-\frac1n\sum_i\big[y^{(i)}\log f(x^{(i)};W)+(1-y^{(i)})\log(1-f(x^{(i)};W))\big] (nelle slide manca il segno meno: senza di esso si massimizzerebbe l'errore).

Esempio. Tre campioni con probabilità predette f=(0,1; 0,8; 0,6)f=(0{,}1;\ 0{,}8;\ 0{,}6) ed etichette y=(1,0,1)y=(1,0,1): le perdite individuali sono −log⁡0,1=2,303-\log0{,}1=2{,}303, −log⁡(1−0,8)=1,609-\log(1-0{,}8)=1{,}609, −log⁡0,6=0,511-\log0{,}6=0{,}511 e la loss empirica vale (2,303+1,609+0,511)/3=1,474(2{,}303+1{,}609+0{,}511)/3=1{,}474. Il primo campione, classificato male con alta confidenza, pesa da solo metà della perdita.

L'obiettivo dell'addestramento è

W∗=arg⁡min⁡WJ(W).W^*=\arg\min_W J(W).

2. Discesa del gradiente

Il gradiente ∇J=∂J/∂W\nabla J=\partial J/\partial W (il vettore delle derivate parziali, Gradiente e direzione di massima crescitaIl gradiente è il vettore delle derivate parziali ∇f(p) = (∂₁f(p), …, ∂ₙf(p)). Se f è C¹ (derivate parziali continue) vale la formula del gradiente D_u f(p) = ∇f(p)·u: tutte le derivate direzionali si ottengono dalle parziali e u ↦ D_u f(p) è lineare. Tra i versori, la crescita è massima lungo ∇f/|∇f| (pendenza |∇f|), minima lungo −∇f/|∇f| (pendenza −|∇f|), nulla lungo le direzioni ortogonali al gradiente. Utili: ∇|x| = x/|x|, ∇φ(|x|) = φ'(|x|) x/|x|.Gradiente e direzione di massima crescita →, Differenziabilità e gradientef è differenziabile in x0 se f(x) = f(x0) + ∇f(x0)·(x − x0) + o(‖x − x0‖): vicino a x0 il grafico si confonde con il piano tangente z = f(x0) + ∇f(x0)·(x − x0). Differenziabile ⇒ continua, derivabile e D_v f = ∇f·v; derivate parziali continue ⇒ differenziabile. Il gradiente indica la direzione di massima crescita (pendenza ‖∇f‖) ed è ortogonale alle curve di livello.Differenziabilità e gradiente →) indica la direzione di massima crescita di JJ. Perché andare nella direzione opposta riduce JJ: per un passo piccolo ΔW=−η∇J\Delta W=-\eta\nabla J lo sviluppo di Taylor al primo ordine (Formula di Taylor con resto di PeanoUna funzione derivabile n volte in x0 si scrive, vicino a x0, come un polinomio di grado al più n (il polinomio di Taylor, costruito con le derivate in x0) più un errore o((x-x0)^n); il polinomio è unico. Per x0 = 0 si chiama sviluppo di Mac-Laurin.Formula di Taylor con resto di Peano →) dà J(W+ΔW)≈J(W)+∇J⋅ΔW=J(W)−η∥∇J∥2J(W+\Delta W)\approx J(W)+\nabla J\cdot\Delta W=J(W)-\eta\|\nabla J\|^2, e ∥∇J∥2≥0\|\nabla J\|^2\ge0: la loss scende, di quanto più è ripido il pendio. Il learning rate η>0\eta>0 è la lunghezza del passo (l'approssimazione vale solo se η\eta è abbastanza piccolo).

Formula (discesa del gradiente).

  1. Inizializza i pesi a caso, W∼N(0,σ2)W\sim\mathcal N(0,\sigma^2).
  2. Ripeti fino a convergenza: calcola ∂J(W)∂W\dfrac{\partial J(W)}{\partial W} e aggiorna W←W−η ∂J(W)∂WW\leftarrow W-\eta\,\dfrac{\partial J(W)}{\partial W}.
  3. Restituisci WW.

Esempio (una sola variabile). J(w)=(w−3)2J(w)=(w-3)^2, derivata 2(w−3)2(w-3), partenza w0=0w_0=0, η=0,1\eta=0{,}1. Ogni passo è w←w−0,1⋅2(w−3)=0,8 w+0,6w\leftarrow w-0{,}1\cdot2(w-3)=0{,}8\,w+0{,}6: 0→0,6→1,08→1,464→1,771→2,017→…0\to0{,}6\to1{,}08\to1{,}464\to1{,}771\to2{,}017\to\dots, che tende a 33 con JJ che scende 9→5,76→3,69→2,36→1,51→0,979\to5{,}76\to3{,}69\to2{,}36\to1{,}51\to0{,}97. Con η=1,1\eta=1{,}1 invece il passo è w←w−2,2(w−3)=−1,2w+6,6w\leftarrow w-2{,}2(w-3)=-1{,}2w+6{,}6: 0→6,6→−1,32→8,18→−3,22…0\to6{,}6\to-1{,}32\to8{,}18\to-3{,}22\dots oscilla e diverge. Un η\eta troppo piccolo è lentissimo, troppo grande diverge: è l'iperparametro più importante.

Perché. L'aggiornamento è w−3←(w−3)−2η(w−3)=(1−2η)(w−3)w-3\leftarrow(w-3)-2\eta(w-3)=(1-2\eta)(w-3): a ogni passo la distanza dal minimo si moltiplica per 1−2η1-2\eta. Converge se ∣1−2η∣<1|1-2\eta|<1, cioè 0<η<10<\eta<1; per η=0,1\eta=0{,}1 il fattore è 0,80{,}8, per η=1,1\eta=1{,}1 è −1,2-1{,}2 (modulo maggiore di 11: la distanza cresce e cambia segno a ogni passo). Per η=0,5\eta=0{,}5 si arriva al minimo in un passo; per η=0,01\eta=0{,}01 il fattore è 0,980{,}98 e servono circa ln⁡0,01/ln⁡0,98≈230\ln0{,}01/\ln0{,}98\approx230 passi per ridurre la distanza al 1%1\%.

Grafico interattivo: Learning rate troppo piccolo (η = 0,01): partendo da w = 0 i passi sono minuscoli (w = 0, 0,06, 0,119, 0,177)

Grafico interattivo: Learning rate troppo grande (η = 1,1): i punti w = 0, 6,6, -1,32, 8,18 si allontanano dal minimo e J cresce

Grafico interattivo: Loss di training nelle epoche con tre learning rate (andamento schematico): troppo piccolo = discesa lenta, giusto = discesa rapida, troppo grande = la loss cresce

Grafico interattivo: J(w) = (w-3)²: discesa del gradiente con η = 0,1 partendo da w = 0 (punti: i primi passi)

Per le reti la superficie J(W)J(W) non è convessa (Funzioni convesse in più variabiliUn insieme C è convesso se contiene il segmento tra due suoi punti; f: C → R è convessa se f(tx + (1−t)y) ≤ t f(x) + (1−t) f(y) per t in [0,1], cioè il grafico sta sotto le corde. Se f è differenziabile, è convessa se e solo se f(y) ≥ f(x) + ∇f(x)·(y − x) (il grafico sta sopra ogni piano tangente). Se f è C² su un aperto convesso, è convessa se e solo se l'hessiana è semidefinita positiva in ogni punto; se è definita positiva ovunque f è strettamente convessa (non vale il viceversa: x⁴). Per una funzione convessa ogni punto critico è un minimo globale.Funzioni convesse in più variabili →; per una funzione convessa ogni minimo locale è globale e la discesa del gradiente lo raggiunge): ha molti minimi locali, punti di sella (punti critici che non sono né massimi né minimi, Massimi e minimi liberi - punti critici e matrice hessianaRegola di Fermat: in un punto interno di massimo o minimo locale, dove f è derivabile, ∇f(p) = 0 (punto critico). Non vale il viceversa: x² − y² ha in (0,0) un punto di sella. Per f ∈ C² in un punto critico interno, criterio dell'hessiana in due variabili: det Hess > 0 e f_xx > 0 → minimo locale stretto; det > 0 e f_xx < 0 → massimo locale stretto; det < 0 → sella; det = 0 → il criterio non decide (x⁴ + y⁴, −x⁴ − y⁴, x⁴ − y⁴) e si studia il segno di f(x) − f(p) direttamente.Massimi e minimi liberi - punti critici e matrice hessiana →) e zone piatte, e il risultato dipende dall'inizializzazione. Per questo bastano raramente ricette ingenue: servono le tecniche dei paragrafi 5-8.

Discesa stocastica e mini-batch

Calcolare il gradiente su tutti gli nn campioni a ogni passo è costoso. Si usa un sottoinsieme:

  • SGD (stochastic gradient descent): si sceglie un campione ii, si calcola ∂Ji/∂W\partial J_i/\partial W e si aggiorna. Facile ma molto rumoroso.
  • Mini-batch SGD: si sceglie un gruppo di BB campioni e si usa il gradiente medio

Formula (mini-batch). ∂J(W)∂W≈1B∑k=1B∂Jk(W)∂W,W←W−η ∂J(W)∂W.\dfrac{\partial J(W)}{\partial W}\approx\dfrac1B\sum_{k=1}^{B}\dfrac{\partial J_k(W)}{\partial W},\qquad W\leftarrow W-\eta\,\dfrac{\partial J(W)}{\partial W}.

Il gradiente è una stima più accurata, la convergenza più regolare e si possono usare learning rate più alti; inoltre il calcolo sul batch si parallelizza sulle GPU.

Termini: epoca = un passaggio completo su tutto il training; batch size BB = campioni per aggiornamento; iterazione = un aggiornamento. Iterazioni per epoca =⌈n/B⌉=\lceil n/B\rceil.

Esempio. MNIST: 60 00060\,000 immagini, B=32B=32: 1 8751\,875 iterazioni per epoca. Con validation_split=0.1 il training scende a 54 00054\,000 e Keras mostra 1 6881\,688 iterazioni (⌈54 000/32⌉\lceil54\,000/32\rceil).

3. Backpropagation

Il gradiente di JJ rispetto a ogni peso, anche di strati lontani dall'uscita, si calcola con la regola della catena.

Teorema (regola della catena). Se y=f(u)y=f(u) e u=g(x)u=g(x) allora dydx=dfdu⋅dudx\dfrac{dy}{dx}=\dfrac{df}{du}\cdot\dfrac{du}{dx} (Regole di derivazioneDerivate delle funzioni elementari e delle loro inverse (arcsin, arctan, settcosh...) e regole di calcolo: linearità, prodotto (Leibniz), quoziente, funzione composta (regola della catena), funzione inversa, f(x)^g(x).Regole di derivazione →). Con più variabili intermedie y=f(u1,…,uk)y=f(u_1,\dots,u_k) e ui=ui(x)u_i=u_i(x) si sommano i contributi di ciascun percorso: dydx=∑i∂f∂uiduidx\dfrac{dy}{dx}=\sum_i\dfrac{\partial f}{\partial u_i}\dfrac{du_i}{dx} (Regola della catena in più variabiliSe x(t) è una curva derivabile e f è differenziabile in x(t₀), allora (f∘x)'(t₀) = ∇f(x(t₀))·x'(t₀) = Σ ∂ᵢf(x(t₀)) xᵢ'(t₀): la variazione di f lungo il moto è il gradiente per la velocità. Serve per derivare composte come f(2t, t²), per ricavare il gradiente da informazioni lungo curve, per le derivate di f(g(s,t)) e per provare che il gradiente è ortogonale alle curve di livello.Regola della catena in più variabili →, Matrice jacobiana e derivata delle funzioni compostePer F: Rn → Rm, F = (f1, …, fm), la matrice jacobiana JF è la matrice m × n con (JF)ij = ∂fi/∂xj: la riga i è il gradiente di fi. Regola della catena: J(f∘g)(x) = Jf(g(x)) · Jg(x); casi frequenti d/dt f(γ(t)) = ∇f(γ(t))·γ'(t) e ∂f/∂x = f_u u_x + f_v v_x. Se det JF(x0) ≠ 0, F è invertibile vicino a x0 e J(F⁻¹) = (JF)⁻¹. Coordinate polari: det J = ρ.Matrice jacobiana e derivata delle funzioni composte →).

La backpropagation applica questa regola partendo dall'uscita e tornando indietro: il fattore comune a più pesi si calcola una volta sola e si riusa. Il costo di tutti i gradienti è dello stesso ordine di un solo forward pass.

Esempio delle slide, a mano

Rete a un nodo: z1=σ(x w1)z_1=\sigma(x\,w_1), y^=z1w2\hat y=z_1w_2 (uscita lineare), perdita L=12(y^−y)2L=\tfrac12(\hat y-y)^2. Dati x=1x=1, w1=0,5w_1=0{,}5, w2=−1w_2=-1, y=1y=1.

Forward pass. z1=σ(0,5)=0,6225z_1=\sigma(0{,}5)=0{,}6225; y^=0,6225⋅(−1)=−0,6225\hat y=0{,}6225\cdot(-1)=-0{,}6225; L=12(−0,6225−1)2=12⋅1,62252=1,316L=\frac12(-0{,}6225-1)^2=\frac12\cdot1{,}6225^2=1{,}316.

Backward pass, dalla perdita ai pesi:

  1. ∂L∂y^=y^−y=−1,6225\dfrac{\partial L}{\partial\hat y}=\hat y-y=-1{,}6225.
  2. Peso più vicino all'uscita: ∂y^∂w2=z1=0,6225\dfrac{\partial\hat y}{\partial w_2}=z_1=0{,}6225, quindi ∂L∂w2=−1,6225⋅0,6225=−1,010\dfrac{\partial L}{\partial w_2}=-1{,}6225\cdot0{,}6225=-1{,}010.
  3. Peso a monte: ∂y^∂z1=w2=−1\dfrac{\partial\hat y}{\partial z_1}=w_2=-1, ∂z1∂w1=σ′(0,5) x=z1(1−z1)x=0,6225⋅0,3775=0,2350\dfrac{\partial z_1}{\partial w_1}=\sigma'(0{,}5)\,x=z_1(1-z_1)x=0{,}6225\cdot0{,}3775=0{,}2350, quindi ∂L∂w1=(−1,6225)⏟∂L/∂y^⋅(−1)⏟∂y^/∂z1⋅0,2350⏟∂z1/∂w1=0,381.\frac{\partial L}{\partial w_1}=\underbrace{(-1{,}6225)}_{\partial L/\partial\hat y}\cdot\underbrace{(-1)}_{\partial\hat y/\partial z_1}\cdot\underbrace{0{,}2350}_{\partial z_1/\partial w_1}=0{,}381.

Passo di discesa con η=0,1\eta=0{,}1: w2←−1−0,1⋅(−1,010)=−0,899w_2\leftarrow-1-0{,}1\cdot(-1{,}010)=-0{,}899, w1←0,5−0,1⋅0,381=0,4619w_1\leftarrow0{,}5-0{,}1\cdot0{,}381=0{,}4619. Ricalcolando: z1=σ(0,4619)=0,6135z_1=\sigma(0{,}4619)=0{,}6135, y^=−0,5515\hat y=-0{,}5515, L=12⋅1,55152=1,204L=\frac12\cdot1{,}5515^2=1{,}204: la perdita è scesa da 1,3161{,}316 a 1,2041{,}204. Altri due passi la portano a 1,1051{,}105.

Formule per una rete a più strati

Si indica con δ(l)=∂J/∂z(l)\delta^{(l)}=\partial J/\partial z^{(l)} l'errore dello strato ll (derivata della loss rispetto alla pre-attivazione).

Formula (backpropagation). Con z(l)=W(l)a(l−1)+b(l)z^{(l)}=W^{(l)}a^{(l-1)}+b^{(l)} e a(l)=g(z(l))a^{(l)}=g(z^{(l)}): δ(L)=∂J∂a(L)⊙g′(z(L)),δ(l)=(W(l+1)⊤δ(l+1))⊙g′(z(l)),\delta^{(L)}=\frac{\partial J}{\partial a^{(L)}}\odot g'\big(z^{(L)}\big),\qquad \delta^{(l)}=\Big(W^{(l+1)\top}\delta^{(l+1)}\Big)\odot g'\big(z^{(l)}\big), ∂J∂W(l)=δ(l) a(l−1)⊤,∂J∂b(l)=δ(l).\frac{\partial J}{\partial W^{(l)}}=\delta^{(l)}\,a^{(l-1)\top},\qquad \frac{\partial J}{\partial b^{(l)}}=\delta^{(l)}. (⊙\odot = prodotto componente per componente.)

Perché, passo per passo. Si lavora componente per componente.

  1. Strato di uscita. JJ dipende da zi(L)z^{(L)}_i solo tramite ai(L)=g(zi(L))a^{(L)}_i=g(z^{(L)}_i): δi(L)=∂J∂ai(L)⋅g′(zi(L))\delta^{(L)}_i=\dfrac{\partial J}{\partial a^{(L)}_i}\cdot g'(z^{(L)}_i) (catena a una variabile). Per il JJ di un campione e uscite indipendenti è la formula vettoriale con ⊙\odot.
  2. Da uno strato al precedente. aj(l)a^{(l)}_j influenza JJ attraverso tutte le zi(l+1)=∑jWij(l+1)aj(l)+bi(l+1)z^{(l+1)}_i=\sum_jW^{(l+1)}_{ij}a^{(l)}_j+b_i^{(l+1)}, quindi si sommano i percorsi (catena in più variabili): ∂J∂aj(l)=∑i∂J∂zi(l+1)∂zi(l+1)∂aj(l)=∑iδi(l+1)Wij(l+1)\dfrac{\partial J}{\partial a^{(l)}_j}=\sum_i\dfrac{\partial J}{\partial z^{(l+1)}_i}\dfrac{\partial z^{(l+1)}_i}{\partial a^{(l)}_j}=\sum_i\delta^{(l+1)}_iW^{(l+1)}_{ij}. Questa somma è la componente jj di W(l+1)⊤δ(l+1)W^{(l+1)\top}\delta^{(l+1)}. Si passa da aa a zz con un'altra catena: δj(l)=∂J∂aj(l) g′(zj(l))\delta^{(l)}_j=\dfrac{\partial J}{\partial a^{(l)}_j}\,g'(z^{(l)}_j).
  3. Gradiente dei pesi. zi(l)=∑jWij(l)aj(l−1)+bi(l)z^{(l)}_i=\sum_jW^{(l)}_{ij}a^{(l-1)}_j+b^{(l)}_i ha derivata aj(l−1)a^{(l-1)}_j rispetto a Wij(l)W^{(l)}_{ij} e 11 rispetto a bi(l)b^{(l)}_i; quindi ∂J∂Wij(l)=δi(l) aj(l−1)\dfrac{\partial J}{\partial W^{(l)}_{ij}}=\delta^{(l)}_i\,a^{(l-1)}_j e ∂J∂bi(l)=δi(l)\dfrac{\partial J}{\partial b^{(l)}_i}=\delta^{(l)}_i. In forma matriciale la prima è il prodotto esterno δ(l)a(l−1)⊤\delta^{(l)}a^{(l-1)\top}.

Il vantaggio: δ(l)\delta^{(l)} si ricava da δ(l+1)\delta^{(l+1)} con un solo prodotto matrice-vettore (Operazioni tra matriciLe matrici m×n formano uno spazio vettoriale (somma e prodotto per scalare elemento per elemento); il prodotto righe per colonne corrisponde alla composizione di funzioni lineari, è associativo ma non commutativo; la trasposta scambia righe e colonne e (AB)^T = B^T A^T.Operazioni tra matrici →), senza ricalcolare nulla da capo.

Caso notevole: sigmoide con cross-entropy. Per un'uscita y^=σ(z)\hat y=\sigma(z) e J=−[ylog⁡y^+(1−y)log⁡(1−y^)]J=-[y\log\hat y+(1-y)\log(1-\hat y)] si procede così. La derivata di log⁡\log è 1/argomento1/\text{argomento} (Esponenziale e logaritmoLa funzione esponenziale a^x (base positiva diversa da 1) e la sua inversa, il logaritmo in base a, con grafici e proprietà.Esponenziale e logaritmo →), e per il secondo termine la catena dà un segno meno: ∂J∂y^=−yy^+1−y1−y^\dfrac{\partial J}{\partial\hat y}=-\dfrac y{\hat y}+\dfrac{1-y}{1-\hat y}. Si porta a denominatore comune: −y(1−y^)+(1−y)y^y^(1−y^)=−y+yy^+y^−yy^y^(1−y^)=y^−yy^(1−y^)\dfrac{-y(1-\hat y)+(1-y)\hat y}{\hat y(1-\hat y)}=\dfrac{-y+y\hat y+\hat y-y\hat y}{\hat y(1-\hat y)}=\dfrac{\hat y-y}{\hat y(1-\hat y)}. Poi σ′(z)=y^(1−y^)\sigma'(z)=\hat y(1-\hat y) (paragrafo precedente), quindi δ(L)=∂J∂y^ σ′(z)=y^−yy^(1−y^)⋅y^(1−y^)=y^−y.\delta^{(L)}=\frac{\partial J}{\partial\hat y}\,\sigma'(z)=\frac{\hat y-y}{\hat y(1-\hat y)}\cdot\hat y(1-\hat y)=\hat y-y. Il termine σ′\sigma' si semplifica: la cross-entropy non soffre della saturazione della sigmoide in uscita. Lo stesso accade con softmax e cross-entropy (δ=y^−y\delta=\hat y-y vettoriale), ed è uno dei motivi per cui si usano insieme.

4. Il problema del gradiente evanescente (e di quello esplosivo)

Nella formula di δ(l)\delta^{(l)} compare il prodotto di molti fattori W⊤W^\top e g′g'. In una rete profonda il gradiente verso i primi strati è un prodotto di tante di queste matrici.

  • Gradiente evanescente (vanishing gradient): se i fattori sono minori di 11 il prodotto tende a 00. Con la sigmoide g′≤0,25g'\le0{,}25: dieci strati danno al più 0,2510≈10−60{,}25^{10}\approx10^{-6}. I primi strati non imparano più.
  • Gradiente esplosivo: se i fattori sono maggiori di 11 il prodotto cresce senza controllo e i pesi diventano enormi o NaN.

Rimedi: attivazioni ReLU, buona inizializzazione, batch normalization, connessioni residue (Reti neurali convolutive (CNN)approfondimento: non nel programma di Telecomunicazioni. Una rete convolutiva (CNN) sostituisce gli strati densi con filtri piccoli che scorrono sull'immagine: ogni neurone vede solo una patch locale (campo recettivo) e i pesi del filtro sono condivisi in tutta l'immagine, quindi i parametri non dipendono dalla dimensione dell'immagine ($K^2C_{in}C_{out}+C_{out}$ per strato) e si conserva l'informazione spaziale. Dimensione dell'uscita: $\lfloor(W-K+2P)/S\rfloor+1$. Pooling (max 2x2, stride 2) sottocampiona e dà invarianza locale; i filtri 1x1 riducono i canali; struttura tipica CONV+ReLU, POOL, ..., FLATTEN, FC, SOFTMAX, addestrata con cross-entropy e backpropagation. Tre strati 3x3 hanno il campo recettivo di un 7x7 con meno parametri e più non linearità (VGG). Architetture: LeNet, AlexNet (ReLU, dropout, data augmentation), VGG, GoogLeNet (moduli Inception), ResNet (blocchi residui $H(x)=F(x)+x$), EfficientNet. Nel lab: CNN su Fashion-MNIST (241 546 parametri) e su CIFAR-10 (122 570).Reti neurali convolutive (CNN) →), gradient clipping (si limita la norma del gradiente).

5. Inizializzazione dei pesi

  • Tutti zero. Ogni neurone di uno strato calcola la stessa uscita e riceve lo stesso gradiente: restano per sempre identici, la rete impara come un neurone solo. Va evitata.
  • Piccoli numeri casuali N(0,σ2)\mathcal N(0,\sigma^2) con σ\sigma piccola: va bene per reti piccole. In una rete profonda (per esempio 1010 strati da 500500 neuroni) la deviazione standard delle attivazioni si restringe strato dopo strato fino a zero, e con essa i gradienti. Con σ\sigma grande le attivazioni di tanh e sigmoide saturano (gradiente nullo).

Idea di Xavier e He. Per uno strato z=∑j=1ninwjxjz=\sum_{j=1}^{n_{in}}w_jx_j con pesi e ingressi indipendenti, a media zero, vale (si veda Varianza e momentiI momenti E[X^k] e i momenti centrati E[(X − μ)^k] descrivono la forma di una legge; la varianza Var(X) = E[(X − μ)²] = E[X²] − E[X]² misura quanto X si disperde attorno alla media, vale Var(aX + b) = a² Var(X) e Var(X) = 0 solo se X è costante.Varianza e momenti →): per un prodotto di variabili indipendenti a media zero Var⁡(wjxj)=E[wj2]E[xj2]=Var⁡(w)Var⁡(x)\operatorname{Var}(w_jx_j)=E[w_j^2]E[x_j^2]=\operatorname{Var}(w)\operatorname{Var}(x); la varianza di una somma di variabili indipendenti è la somma delle varianze (Somma di variabili aleatorie indipendentiSe X e Y sono indipendenti, la legge di Z = X + Y è la convoluzione: p_Z(n) = Σ_k p_X(k) p_Y(n − k) nel discreto, f_Z(z) = ∫ f_X(z − y) f_Y(y) dy nel continuo. Casi notevoli: Bin(n,p) + Bin(m,p) = Bin(n+m,p), Poi(λ) + Poi(μ) = Poi(λ+μ), Geo + Geo con densità (n−1)p²(1−p)^(n−2), Exp(λ) + Exp(λ) = Γ(2,λ), gaussiane indipendenti sommano medie e varianze.Somma di variabili aleatorie indipendenti →), quindi Var⁡(z)=ninVar⁡(w)Var⁡(x)\operatorname{Var}(z)=n_{in}\operatorname{Var}(w)\operatorname{Var}(x). Per non far crescere né restringere la varianza strato dopo strato serve ninVar⁡(w)=1n_{in}\operatorname{Var}(w)=1, cioè Var⁡(w)=1/nin\operatorname{Var}(w)=1/n_{in}. Con la ReLU l'attivazione a=max⁡(0,z)a=\max(0,z) ha E[a2]=12Var⁡(z)E[a^2]=\frac12\operatorname{Var}(z) (se zz è simmetrico attorno a 00 la metà dei valori viene azzerata), e per compensare serve il doppio: Var⁡(w)=2/nin\operatorname{Var}(w)=2/n_{in}.

Formula (inizializzazioni).

  • Glorot / Xavier (per tanh e sigmoide): Var⁡(W)=2nin+nout\operatorname{Var}(W)=\dfrac2{n_{in}+n_{out}} (media tra la condizione in avanti 1/nin1/n_{in} e quella all'indietro 1/nout1/n_{out}).
  • He (per ReLU): Var⁡(W)=2nin\operatorname{Var}(W)=\dfrac2{n_{in}}. La ReLU azzera metà degli ingressi, dimezzando la varianza: si raddoppia per compensare.

Esempio. Strato 784→512784\to512: Xavier dà deviazione standard 2/(784+512)=0,039\sqrt{2/(784+512)}=0{,}039; per uno strato ReLU 512→512512\to512 He dà 2/512=0,0625\sqrt{2/512}=0{,}0625. Keras usa Glorot uniforme di default; con ReLU conviene kernel_initializer="he_normal".

6. Batch normalization

Si normalizzano gli ingressi della rete perché attributi su scale diverse rendono il gradiente sbilanciato; la batch normalization applica la stessa idea agli ingressi di ogni strato nascosto, riducendo la dipendenza dall'inizializzazione e permettendo learning rate più alti. Su un mini-batch B={x1,…,xm}\mathcal B=\{x_1,\dots,x_m\} si calcolano la media e la varianza campionarie (Valore attesoIl valore atteso E[X] = Σ x p_X(x) è la media dei valori di X pesata con le loro probabilità (esiste se la serie converge assolutamente); per una funzione g vale E[g(X)] = Σ g(x) p_X(x) senza trovare la legge di g(X), ed E è lineare: E[aX + bY + c] = aE[X] + bE[Y] + c.Valore atteso →, Varianza e momentiI momenti E[X^k] e i momenti centrati E[(X − μ)^k] descrivono la forma di una legge; la varianza Var(X) = E[(X − μ)²] = E[X²] − E[X]² misura quanto X si disperde attorno alla media, vale Var(aX + b) = a² Var(X) e Var(X) = 0 solo se X è costante.Varianza e momenti →), si standardizza (sottrarre la media e dividere per la deviazione standard dà media 00 e varianza 11) e si lascia alla rete la libertà di cambiare scala e centro:

Formula (batch normalization). μB=1m∑ixi,σB2=1m∑i(xi−μB)2,x^i=xi−μBσB2+ε,yi=γx^i+β.\mu_{\mathcal B}=\frac1m\sum_ix_i,\qquad\sigma^2_{\mathcal B}=\frac1m\sum_i(x_i-\mu_{\mathcal B})^2,\qquad\hat x_i=\frac{x_i-\mu_{\mathcal B}}{\sqrt{\sigma^2_{\mathcal B}+\varepsilon}},\qquad y_i=\gamma\hat x_i+\beta. γ\gamma (scala) e β\beta (traslazione) sono parametri appresi per ogni strato; ε\varepsilon evita la divisione per zero.

Esempio. Batch {2,4,6,8}\{2,4,6,8\}: μ=5\mu=5, σ2=5\sigma^2=5, quindi x^=(−1,342; −0,447; 0,447; 1,342)\hat x=(-1{,}342;\ -0{,}447;\ 0{,}447;\ 1{,}342). Con γ=2\gamma=2, β=1\beta=1: y=(−1,683; 0,106; 1,894; 3,683)y=(-1{,}683;\ 0{,}106;\ 1{,}894;\ 3{,}683). Al momento dell'inferenza media e varianza del batch non esistono: si usano medie mobili calcolate durante l'addestramento (Keras lo fa da solo).

7. Ottimizzatori

La discesa del gradiente semplice avanza lenta nelle direzioni poco ripide e oscilla (jitter) in quelle ripide quando la superficie ha scale molto diverse nelle varie direzioni. Gli ottimizzatori moderni correggono questo.

SGD con momento (momentum). Si accumula una velocità, media mobile dei gradienti passati; ρ\rho fa da attrito (0,9 o 0,99):

vt+1=ρ vt+∇f(xt),xt+1=xt−α vt+1.v_{t+1}=\rho\,v_t+\nabla f(x_t),\qquad x_{t+1}=x_t-\alpha\,v_{t+1}.

Esempio. Con gradiente costante 11 e ρ=0,9\rho=0{,}9 la velocità è 1; 1,9; 2,71;…1;\ 1{,}9;\ 2{,}71;\dots (tende a 1010): i passi si allungano nelle direzioni coerenti, le oscillazioni si smorzano perché i gradienti di segno opposto si cancellano. Nesterov: il gradiente si calcola nel punto già raggiunto con la sola velocità («guardare avanti»).

AdaGrad. Divide il passo per la radice della somma storica dei quadrati dei gradienti di ciascuna coordinata: velocizza le coordinate con gradienti piccoli e rallenta quelle con gradienti grandi. Difetto: la somma cresce sempre e il passo tende a zero.

python
grad_squared += dx * dx
x -= learning_rate * dx / (np.sqrt(grad_squared) + 1e-7)

RMSProp. Come AdaGrad ma con una media mobile esponenziale, così lo storico lontano viene dimenticato:

python
grad_squared = decay_rate * grad_squared + (1 - decay_rate) * dx * dx
x -= learning_rate * dx / (np.sqrt(grad_squared) + 1e-7)

Adam. Combina il momento (primo momento mm) con la normalizzazione di RMSProp (secondo momento vv) e corregge il fatto che mm e vv partono da zero (bias correction):

mt=β1mt−1+(1−β1)gt,vt=β2vt−1+(1−β2)gt2,m^t=mt1−β1t, v^t=vt1−β2t,x←x−αm^tv^t+ε.m_t=\beta_1m_{t-1}+(1-\beta_1)g_t,\quad v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2,\quad\hat m_t=\frac{m_t}{1-\beta_1^t},\ \hat v_t=\frac{v_t}{1-\beta_2^t},\quad x\leftarrow x-\alpha\frac{\hat m_t}{\sqrt{\hat v_t}+\varepsilon}.

Perché la correzione. Con m0=v0=0m_0=v_0=0, al passo 11 si ha m1=(1−β1)g1=0,1 g1m_1=(1-\beta_1)g_1=0{,}1\,g_1: molto più piccolo del gradiente. In generale mt=(1−β1)∑k≤tβ1t−kgkm_t=(1-\beta_1)\sum_{k\le t}\beta_1^{t-k}g_k e, se i gradienti fossero costanti, mt=(1−β1t) gm_t=(1-\beta_1^t)\,g (somma di una serie geometrica di ragione β1\beta_1). Dividere per 1−β1t1-\beta_1^t ripristina gg; lo stesso vale per vtv_t con β2\beta_2. Per tt grande βt→0\beta^t\to0 e la correzione sparisce.

Esempio (primo passo). g1=0,5g_1=0{,}5, β1=0,9\beta_1=0{,}9, β2=0,999\beta_2=0{,}999: m1=0,05m_1=0{,}05, v1=0,00025v_1=0{,}00025; con la correzione m^1=0,05/0,1=0,5\hat m_1=0{,}05/0{,}1=0{,}5 e v^1=0,00025/0,001=0,25\hat v_1=0{,}00025/0{,}001=0{,}25, quindi il passo è α⋅0,5/0,25=α\alpha\cdot0{,}5/\sqrt{0{,}25}=\alpha. Senza correzione sarebbe α⋅0,05/0,0158=3,2 α\alpha\cdot0{,}05/0{,}0158=3{,}2\,\alpha circa. Il primo passo ha ampiezza pari al learning rate, qualunque sia la scala del gradiente.

In pratica: Adam con β1=0,9\beta_1=0{,}9, β2=0,999\beta_2=0{,}999 e learning rate 10−310^{-3} o 5⋅10−45\cdot10^{-4} è un ottimo punto di partenza per quasi tutti i modelli. Nell'esperimento delle slide (rete a tre strati da 128 neuroni su y=sin⁡(5x)+0,5sin⁡(20x)+rumorey=\sin(5x)+0{,}5\sin(20x)+\text{rumore}) Adam converge molto più in fretta di SGD, SGD con momento e RMSProp.

8. Learning rate variabile

Il learning rate è un iperparametro di tutti questi ottimizzatori. Conviene farlo variare nel tempo: grande all'inizio per progredire, piccolo alla fine per assestarsi sul minimo. Strategie: a gradini (per le ResNet si moltiplica per 0,10{,}1 dopo le epoche 3030, 6060 e 9090), lineare, warmup iniziale, inverso della radice, coseno:

αt=12 α0(1+cos⁡tπT)\alpha_t=\tfrac12\,\alpha_0\Big(1+\cos\frac{t\pi}{T}\Big)

con α0\alpha_0 iniziale, TT epoche totali. Esempio: α0=0,1\alpha_0=0{,}1, T=100T=100: α0=0,1\alpha_0=0{,}1 in t=0t=0, 0,0850{,}085 in t=25t=25, 0,050{,}05 in t=50t=50, 0,0150{,}015 in t=75t=75, 00 in t=100t=100.

Grafico interattivo: Learning rate a coseno con α0 = 0,1 e T = 100 epoche

9. Come si addestra una rete: ricetta

  1. Normalizzare/standardizzare gli ingressi (Overfitting, ridge regression e cross-validationUna buona prestazione sul training non basta: serve stimare quella su dati nuovi. La cross-validation (K-fold: $k$ parti, ciascuna a turno come test, errore medio; Monte Carlo: $k$ divisioni casuali con quota di test $q$; leave-one-out se $k=n$) evita di dipendere da una sola divisione casuale. L'errore atteso si scompone in $\text{bias}^2+\text{varianza}+\sigma^2$: i modelli semplici fanno underfitting (bias alto), quelli complessi overfitting (varianza alta). La regolarizzazione aggiunge alla perdita una penalità: la ridge regression minimizza $|y-X\beta|^2+\lambda\sum_{j\ge1}\beta_j^2$ e ha soluzione $\beta=(X^TX+\lambda\tilde I)^{-1}X^Ty$ (l'intercetta non si penalizza, le feature si standardizzano): riduce i coefficienti, rende l'inversa stabile con feature collineari, e $\lambda$ è un iperparametro scelto con la validazione (cross-validation annidata per non contaminare il test).Overfitting, ridge regression e cross-validation →).
  2. Attivazioni ReLU negli strati nascosti, inizializzazione He.
  3. Inserire batch normalization.
  4. Ottimizzatore Adam, learning rate 10−310^{-3}.
  5. Guardare le curve di loss e accuratezza su training e validazione («babysitting»): se la loss di training non scende il learning rate è troppo alto o troppo basso; se la validazione risale c'è overfitting (Regolarizzazione delle reti neuraliUna rete con tanti parametri tende a memorizzare il training set (overfitting): la loss di training scende ma quella di validazione risale. Le tecniche di regolarizzazione limitano la capacità effettiva: penalità sui pesi ($\ell_2$: $J+\lambda|W|_2^2$, il passo diventa $W\leftarrow(1-2\eta\lambda)W-\eta\nabla J$; $\ell_1$: $J+\lambda|W|_1$, porta pesi esattamente a zero), early stopping (si ferma l'addestramento quando la validation loss smette di scendere, con pazienza e ripristino dei pesi migliori), dropout (in training si azzera a caso una frazione $p$ delle attivazioni e si riscala per $1/(1-p)$; in inferenza è spento), batch normalization (effetto collaterale) e data augmentation. Nel lab MNIST con $\lambda=0{,}01$ la penalità $\ell_1$ è troppo forte (accuratezza di test 0,844 contro 0,9815 senza regolarizzazione), mentre dropout e early stopping non peggiorano e tengono la validation loss più bassa.Regolarizzazione delle reti neurali →).
  6. Solo dopo, ottimizzare gli iperparametri: architettura, learning rate, regolarizzazione.

In Keras gli strumenti di monitoraggio sono le callback: ModelCheckpoint (salva i pesi a ogni epoca o solo al migliore valore di val_loss), EarlyStopping (Regolarizzazione delle reti neuraliUna rete con tanti parametri tende a memorizzare il training set (overfitting): la loss di training scende ma quella di validazione risale. Le tecniche di regolarizzazione limitano la capacità effettiva: penalità sui pesi ($\ell_2$: $J+\lambda|W|_2^2$, il passo diventa $W\leftarrow(1-2\eta\lambda)W-\eta\nabla J$; $\ell_1$: $J+\lambda|W|_1$, porta pesi esattamente a zero), early stopping (si ferma l'addestramento quando la validation loss smette di scendere, con pazienza e ripristino dei pesi migliori), dropout (in training si azzera a caso una frazione $p$ delle attivazioni e si riscala per $1/(1-p)$; in inferenza è spento), batch normalization (effetto collaterale) e data augmentation. Nel lab MNIST con $\lambda=0{,}01$ la penalità $\ell_1$ è troppo forte (accuratezza di test 0,844 contro 0,9815 senza regolarizzazione), mentre dropout e early stopping non peggiorano e tengono la validation loss più bassa.Regolarizzazione delle reti neurali →), TensorBoard (cruscotto con curve, istogrammi dei pesi, grafo del modello, da aprire con tensorboard --logdir tb_logs).

Lo stesso addestramento in PyTorch

In Keras fit nasconde tutto; in PyTorch il ciclo si scrive a mano:

python
for epoch in range(epochs):
    model.train()                          # attiva dropout, batch norm in modalità training
    for xb, yb in train_loader:            # mini-batch (DataLoader)
        optimizer.zero_grad()              # azzera i gradienti del passo precedente
        loss = loss_fn(model(xb), yb)      # forward pass e loss (CrossEntropyLoss: vuole i logits)
        loss.backward()                    # backpropagation: riempie p.grad per ogni parametro
        optimizer.step()                   # aggiornamento dei pesi
    model.eval()                           # niente dropout in valutazione
    with torch.no_grad():                  # nessun gradiente in validazione
        ...

Differenze principali dal laboratorio: in PyTorch ottimizzatore e loss non fanno parte del modello, l'attivazione è uno strato a parte (ReLU()), le dimensioni di ingresso si dichiarano (Linear(784, 512)), servono tensori (torch.tensor) e la suddivisione train/validazione e i mini-batch si gestiscono a mano. Più codice, ma ogni passo è visibile; Keras è più semplice, PyTorch più flessibile e comodo da debuggare. Esercizio: Esercizio - Keras e PyTorch a confronto.

Esercizi: Esercizio - Backpropagation a mano su una rete 2-2-1, Esercizio - Discesa del gradiente, momento e Adam a mano.

10. Errori tipici

  • Dimenticare il segno meno nella cross-entropy.
  • Learning rate troppo alto (la loss oscilla o diventa NaN) o troppo basso (la loss quasi non scende).
  • Inizializzare tutti i pesi a zero.
  • Confondere epoca, batch e iterazione.
  • Non azzerare i gradienti in PyTorch (si accumulano) o valutare senza model.eval().
  • Nella batch normalization dimenticare che media e varianza sono quelle del batch in training e quelle mobili in inferenza.

Versione ripasso

Esercizi su questo argomento

Lezioni in cui compare

Teoria collegata