Perchè utilizzare train_test_split di scikit-learn spesso non è ottimale?

Articolo in lingua originale di  Daniel Klitzke

Sebbene la suddivisione dei dati in dati di training e di validation sembri semplice, può essere fonte di molti errori, soprattutto di valutazioni non significative. I punti chiave da considerare sono:

  • Assicurarsi che tutti i casi importanti per il caso d’uso siano rappresentati nella valutazione.
  • Assicurarsi che la suddivisione misuri la generalizzazione richiesta per il caso d’uso.
  • Fare attenzione ai duplicati che possono rendere i risultati della valutazione migliori di quelli che sono.
  • Considerare le caratteristiche di problemi come la previsione delle serie temporali nella suddivisione per evitare perdite e, quindi, risultati di valutazione inaffidabili.

Per maggiori dettagli visitate il sito https://renumics.com/solutions/workshop-dcai/ o Spotlight, lo strumento gratuito per la raccolta dei dati.

Introduzione

Tutti amano la semplicità di scikit-learn e la famosissima funzione train_test_split è parte di milioni di tutorial sul machine learning. Tuttavia, il suo utilizzo in problemi reali di apprendimento automatico spesso vi spezzerà il collo! In questo breve articolo, vi spiegherò perché e vi collegherò ad alcune risorse che possono aiutarvi a scegliere saggiamente la divisione train/test.

(L’uso della funzione train_test_split di scikit-learn è un metodo semplice per suddividere i dati in modo casuale, ma non è sempre la soluzione migliore.)

Testate ciò che deve essere testato

La suddivisione casuale e l’analisi di metriche globali come l’accuratezza sono facili e veloci, ma cosa succede se ci sono 20 diversi sottogruppi di campioni che devono essere classificati correttamente per rendere fattibile il vostro caso d’uso? E se ci fossero casi limite fortemente sottorappresentati ma altrettanto importanti, ad esempio i casi in cui la macchina si guasta nel caso d’uso della manutenzione predittiva?

(Esplorare un dataset riducendone le features a due dimensioni tramite UMAP può generare intuizioni su quali sottogruppi esistano e come dovrebbero essere divisi tra training e test)

Assicuratevi di sapere quali sottogruppi esistano nei vostri dati! Con questo intendo quelli facilmente riconoscibili, ad esempio utilizzando le etichette di classe, ma anche quelli non esplicitamente indicati. In molti casi, si avranno molti gruppi diversi all’interno di una stessa classe, ad esempio, in un contesto di manutenzione predittiva, si potrebbero avere macchine normalmente funzionanti con rumore di fondo forte e silenzioso. Ecco i miei consigli principali per trattare i sottogruppi nei dati:

  • Esplorate i vostri dati nel contesto del caso d’uso, ad esempio con Spotlight
  • Utilizzate la riduzione della dimensionalità come modo per valutare visivamente gruppi e somiglianze tra i dati, ad esempio con UMAP
  • Utilizzate l’analisi automatica dei sottogruppi ad esempio attraverso features di clustering con scikit-learn o librerie specializzate come pysubgroup
  • Calcolate le metriche sui sottogruppi identificati utilizzando pacchetti come fairlearn

Inoltre, assicuratevi di identificare  i casi limite e i sottogruppi meno rappresentati includendoli nel test set. Questi suggerimenti possono aiutarvi a riguardo:

  • Utilizzare tecniche di riconoscimento degli outlier per trovarer campioni di dati insoliti, ad esempio con PyOD
  • Per i dati non strutturati, sruttate gli strumenti EDA ce consentono di identificare pattern insoliti nei dati e di visualizzare direttamente dati non strutturati (immagini, audio, serie temporali ecc.), ad esempio Spotlight
  • Quando utilizzate funzioni come train_test_split in scikit-learn, considerate di utilzizare il parametro stratify per assicurarvi che le classi più piccole siano rappresentate sia nel training che nel test (https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)

Testate la generalizzazione richiesta nel caso d’uso

Pensate a quale generalizzazione è richiesta nel vostro caso d’uso. Se state progettando un sistema di manutenzione predittiva, ad esempio, potrebbero esserci i seguenti requisiti di generalizzazione:

  • Il sistema deve funzionare esattamente su una macchina
  • Il sistema deve funzionare su un tipo di macchina (ma su molti individui).
  • Il sistema deve essere generalizzato su tipi di macchine simili.

Tenete conto di queste considerazioni quando dividete i vostri dati! Se dovete generalizzare a tipi di macchine simili, prendete in considerazione la suddivisione per tipo di macchina, un compito molto più impegnativo.

I miei consigli principali in questo caso sono:

  • Nella pianificazione del progetto definite propriamente come il vostro sistema verrà applicato e come misurare il successo! Utilizzate metodi che supportano questo, ad esempio the Industrial AI Canvas
  • Quando utilizzate librerie, controllate se hanno funzioni avanzate di split che supportano la divisione per gruppo. Ad esempio, consultate i documenti di scikit-learn.

Evitate la divisione dei -quasi- duplicati

In molti casi, ci si trova di fronte a un dataset non accuratamente curato. Nei miei progetti, ho spesso ottenuto dati contenenti un numero elevato di duplicati. Questo può significare due cose:

  1. Ci sono duplicati identici, ad esempio perché il cliente ha raccolto i dati da diverse condivisioni di file e i dati sono stati copiati MOOOLTE volte 😉
  2. Ci sono quasi duplicati, ad esempio perché alcune specifiche del processo di generazione dei dati producono esempi simili. Un esempio potrebbe essere un programma di test per la macchina che si desidera monitorare, che viene eseguito quotidianamente e produce dati del sensore quasi identici.

Per gestire i duplicati ho questi consigli:

  • Per i dati strutturati e duplicati identici, considerate di rimuoverli ad esempio con Pandas
  • Per dati strutturati, controllate se ci sono pacchetti specializzati per il riconoscimenti dei duplicati, come cleanvision per le immagini
  • Per dati strutturati, se non esistono librerie specializzate per la vostra modalità (immagini, audio, serie temporali …) considerate di utilizzare metriche standard di distanza sugli embedding. Esistono numerose librerie per il calcolo sugli embedding (https://github.com/Renumics/awesome-anything2vec)

Evitate le perdite

Ci sono problemi di ML che sono semplicemente diversi. Un caso tipico è quello delle serie temporali, ad esempio quando si affrontano problemi di previsione. In questo caso non è possibile suddividere i dati in modo casuale. Altrimenti, si valuterà il modello su dati già visti nel set di addestramento. Avete mostrato al modello il futuro. Ecco i miei consigli principali per evitare questi problemi:

  • Pensate attentamente al processo di generazione dei vostri dati. Ci sono correlazioni spaziali o temporali che possono rendere più facile la risoluzione del problema da parte del vostro modello ma non possono essere sfruttati in un contesto di produzione? Considerate la possibilità di documentare questo aspetto nella pianificazione del vostro progetto (https://renumics.com/blog/the-industrial-ai-canvas/)
  • Utilizzate funzioni di split che sono state progettate specificatamente per il vostro problema, ad esempio TimeSeriesSplit di scikit-learn

Conclusioni

Dividere i dati in training e validation sembra essere un task relativamente semplice. Tuttavia, come avete visto in questo articolo, spesso è fondamentale ottenere un risultato di valutazione significativo e un modello che funzioni bene in un ambiente di produzione. Spero che possiate utilizzare questo articolo come checklist per evitare alcune insidie.

 

Share:

Contenuti
Torna in alto