Dall’overfitting all’eccellenza sfruttare il potere della regolarizzazione
From overfitting to excellence harnessing the power of regularization
Il Ruolo della Regularizzazione: Bilanciare Complessità e Generalizzazione nell’Apprendimento Automatico
Quando si tratta di Apprendimento Automatico, il nostro obiettivo è trovare il modello di ML che fa le migliori previsioni su dati su cui non è stato addestrato.
Per farlo, addestriamo i nostri modelli di ML su dati di addestramento e vediamo come si comportano nel fare previsioni. Poi, confrontiamo le prestazioni delle previsioni sul set di addestramento e sul set di test, ovvero il set con nuovi dati, per decidere quale è il miglior modello di ML tra quelli che stiamo testando per risolvere il problema che stiamo affrontando.
In questo articolo, descriveremo la regularizzazione nell’Apprendimento Automatico come un modo per evitare l’overfitting.
Il problema dell’overfitting nell’Apprendimento Automatico
L’overfitting è un problema che si verifica nell’Apprendimento Automatico ed è dovuto a un modello che è diventato “troppo specializzato e focalizzato” sui dati particolari su cui è stato addestrato e non può generalizzare bene.
- Indicizza i tuoi contenuti Alfresco utilizzando il nuovo connettore Amazon Kendra Alfresco
- Ottimizza la preparazione dei dati con le nuove funzionalità in AWS SageMaker Data Wrangler
- Crea un semplice modulo utente con Python e Tkinter in 5 minuti – Guida per principianti
Mostriamo una figura che descrive le tre condizioni dell’Apprendimento Automatico: overfitting, underfitting e buon adattamento.
Quindi, l’overfitting è come gli studenti che memorizzano le risposte a domande specifiche: è probabile che falliscano il test perché non hanno capito la materia. Hanno solo ricordato come rispondere a alcune domande.
Per quanto riguarda le prestazioni, in generale possiamo capire che un ML sta facendo overfitting quando una metrica che abbiamo scelto per valutare il nostro modello di ML è molto alta (vicina al 100%) sia nel set di addestramento che nel set di test.
Quindi, l’overfitting – così come l’underfitting – è qualcosa che noi, come Data Scientist, dobbiamo assolutamente evitare.
Un modo per evitare l’overfitting è attraverso la regularizzazione. Vediamo come.
Risolvere l’Overfitting tramite la Regularizzazione
La regularizzazione aggiunge un termine di penalità alla funzione di perdita durante l’addestramento del modello: questo “discourage” il modello dal diventare troppo complesso.
L’idea è che limitando la capacità del modello di adattarsi troppo strettamente ai dati di addestramento, possiamo anche ridurne la capacità di adattarsi al rumore o alle variazioni casuali nei dati. In questo modo, evitiamo l’overfitting.
Supponiamo quindi di avere una funzione di costo definita come segue:
Dove abbiamo:
- `Theta` è un estimatore.
- `x` e `y` sono, rispettivamente, la caratteristica e l’etichetta del nostro modello.
Se definiamo il parametro di regolarizzazione come `lambda` e la funzione di regolarizzazione come `omega`, allora la funzione oggettivo regolarizzata è:
Quindi, la funzione da studiare ora è la somma della funzione di costo più una funzione di regolarizzazione.
La funzione di regolarizzazione e il parametro di regolarizzazione possono variare, a seconda del tipo di regolarizzazione che vogliamo utilizzare.
Nel paragrafo successivo, descriveremo i due tipi di funzioni di regolarizzazione più usate nell’Apprendimento Automatico.
Descrizione della Regolarizzazione Lasso e Ridge
Il Modello Regolarizzato Lasso
L’aggiustamento della regolarizzazione Lasso (Least Absolute and Selection Operator) esegue una regolarizzazione L1, che aggiunge una penalità uguale al valore assoluto della magnitudine dei coefficienti. Questo metodo di regolarizzazione spinge i pesi più vicini all’origine aggiungendo un termine di regolarizzazione:
Possiamo aggiungere una penalità di regolarizzazione L1, ad esempio alla MSE (o a qualsiasi altra funzione di costo che vogliamo) in questo modo:
dove abbiamo:
- `n` è il numero totale dei punti/dati che stiamo studiando
- `yi` sono i valori effettivi
- “hat yi” sono i valori predetti dal nostro modello
L’interpretazione geometrica della regolarizzazione Lasso
La regolarizzazione Lasso, sotto il cofano, esegue quella che chiamiamo selezione delle caratteristiche. Diamo un’interpretazione grafica della regolarizzazione Lasso per capire questo fatto. Per semplicità, creeremo un disegno bidimensionale con due pesi, w_1 e w_2:
Le ellissi concentriche arancioni sono la rappresentazione geometrica della funzione di costo che abbiamo scelto (MSE nel nostro caso), mentre il rombo azzurro chiaro è l’interpretazione geometrica della funzione di penalità (L1).
Il nostro obiettivo è minimizzare la funzione di perdita; come possiamo vedere dall’illustrazione sopra, le ellissi possono essere tangenti al rombo solo su uno dei suoi angoli. In questi angoli, uno dei pesi sarà 0. La tangenza può essere meglio visualizzata nell’immagine seguente perché la minimizzazione avviene sulla tangenza delle funzioni, non sull’intersezione tra di loro:
Ora, immaginiamo di fare questo processo per tutti i pesi w_i; alla fine, avremo quello che chiamiamo un modello sparso, il che significa un modello con meno caratteristiche rispetto a quelle iniziali – perché la regolarizzazione Lasso penalizza i pesi portando a 0 i pesi più grandi. Ciò significa che il nostro modello ha eseguito la selezione delle caratteristiche, eliminando alcune caratteristiche (perché i loro pesi sono stati impostati a 0 per semplificare il modello iniziale).
Parlando matematicamente, ricordando che dobbiamo calcolare il gradiente della funzione per minimizzarla, dovremmo calcolare quanto segue:
In questo contesto, sparsità si riferisce al fatto che alcuni parametri hanno un valore ottimale di zero. In altre parole, questa equazione può avere una soluzione numerica: alcune caratteristiche possono essere portate a 0, e questo è chiamato selezione delle caratteristiche.
Il modello regolarizzato di Ridge.
Il modello Ridge esegue una regolarizzazione L2, che aggiunge una penalità uguale al quadrato della magnitudine dei coefficienti. Questa strategia di regolarizzazione spinge i pesi w_i più vicini all’origine aggiungendo un termine di regolarizzazione.
Possiamo aggiungere una penalità di regolarizzazione L2, ad esempio, al MSE (o a qualsiasi altra funzione di costo che vogliamo) nel seguente modo:
L’interpretazione geometrica della regolarizzazione Ridge
Diamo un’interpretazione grafica della regolarizzazione Ridge per capire questo fatto. Per semplicità, creeremo un disegno 2-D con due pesi, w_1 e w_2:
A differenza della regolarizzazione Lasso, Ridge non esegue la selezione delle caratteristiche. Ridge riduce la complessità del modello senza ridurre il numero di variabili indipendenti perché non porta mai a un valore di coefficiente pari a 0. Visualizziamolo con l’aiuto dell’immagine seguente:
Se osserviamo l’immagine sopra, possiamo vedere che le ellissi possono essere tangenti al cerchio (l’interpretazione geometrica della penalizzazione L2) ovunque, il che significa che il modello penalizza i pesi elevati senza ridurli a 0. Ciò significa che il modello finale includerà tutte le variabili indipendenti.
Inoltre, in questo caso, ricordando che dobbiamo calcolare il gradiente della funzione per minimizzarla, dovremmo calcolare quanto segue:
La differenza rispetto alla regolarizzazione Lasso è che l’equazione sopra non può sempre avere una soluzione numerica, ed è per questo che non esegue la selezione delle caratteristiche.
Implementazione dei modelli regolarizzati Ridge e Lasso in Python
Quindi, vediamo come possiamo implementare entrambi questi metodi regolarizzati.
Iniziamo con la regolarizzazione Lasso:
import numpy as npfrom sklearn.datasets import make_regressionfrom sklearn.preprocessing import StandardScalerfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import r2_scorefrom sklearn.linear_model import Lassofrom sklearn.preprocessing import PolynomialFeaturesfrom sklearn.pipeline import make_pipelinefrom sklearn.linear_model import LinearRegression#warningsimport warnings#ignoring warningswarnings.filterwarnings('ignore')# Creare un datasetX, y = make_regression(n_samples=100, n_features=5, noise=10, random_state=42)# Scalare le caratteristichecaler = StandardScaler()X = scaler.fit_transform(X)# Suddividere i dati in set di addestramento e testX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# Adattare un polinomio di grado 6 ai dati di addestramentopoly = PolynomialFeatures(degree=6)X_train_poly = poly.fit_transform(X_train)# Adattare il polinomio di grado 6 ai dati di addestramentopoly_reg = LinearRegression()poly_reg.fit(X_train_poly, y_train)# Valutare il polinomio sui dati di addestramento e testX_test_poly = poly.transform(X_test)y_pred_train = poly_reg.predict(X_train_poly)y_pred_test = poly_reg.predict(X_test_poly)r2_score_poly_train = r2_score(y_train, y_pred_train)r2_score_poly_test = r2_score(y_test, y_pred_test)print(f'R-quadrato del polinomio di grado 6 sul set di addestramento: {r2_score_poly_train: .3f}')print(f'R-quadrato del polinomio di grado 6 sul set di test: {r2_score_poly_test: .3f}')# Adattare un polinomio regolarizzato di grado 6 ai dati di addestramentolasso_reg = make_pipeline(PolynomialFeatures(degree=6), Lasso(alpha=1))lasso_reg.fit(X_train, y_train)# Valutare il polinomio regolarizzato sui dati di testy_pred_lasso = lasso_reg.predict(X_test)r2_score_lasso = r2_score(y_test, y_pred_lasso)print(f'R-quadrato del polinomio regolarizzato di grado 6 sul set di test: {r2_score_lasso: .3f}')
E otteniamo:
R-quadrato del polinomio di grado 6 sul set di addestramento: 1.000R-quadrato del polinomio di grado 6 sul set di test: -84.110R-quadrato del polinomio di grado 6 regolarizzato sul set di test: 0.827
Quindi, come possiamo vedere, il polinomio di grado 6 “standard” fa overfitting perché ha un R² di 1 sul set di addestramento e un valore negativo sul set di test.
Invece, il modello regolarizzato di grado 6 ha un R² accettabile sul set di test, il che significa che ha una buona capacità di generalizzazione. Quindi, la regolarizzazione ha migliorato le prestazioni del modello non regolarizzato.
Ora, facciamo un esempio simile utilizzando il modello Ridge:
import numpy as npfrom sklearn.datasets import make_regressionfrom sklearn.preprocessing import StandardScalerfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import r2_scorefrom sklearn.linear_model import Ridgefrom sklearn.preprocessing import PolynomialFeaturesfrom sklearn.pipeline import make_pipelinefrom sklearn.linear_model import LinearRegression# Creiamo un datasetX, y = make_regression(n_samples=100, n_features=3, noise=5, random_state=42)# Scaliamo le caratteristiche scaler = StandardScaler()X = scaler.fit_transform(X)# Suddividiamo i dati in set di addestramento e testX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# Addestriamo un polinomio di grado 6 sui dati di addestramentopoly = PolynomialFeatures(degree=6)X_train_poly = poly.fit_transform(X_train)# Addestriamo il polinomio di grado 6 sui dati di addestramentopoly_reg = LinearRegression()poly_reg.fit(X_train_poly, y_train)# Valutiamo il polinomio sui dati di addestramento e di testX_test_poly = poly.transform(X_test)y_pred_train = poly_reg.predict(X_train_poly)y_pred_test = poly_reg.predict(X_test_poly)r2_score_poly_train = r2_score(y_train, y_pred_train)r2_score_poly_test = r2_score(y_test, y_pred_test)print(f'R-quadrato del polinomio di grado 6 sul set di addestramento: {r2_score_poly_train}')print(f'R-quadrato del polinomio di grado 6 sul set di test: {r2_score_poly_test}')# Addestriamo un polinomio di grado 6 regolarizzato sui dati di addestramentoridge_reg = make_pipeline(PolynomialFeatures(degree=6), Ridge(alpha=1))ridge_reg.fit(X_train, y_train)# Valutiamo il polinomio regolarizzato sui dati di testy_pred_ridge = ridge_reg.predict(X_test)r2_score_ridge = r2_score(y_test, y_pred_ridge)print(f'R-quadrato del polinomio di grado 6 regolarizzato sul set di test: {r2_score_ridge}')
E otteniamo:
R-quadrato del polinomio di grado 6 sul set di addestramento: 1.0R-quadrato del polinomio di grado 6 sul set di test: -1612.4842791834997R-quadrato del polinomio di grado 6 regolarizzato sul set di test: 0.9266258222037977
Quindi, la regolarizzazione Ridge, anche in questo caso, ha aumentato le prestazioni del modello polinomiale non regolarizzato. Inoltre, funziona ancora meglio del modello Lasso.
Conclusioni
In questo articolo, abbiamo spiegato il problema dell’overfitting e come risolverlo tramite la regolarizzazione.
Ma quando usare un modello regolarizzato e l’altro. Come regola generale:
- È meglio utilizzare la regolarizzazione Ridge quando le caratteristiche sono altamente correlate. Pertanto, è importante studiare la matrice di correlazione prima di decidere quali caratteristiche eliminare dallo studio del nostro problema.
- La regolarizzazione Lasso aiuta a ridurre le caratteristiche in un dataset. La regolarizzazione Lasso seleziona automaticamente un sottoinsieme delle caratteristiche più importanti mentre allo stesso tempo riduce i coefficienti delle caratteristiche meno importanti a zero. Quindi, la regolarizzazione Lasso è utile:
- Per dataset con alta dimensionalità.
- Quando un numero significativo di caratteristiche è correlato.
- Per imporre sparsità al coefficiente del modello.