Esercizio - Confronto di tecniche di regolarizzazione su MNIST
Questa pagina non ha ancora la versione ripasso: qui sotto c'è il testo completo.
In questa pagina 5
Testo (laboratorio sulle reti neurali, regolarizzazione). La rete con ReLU e softmax viene addestrata per dieci epoche (Adam, batch , validation_split=0.1) in sei varianti: nessuna regolarizzazione, ( su pesi e bias di entrambi gli strati), (), dropout , batch normalization (dopo il flatten e dopo lo strato nascosto), early stopping (monitor="val_loss", patience=2). Accuratezze di test ottenute:
| variante | accuratezza di test |
|---|---|
| nessuna | |
| dropout | |
| batch normalization | |
| early stopping |
- Perché e peggiorano così tanto? Cosa si prova per rimediare?
- Con una validation loss per epoca e
patience=2, in che epoca si ferma l'addestramento e quali pesi si ripristinano? - Un peso riceve solo la penalità. Con , , quanto vale dopo un passo con e con ? E per ?
- Dropout con su e maschera : uscita in training e perché non serve correggere in inferenza.
Teoria usata: 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 →, 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 →.
1. Perché e peggiorano
Il è applicato a tutti i pesi e i bias, in una rete con parametri. Nella loss totale (o ) la penalità è la somma di centinaia di migliaia di termini: con la penalità iniziale vale ; per pesi inizializzati con valori assoluti tipici di - ( pesi nel solo primo strato) la somma è dell'ordine di - e la penalità di -, contro una cross-entropy iniziale di circa (), quindi il gradiente è dominato dalla penalità: la rete riduce i pesi quasi a zero e non impara (underfitting). Con il rimpicciolimento è costante in valore assoluto e spinge molti pesi esattamente a zero, per questo l'accuratezza () è la più bassa; riduce in proporzione ai pesi ed è più dolce (), ma anche qui è troppo grande.
Rimedi. Provare valori molto più piccoli (, ), scelti per validazione, o penalizzare solo i pesi (non i bias) e solo lo strato più grande. L'overfitting di questa rete è lieve, quindi la regolarizzazione non è obbligatoria.
Dropout ed early stopping non cambiano l'accuratezza ( e contro ) ma, a dieci epoche, dropout tiene la validation loss tra e mentre senza regolarizzazione sale da a : il vantaggio si vede nella curva, non nel test.
2. Early stopping
Epoche e validation loss: , , , , (minimo), , , . Dopo il minimo all'epoca ci sono due epoche consecutive senza miglioramento ( e ): con patience=2 l'addestramento si ferma alla fine dell'epoca . Con restore_best_weights=True si ripristinano i pesi dell'epoca (loss ); senza quell'opzione si terrebbero quelli dell'epoca (peggiori).
3. Weight decay
Regola : . Regola : .
Per : con diventa (la riduzione è proporzionale: quasi nulla); con si sottrae ancora e il peso arriva a (nella pratica oscilla attorno a zero perché il passo è pari al valore). Lo stesso passo costante dell' è ciò che azzera i pesi piccoli e dà modelli sparsi.
4. Dropout
Uscita in training: gli elementi con maschera vanno a zero e gli altri si dividono per , cioè si moltiplicano per : . Perché in inferenza non serve correggere: il valore atteso di una attivazione è , uguale al valore senza dropout; quindi in test si usa la rete completa senza alcuna scala.
Codice
from tensorflow.keras import regularizers
from tensorflow.keras.callbacks import EarlyStopping
modelli = {
"l2": Sequential([Input((28,28)), Flatten(),
Dense(512, activation="relu", kernel_regularizer=regularizers.l2(1e-4)),
Dense(10, activation="softmax")]),
"dropout": Sequential([Input((28,28)), Flatten(), Dense(512, activation="relu"),
Dropout(0.5), Dense(10, activation="softmax")]),
}
es = EarlyStopping(monitor="val_loss", patience=2, restore_best_weights=True)