Cross validation per la selezione di un modello di Machine Learning

La Cross validation è una potente tecnica di valutazione e confronto di modelli di Machine Learning, nota in lingua italiana anche come convalida incrociata. Negli scorsi articoli abbiamo addestrato e utilizzato vari algoritmi di classificazione come il Perceptron, la regressione logistica e gli alberi decisionali, unificando i vari step all’interno delle pipeline. In questa lezione studieremo come valutare quale pipeline fornisce i risultati migliori e per far ciò utilizzeremo un procedimento più robusto del semplice confronto dell’accuratezza sul singolo dataset di test. In particolare useremo l’algoritmo di cross validation implementato nella libreria scikit-learn di Python.

Confronto di due Pipeline tramite cross validation

Dopo aver importato il dataset Iris e diviso i dati in traning e test (puoi recuperare il codice qui) creiamo due pipeline che utilizzano rispettivamente il perceptron e la regressione logistica.

lr_pipeline=Pipeline([("vn",SimpleImputer(strategy="mean")), 
                ("sc",StandardScaler()),
                ("lr",LogisticRegression(random_state = 0))])
pcp_pipeline=Pipeline([("vn",SimpleImputer(strategy="mean")),
                ("sc",StandardScaler()), 
                ("pcp",Perceptron(random_state = 0))])

Finora abbiamo confrontato i due algoritmi analizzandone semplicemente l’accuratezza sui dati di test. In questo modo però non stiamo trovando l’algoritmo che performa meglio in generale. Piuttosto stiamo valutando quale algoritmo ha una maggiore accuratezza per quella specifica suddivisione dei dati in training e test.

Non è assolutamente scontato che effettuando una suddivisione diversa (ad esempio scegliendo un random_state differente nella chiamata del metodo train_test_split) otterremo gli stessi risultati. Questo limite può essere superato tramite l’algoritmo di valutazione della cross validation. Nella sua versione k-fold, il metodo prevede di:

  • dividere in dieci parti i soli dati di training. Ogni parte è nota nel gergo tecnico come fold. Il valore di default su scikit-learn è di 5 fold, ma comunque anche 10 è una scelta abbastanza comune;
  • eseguire 10 volte l’addestramento dell’algoritmo, scegliendo come training ogni volta una combinazione diversa dei 9 fold, mentre come test useremo il fold restante;
  • calcolare la media aritmetica delle 10 accuratezze ottenute.

Per quanto non sarebbe troppo difficile implementare manualmente questo algoritmo con Python, all’interno della libreria scikit-learn abbiamo il metodo cross_val_score che fa già tutto il lavoro al posto nostro! Ci basterà eseguire questo codice:

from sklearn.model_selection import cross_val_score
score_lr = cross_val_score(estimator = lr_pipeline,
                                           X = x1,
                                           y = y1,
                                           cv = 10)
score_pcp = cross_val_score(estimator = pcp_pipeline,
                                           X = x1,
                                           y = y1,
                                           cv = 10)

Abbiamo utilizzato il metodo cross_val_score passandogli in input:

  1. la pipeline che vogliamo valutare;
  2. i soli dati di training;
  3. il numero di suddivisioni.

All’interno degli output score_lr e score_pcp abbiamo una lista di 10 accuratezze (pari al numero di folder scegli nell’argomento cv) che possiamo confrontare tramite i consueti indicatori statistici come la media aritmetica, la mediana e la deviazione standard.

In particolare eseguendo questo codice

score_lr.mean(), score_pcp.mean()
score_lr.std(), score_pcp.std()

osserviamo che l’algoritmo di regressione logistica ha una media maggiore nell’accuratezza (0.94 vs 0.88) e una deviazione standard minore (0.05 vs 0.09), di conseguenza è l’algoritmo preferibile tra i due.

implementazione cross validation con Python e Jupyter

Chiarimenti sull’uso e gli scopi della Cross validation

La Cross validation è una tecnica di selezione del modello, il suo obiettivo cioè è valutare nel modo migliorare possibile quale tra due classi di algoritmi performa meglio su un particolare dataset di dati, a prescindere dalla particolare suddivisione tra training e test.

La cross validation però non ci restituisce in output un modello addestrato da portare in produzione! Durante l’algoritmo sono stati eseguiti ben 10 addestramenti, che hanno portato alla creazione di 10 diversi modi di predire la variabile target. Ho utilizzato infatti 10 volte lo stesso algoritmo partendo da input sempre diversi (le 10 combinazioni possibili di 9 folder) e ottenendo quindi output sempre diversi (dove come output intendiamo la formula di predizione generata dall’algoritmo).

Risulta spontaneo allora farsi questa domanda:

Quale delle 10 formule dovrei utilizzare? Forse quella che mi ha dato l’accuratezza maggiore analizzando l’array score_lr ottenuto in output dalla cross validation?

La risposta è no, non devo usare nessuna delle 10 formule! Se ne scegliessi una tornerei al punto di partenza dell’articolo, per cui ci affidiamo a selezionare un algoritmo di Machine Learning sulla base dell’accuratezza ottenuta su una sola particolare suddivisione di training e test.

Il modo giusto di procedere è invece il seguente:

  1. uso la cross validation solamente come criterio di scelta dell’algoritmo (o più in generale della pipeline). In questo caso ad esempio preferiamo la pipeline contenente la regressione logistica;
  2. eseguo nuovamente il metodo fit dell’algoritmo scelto sull’intero dataset di traning. La metodologia di predizione trovata in questo modo sarà quella finale del mio modello;
  3. utilizzo il dataset di test per fare una valutazione finale dell’accuratezza del modello scelto.

Ecco il codice:

log_regression_pipeline.fit(x1,y1)
log_regression_pipeline.score(x2,y2)

Valutazione finale dell’accuratezza

Ci aspettiamo che l’accuratezza ottenuta sui dati di test sia simile alla media delle accuratezze ricavate durante gli step di cross validation. Nel nostro caso ad esempio otteniamo 0.95, quindi un valore anche un po’ più alto!

Tuttavia ciò non è affatto scontato, le combinazioni di dati sono sostanzialmente infinite e potrei teoricamente avere un’accuratezza finale anche più bassa di tutte quelle ottenute durante la fase di cross validation. Le cause di ciò potrebbero essere molte: problemi di overfitting così marcati che la tecnica della cross validation non è riuscita ad alleviare, oppure un eccessivo sbilanciamento dei valori della variabile target tra i dati di training e quelli di test.

In tutti i casi sarebbe metodologicamente sbagliato scegliere un algoritmo diverso da quello proposto dalla cross validation sulla base del risultato deludente ottenuto sui dati di test. Vi ricordo che il compito del Data Scientist è creare un algoritmo robusto che funzioni bene sui futuri dati da classificare (che arriveranno solo dopo la creazione dell’algoritmo), non massimizzare l’accuratezza su un particolare dataset di test.

Se l’accuratezza non fosse sufficiente potrò sicuramente continuare le mie analisi, provando ad inserire nella fase di convalida delle nuove pipeline, che utilizzino altri step e parametri differenti, al fine di trovare un processo migliore di quelli precedenti. Una volta fatto ciò sarebbe importante valutare l’accuratezza finale su un dataset di test diverso da quello usato in precedenza, altrimenti torniamo nel circolo vizioso di valutare i modelli in base al risultato su una particolare suddivisione.

Continua a imparare

Torna in alto
Torna su