Salta al contenuto
Note per Studenti Regolarizzazione delle reti neurali

Regolarizzazione delle reti neurali

In questa pagina 7

Il problema è quello già visto per i modelli lineari (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 →, LASSO e discesa del gradienteIl LASSO è la regressione regolarizzata con penalità $L_1$: minimizza $\sum_i(y_i-x_i^T\beta)^2+\lambda\sum_{j\ge1}|\beta_j|$. A differenza della ridge, porta alcuni coefficienti esattamente a zero (soluzione sparsa, selezione delle feature): geometricamente le curve di livello dell'errore toccano il vincolo $\sum|\beta_j|\le s$ (un rombo) in uno spigolo. Non ha formula chiusa, quindi si minimizza con la discesa del gradiente $W\leftarrow W-\eta,\nabla J(W)$, usando il subgradiente $\operatorname{sign}(\beta_j)$ per il valore assoluto (nel punto 0 qualunque valore in $[-1,1]$). Il passo $\eta$ è critico: per l'errore quadratico converge se $\eta<1/\mu_{\max}(X^TX)$; si può usare $\eta_t=\eta_0/(1+\gamma t)$. L'Elastic Net combina le penalità $L_1$ e $L_2$ con $\lambda_1=\alpha\lambda$, $\lambda_2=(1-\alpha)\lambda$.LASSO e discesa del gradiente →) ma amplificato: una rete con centinaia di migliaia di pesi, come i 407 050407\,050 della rete MNIST 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 capacità sufficiente per memorizzare il training set, rumore compreso.

1. Riconoscere l'overfitting

Si registrano a ogni epoca la loss (e l'accuratezza) sul training e su un insieme di validazione. All'inizio calano entrambe; a un certo punto la loss di training continua a scendere mentre quella di validazione smette di scendere e risale: da lì in poi la rete impara il rumore.

Grafico interattivo: Andamento tipico (schematico): la loss di training scende sempre, quella di validazione ha un minimo e poi risale; il minimo è il punto in cui fermarsi

Nel lab di Keras la rete 784→512→10784\to512\to10 senza regolarizzazione ha loss di training che scende da 0,360{,}36 a 0,0260{,}026 in dieci epoche mentre la loss di validazione passa da 0,0940{,}094 a 0,1270{,}127: segno chiaro di overfitting, anche se l'accuratezza di validazione resta quasi costante (≈0,977\approx0{,}977).

2. Penalità sui pesi: ℓ2\ell_2 e ℓ1\ell_1

Si aggiunge alla loss un termine che penalizza i pesi grandi. Una rete con pesi piccoli è meno sensibile a variazioni dell'ingresso (funzione più «liscia»).

Formula (regolarizzazione ℓ2\ell_2 e ℓ1\ell_1). Con λ≥0\lambda\ge0 forza della penalità: Jℓ2(W)=J(W)+λ∑kwk2,Jℓ1(W)=J(W)+λ∑k∣wk∣.J_{\ell_2}(W)=J(W)+\lambda\sum_k w_k^2,\qquad J_{\ell_1}(W)=J(W)+\lambda\sum_k|w_k|.

L'ℓ2\ell_2 è la ridge regression applicata ai pesi della rete; l'ℓ1\ell_1 è il LASSO (nelle slide si rivede la formula β^lasso=arg⁡min⁡{12∑i(yi−β0−∑jxijβj)2+λ∑j∣βj∣}\hat\beta^{\text{lasso}}=\arg\min\{\frac12\sum_i(y_i-\beta_0-\sum_jx_{ij}\beta_j)^2+\lambda\sum_j|\beta_j|\}).

Grafico interattivo: Le due penalità su un singolo peso: w² (ℓ2) è piatta vicino a 0 e ripida lontano, |w| (ℓ1) ha pendenza costante e un angolo in 0

Cosa cambia nell'aggiornamento. La derivata di λw2\lambda w^2 è 2λw2\lambda w, proporzionale a ww; quella di λ∣w∣\lambda|w| è λsign⁡(w)\lambda\operatorname{sign}(w) per w≠0w\neq0 (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 →), di modulo costante. Per ℓ2\ell_2 il gradiente totale è ∇J+2λW\nabla J+2\lambda W, quindi

W←W−η(∇J+2λW)=(1−2ηλ) W−η∇J.W\leftarrow W-\eta(\nabla J+2\lambda W)=(1-2\eta\lambda)\,W-\eta\nabla J.

A ogni passo il peso viene prima ridotto di un fattore 1−2ηλ1-2\eta\lambda e poi spinto dal gradiente: per questo si parla di weight decay (decadimento dei pesi). Per ℓ1\ell_1 il gradiente della penalità è λsign⁡(w)\lambda\operatorname{sign}(w), una riduzione di ampiezza costante ηλ\eta\lambda verso zero indipendente da ∣w∣|w|: i pesi poco utili raggiungono esattamente zero e la rete diventa sparsa. L'ℓ2\ell_2 riduce molto i pesi grandi ma non li azzera.

Esempio. w=2w=2, ∇J=0\nabla J=0 (solo penalità), η=0,1\eta=0{,}1, λ=0,01\lambda=0{,}01. Con ℓ2\ell_2: w←(1−0,002)⋅2=1,996w\leftarrow(1-0{,}002)\cdot2=1{,}996 per passo. Con ℓ1\ell_1: w←2−0,1⋅0,01=1,999w\leftarrow2-0{,}1\cdot0{,}01=1{,}999 per passo, ma lo stesso passo vale per w=0,001w=0{,}001, che quindi in pochi passi arriva a 00.

In Keras la penalità si aggiunge strato per strato:

python
from tensorflow.keras import regularizers
Dense(512, activation="relu",
      kernel_regularizer=regularizers.l2(0.01),    # sui pesi
      bias_regularizer=regularizers.l2(0.01))      # opzionale, anche sui bias

Scelta di λ\lambda. Troppo piccola: nessun effetto. Troppo grande: i pesi sono schiacciati e la rete va in underfitting. Nel lab con λ=0,01\lambda=0{,}01 applicata a tutti i pesi e i bias di entrambi gli strati, l'accuratezza di test crolla a 0,8440{,}844 con ℓ1\ell_1 e 0,9170{,}917 con ℓ2\ell_2 (contro 0,98150{,}9815 senza penalità): per questa rete e questo dataset 0,010{,}01 è troppo. Come per ridge e LASSO, λ\lambda si sceglie per cross-validation/validazione, partendo da valori molto più piccoli (10−410^{-4}, 10−510^{-5}).

3. Early stopping

L'idea più semplice: fermare l'addestramento quando la loss di validazione smette di migliorare, anche se quella di training scende ancora. Si evita così la zona di overfitting senza alterare la loss.

Definizione (early stopping). Si monitora una metrica di validazione (monitor, tipicamente val_loss). Se non migliora per patience epoche consecutive l'addestramento si interrompe; con restore_best_weights=True si ripristinano i pesi dell'epoca migliore.

python
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor="val_loss", patience=2, restore_best_weights=True)
model.fit(x_train, y_train, epochs=100, validation_split=0.1, callbacks=[es])

La pazienza serve perché la validation loss è rumorosa e può peggiorare per un'epoca e poi migliorare. Il numero di epoche diventa un iperparametro che si sceglie da solo. Va usato un insieme di validazione distinto dal test, altrimenti il test non è più imparziale. Nel lab (patience=2\text{patience}=2) l'accuratezza di test è 0,98000{,}9800.

4. Dropout

Definizione (dropout). Durante l'addestramento, a ogni passo e per ogni neurone di uno strato, con probabilità pp (la rate) l'uscita viene posta a 00. Gli altri neuroni sono riscalati per 1/(1−p)1/(1-p). In inferenza il dropout è spento e si usano tutti i neuroni.

Esempio. Attivazioni a=(0,8; 1,2; 0,5; 2,0)a=(0{,}8;\ 1{,}2;\ 0{,}5;\ 2{,}0), p=0,5p=0{,}5, maschera estratta (1,0,1,0)(1,0,1,0): l'uscita in training è (0,8; 0; 0,5; 0)/0,5=(1,6; 0; 1,0; 0)(0{,}8;\ 0;\ 0{,}5;\ 0)/0{,}5=(1{,}6;\ 0;\ 1{,}0;\ 0). La riscalatura fa sì che il valore atteso (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 →) di ogni attivazione sia lo stesso con e senza dropout (la maschera vale 11 con probabilità 1−p1-p e 00 con probabilità pp): E=(1−p)⋅a1−p+p⋅0=aE=(1-p)\cdot\frac{a}{1-p}+p\cdot0=a. Per questo in inferenza non serve correggere nulla (versione «inverted dropout» usata da Keras e PyTorch).

Perché funziona.

Valori tipici: p=0,5p=0{,}5 sugli strati nascosti grandi (le slide), 0,20{,}2-0,30{,}3 in rete piccole come quella del lab (Dropout(0.2)). Il dropout va dopo l'attivazione di uno strato nascosto, non nell'uscita. Si accompagna di solito a più epoche, perché l'addestramento è più lento.

python
from tensorflow.keras.layers import Dropout
Sequential([Input((28, 28)), Flatten(), Dense(512, activation="relu"),
            Dropout(0.5), Dense(10, activation="softmax")])

5. Altri strumenti

6. Il confronto del laboratorio (MNIST)

Stessa rete 784→512→10784\to512\to10 addestrata dieci epoche con Adam e batch da 3232 (λ=0,01\lambda=0{,}01 per ℓ1\ell_1 e ℓ2\ell_2; dropout 0,50{,}5; batch norm prima e dopo lo strato nascosto; early stopping con pazienza 22). Accuratezza di test:

variante accuratezza di test
nessuna regolarizzazione 0,98150{,}9815
ℓ1\ell_1, λ=0,01\lambda=0{,}01 0,84380{,}8438
ℓ2\ell_2, λ=0,01\lambda=0{,}01 0,91730{,}9173
dropout 0,50{,}5 0,98110{,}9811
batch normalization 0,97720{,}9772
early stopping 0,98000{,}9800

Lettura. Su MNIST con una rete così piccola l'overfitting è lieve e la rete senza regolarizzazione è già ottima: le tecniche che agiscono sui pesi con un λ\lambda elevato peggiorano (underfitting), dropout ed early stopping lasciano l'accuratezza invariata ma tengono la validation loss più bassa (con dropout 0,0750{,}075-0,0840{,}084 contro 0,0940{,}094-0,1270{,}127). Una tecnica di regolarizzazione non va mai applicata alla cieca: si controlla la validazione. Esercizio: Esercizio - Confronto di tecniche di regolarizzazione su MNIST.

7. Errori tipici

  • Scegliere λ\lambda troppo alto (underfitting) o non sceglierlo con la validazione.
  • Usare il test come insieme di validazione per l'early stopping.
  • Dimenticare che il dropout è attivo solo in training (in Keras model.predict e evaluate lo spengono; in PyTorch serve model.eval()).
  • Applicare il dropout allo strato di uscita.
  • Aspettarsi che la regolarizzazione migliori sempre l'accuratezza: se il modello non fa overfitting non serve.

Versione ripasso

Esercizi su questo argomento

Lezioni in cui compare

Teoria collegata