CHE COS'È L'OVERFITTING?
L'overfitting è un problema comune che i data scientist devono affrontare durante la creazione di modelli con elevata complessità. Si verifica quando un modello si adatta molto bene ai dati di addestramento e successivamente si comporta male quando viene testato su nuovi dati.
Questo problema si verifica più spesso quando si costruiscono modelli di rete neurale profonda, che è un modello statistico che rappresenta in modo approssimativo la connettività nel cervello. Questi modelli tendono ad essere complessi poiché possono contenere da centinaia a migliaia di parametri. A causa dell'elevata complessità, questi modelli possono rilevare il rumore casuale come vere tendenze, causando scarse prestazioni quando si effettuano inferenze su nuovi dati.
L'overfitting è una grande preoccupazione per qualsiasi azienda che utilizza modelli di deep learning per fare previsioni. Ad esempio, se un'azienda desidera prevedere la fidelizzazione dei clienti, un modello di overfit può rappresentare rumore casuale e valori anomali nei dati come tendenze statistiche significative. Di conseguenza, il modello avrà prestazioni scadenti se utilizzato per prevedere se un cliente effettuerà un acquisto ripetuto in futuro, con conseguente significativa perdita di entrate per l'azienda.
Diversi metodi sono comunemente usati per prevenire l'overfitting nei modelli di deep learning. La regressione lazo, chiamata anche regolarizzazione L1, è un metodo popolare per prevenire l'overfitting in modelli complessi come le reti neurali. La regolarizzazione L1 funziona aggiungendo un termine di penalità al modello. Questa penalità fa sì che alcuni dei coefficienti nel modello vadano a zero, che puoi interpretare come l'eliminazione dei pesi del modello assegnati a rumore casuale, valori anomali o qualsiasi altra relazione statisticamente insignificante trovata nei dati.
In generale, la regolarizzazione L1 è utile per la fase di selezione delle caratteristiche del processo di creazione del modello. In particolare, puoi usarlo per rimuovere caratteristiche che non sono predittori forti. Ad esempio, quando si prevede la fidelizzazione dei clienti, potremmo avere accesso a funzioni che non sono molto utili per fare previsioni accurate come il nome e l'e-mail del cliente.
Un altro metodo di regolarizzazione è la regressione della cresta, chiamata anche regolarizzazione L2. La regressione della cresta funziona riducendo uniformemente i pesi assegnati alle feature nel modello. Questo metodo è utile quando nel modello sono presenti feature altamente correlate. Negli esempi di fidelizzazione dei clienti, le funzionalità altamente correlate possono essere i dollari spesi per l'ultimo acquisto o il numero di articoli acquistati. Queste due caratteristiche sono altamente correlate perché più articoli un cliente acquista, più soldi spendono. Anche la presenza di feature collineari può influire negativamente sulle prestazioni del modello.
La libreria Python Keras semplifica la creazione di modelli di deep learning. La libreria di deep learning può essere utilizzata per creare modelli per attività di classificazione, regressione e clustering non supervisionate. Inoltre, Keras semplifica anche l'applicazione dei metodi di regolarizzazione L1 e L2 a questi modelli statistici. Sia la regolarizzazione L1 che L2 possono essere applicate ai modelli di deep learning specificando un valore di parametro in una singola riga di codice.
Qui, utilizzeremo i dati di abbandono delle telecomunicazioni per costruire un modello di rete neurale profonda che predice la fidelizzazione dei clienti. I dati contengono informazioni su una società di telecomunicazioni fittizia.
Preparazione dei dati
Per iniziare, importiamo la libreria Pandas e leggiamo i dati di abbandono di Teclo in un frame di dati Pandas:
import pandas as pd
df = pd.read_csv('telco_churn.csv')
Successivamente, mostriamo le prime cinque righe di dati:
print(df.head())
l'output sarà questo :
Per costruire il nostro modello di abbandono, dobbiamo convertire la colonna di abbandono nei nostri dati in valori leggibili dalla macchina. Dove l'abbandono ha un valore di "no", assegneremo un'etichetta "zero" e dove l'abbandono ha un valore di "sì", assegneremo l'etichetta "uno".
Importiamo il pacchetto Numpy e usiamo il metodo where() per etichettare i nostri dati:
import numpy as np
df['Churn'] = np.where(df['Churn'] == 'Yes', 1, 0)
Molti dei campi nei dati sono categoriali. Dobbiamo convertire questi campi in codici categoriali leggibili dalla macchina in modo da poter addestrare il nostro modello. Scriviamo una funzione che prenda un elenco di nomi di colonne categoriali e modifichi il nostro frame di dati per includere i codici categoriali per ogni colonna:
def convert_categories(cat_list):for col in cat_list:
df[col] = df[col].astype('category')
df[f'{col}_cat'] = df[f'{col}_cat'].cat.codes
Definiamo il nostro elenco di colonne categoriali:
category_list = [gender, 'Partner', 'Dependents', 'PhoneService',
'MultipleLines', 'InternetService',
'OnlineSecurity', 'OnlineBackup',
'DeviceProtection', 'TechSupport', 'StreamingTV',
'StreamingMovies', 'Contract', 'PaperlessBilling',
'PaymentMethod']
Successivamente, chiamiamo la nostra funzione con questo elenco e visualizziamo le prime cinque righe di dati:
convert_categories(category_list)
print(df.head())
l'output sarà questo:
Possiamo vedere che il nostro frame di dati ora contiene codici categoriali per ogni colonna categoriale.
Quindi, definiamo il nostro input e output:
X = df[['gender_cat', 'Partner_cat', 'Dependents_cat', 'PhoneService_cat', 'MultipleLines_cat', 'InternetService_cat',
'OnlineSecurity_cat', 'OnlineBackup_cat', 'DeviceProtection_cat', 'TechSupport_cat', 'StreamingTV_cat',
'StreamingMovies_cat', 'Contract_cat', 'PaperlessBilling_cat', 'PaymentMethod_cat','MonthlyCharges''TotalCharges', 'SeniorCitizen', 'tenure']]
y= df['Churn']
Successivamente, importiamo il metodo split train/test per il modulo di selezione del modello in Scikit-learn. Dividiamo i nostri dati per allenamento e test
from sklearn.model_selection import train_test_split
X_train, X_test_hold_out, y_train, y_test_hold_out =
train_test_split(X, y, test_size=0.33)
Reti neurali per la regressione
Per iniziare a costruire il nostro modello di rete neurale di regressione, importiamo la classe del layer denso dal modulo layer in Keras. Importiamo anche la classe sequenziale dal modulo models in Keras e il metodo di accuratezza dal modulo metric in Scikit-learn:
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from sklearn.metrics import accuracy_score
Ora definiamo e adattiamo il nostro modello e adattiamo il modello ai nostri dati di addestramento. Costruiremo una rete neurale con due strati nascosti e 32 neuroni. Utilizzeremo anche 20 epoche, che corrispondono al numero di passaggi attraverso i dati di addestramento.
Definiamo il nostro oggetto modello.
model = Sequential()
Quindi, aggiungiamo uno strato denso usando il metodo add. Dobbiamo passare il numero di caratteristiche, che è la lunghezza dell'elenco delle colonne, e l'input, che è una tupla con la lunghezza dell'elenco delle colonne. Verranno inoltre inizializzati i valori di peso secondo una distribuzione normale e utilizzando una funzione di attivazione dell'unità lineare rettificata (ReLu). La funzione di attivazione è ciò che simula l'attivazione dei neuroni:
model.add(Dense(len(cols),input_shape=(len(cols),),
kernel_initializer='normal', activation='relu'))
Successivamente, aggiungeremo due livelli nascosti usando il metodo add. Questi strati avranno 32 neuroni e utilizzeranno anche una funzione di attivazione ReLu:
model.add(Dense(32, activation='relu'))
model.add(Dense(32, activation='relu'))
Dobbiamo quindi aggiungere il livello di output, che avrà un neurone e una funzione di attivazione softmax. Ciò consentirà al nostro modello di produrre probabilità di classe per prevedere se un cliente abbandonerà:
model.add(Dense(1, activation='softmax'))
model.compile(optimizer = 'adam',loss='binary_crossentropy', metrics
=['accuracy'])
model.fit(X_train, y_train,epochs =20)
l'output sarà questo:
Possiamo vedere che, ad ogni epoca, la perdita generalmente diminuisce e la precisione aumenta.
Ora generiamo previsioni. L'output della previsione è un elenco di probabilità di abbandono corrispondente a ciascun input nei dati del test. Possiamo convertire le previsioni in punteggi binari, dove i valori di probabilità maggiori del 50 percento (0,5) saranno classificati come abbandono, con un'etichetta di uno. In caso contrario, sarà classificato con un'etichetta pari a zero, che corrisponde al cliente che soggiorna presso l'azienda:
y_pred = model.predict(X_test)
y_pred = np.where(y_pred > 0.5, 1, 0)
Calcoliamo anche la precisione del nostro modello:
print("Accuracy: ", accuracy_score(y_pred, y_test))
Vediamo che la precisione del nostro modello è del 77,9 percento, il che è abbastanza buono. Vediamo se possiamo migliorare le prestazioni con la regressione lazo.
Regressione lazo (regolarizzazione L1)
Keras semplifica l'implementazione della regressione lazo con i modelli di rete neurale. Il pacchetto regolarizzatori in Keras ha un metodo che possiamo chiamare, chiamato l1, negli strati della nostra rete neurale. Ciò applicherà termini di penalità ai pesi negli strati che aiuteranno a prevenire il sovradattamento.
In genere, la regressione lazo invia i pesi delle caratteristiche insignificanti a zero, consentendo al modello di includere le caratteristiche più importanti per fare previsioni accurate. Importiamo il pacchetto regolarizzatore da Keras:
from tensorflow.keras import regularizers
Successivamente, definiamo un nuovo oggetto modello, che chiameremo model_lasso.
model_lasso = Sequential()
Nel livello di input, passeremo un valore per kernel_regularizer usando il metodo l1 dal pacchetto regolarizzatori:
model_lasso.add(Dense(len(cols),input_shape=(len(cols),),
kernel_initializer='normal', activation='relu', kernel_regularizer =
regularizers.l1(1e-6)))
Le prossime righe di codice sono identiche al nostro modello di rete neurale iniziale. L'unica differenza è che stiamo lavorando con l'oggetto modello model_lasso, invece del modello:
model_lasso.add(Dense(32, activation='relu'))
model_lasso.add(Dense(32, activation='relu'))
model_lasso.add(Dense(1, activation='sigmoid'))
model_lasso.compile(optimizer = 'adam',loss='binary_crossentropy',
metrics =['accuracy'])
model_lasso.fit(X_train, y_train,epochs =20)
y_pred = model_lasso.predict(X_test)
y_pred = np.where(y_pred > 0.5, 1, 0)
print("Accuracy With Lasso: ", accuracy_score(y_pred, y_test))
La regressione con lazo è un'ottima opzione se nel modello sono presenti molte funzionalità che non contribuiscono positivamente alle prestazioni. Per questo motivo, è utile come strumento di selezione delle funzionalità.
Regressione Ridge (L2)
Anche applicare la regressione della cresta ai modelli di rete neurale è facile in Keras. Simile al metodo lazo, dobbiamo semplicemente chiamare un nome di metodo l2 negli strati della nostra rete neurale. La differenza tra lazo e ridge è che il primo tende a scartare del tutto valori insignificanti, mentre ridge riduce semplicemente l'entità dei pesi nella nostra rete neurale su tutte le caratteristiche. Definiamo un nuovo oggetto modello chiamato model_ridge:
model_ridge = Sequential()
E nel livello di input, useremo il metodo l2:
model_ridge.add(Dense(len(cols),input_shape=(len(cols),),
kernel_initializer='normal', activation='relu', kernel_regularizer =
regularizers.l2(1e-6)))
Il resto è simile a quello che abbiamo fatto sopra:
model_ridge.add(Dense(32, activation='relu'))
model_ridge.add(Dense(32, activation='relu'))
model_ridge.add(Dense(1, activation='sigmoid'))
model_ridge.compile(optimizer = 'adam',loss='binary_crossentropy', metrics =['accuracy'])
model_ridge.fit(X_train, y_train,epochs =20)
y_pred = model_lasso.predict(X_test)
y_pred = np.where(y_pred > 0.5, 1, 0)
print("Accuracy With Ridge: ", accuracy_score(y_pred, y_test))
Con ridge, la precisione è leggermente migliore rispetto alla prima rete neurale che abbiamo costruito e alla rete neurale con lazo. La scelta del miglior metodo di regolarizzazione da utilizzare dipende dal caso d'uso. Se l'utilizzo di tutte le funzionalità di input nel modello è importante, la regressione della cresta potrebbe essere una scelta migliore per la regolarizzazione. Questo può essere il caso in cui alcune funzionalità devono essere mantenute per addestrare il nostro modello.
Ad esempio, una caratteristica debole può essere ancora utile come leva per un'azienda. Potrebbero voler vedere come cambiano le previsioni del modello quando cambia il valore della caratteristica debole anche se non contribuisce fortemente alle prestazioni.
Conclusioni
Prevenire l'overfitting dei modelli è importante per i team di data science che utilizzano modelli complessi come le reti neurali. L'overfitting può avere un impatto significativo sui ricavi di un'azienda se non preso in considerazione. I modelli con molti parametri, come le reti neurali, sono particolarmente inclini all'overfitting e possono dare ai ricercatori un falso senso di buone prestazioni del modello.
In genere, i modelli overfit mostrano prestazioni elevate quando vengono testati sui dati attuali e possono funzionare molto male una volta che il modello viene presentato con nuovi dati. Ad esempio, in caso di abbandono, un modello di overfit può essere in grado di prevedere con elevata precisione se un cliente non effettuerà un acquisto ripetuto. Quando vengono presentati nuovi dati sui clienti, tuttavia, il modello di overfit avrà prestazioni scadenti e non sarà più in grado di prevedere l'abbandono dei clienti.
Questa imprecisione può far sì che le aziende sprechino una notevole quantità di denaro e risorse mirando ai clienti sbagliati con annunci e promozioni, ignorando i clienti che potrebbero effettivamente abbandonare. Per questo motivo, avere una buona conoscenza di come utilizzare la regressione lazo e ridge per prevenire l'overfitting di modelli complessi è un'abilità importante per ogni data scientist.
Comentários