Preparazione dei dati per Machine Learning
Prima di poter creare un modello di Machine Learning, è necessario preparare i dati che verranno usati per eseguire il training e valutarlo. I dati vengono inseriti in Azure Databricks dall'origine, spesso come file di dati. Facoltativamente, è possibile creare tabelle delta basate sui file di dati per semplificare l'esplorazione e l'analisi dei dati. Dopo aver inserito i dati, uno scienziato dei dati li prepara per il Machine Learning.
In genere, la preparazione dei dati comporta due attività chiave:
- Pulizia dei dati: identificazione e mitigazione dei problemi nei dati che influiranno sull'utilità per il Machine Learning.
- Ingegneria e pre-elaborazione delle funzionalità: selezione e trasformazione delle funzionalità appropriate per il training del modello.
Pulizia dei dati
I passaggi specifici necessari per pulire i dati variano da progetto a progetto, ma i problemi tipici da risolvere includono:
- Dati incompleti: i dati includono spesso record in cui mancano singoli campi (spesso indicati dalla presenza di valori NULL). È necessario identificare i valori mancanti e correggerli:
- Sostituendoli con una sostituzione appropriata: interpolando un valore in una serie, usando un valore medio (o mediano) o creando un altro valore appropriato.
- Rimuovendo del tutto le righe incomplete (presupponendo che rimangano dati rappresentativi sufficienti per la creazione del modello)
- Errori: non è raro che i dati includano errori, causati da errori di immissione dei dati o da un'elaborazione dati upstream non riuscita. La ricerca di errori può essere difficile e in genere comporta un esame sostanziale dei dati usando query e visualizzazioni per riepilogare i dati e cercare i valori che non sono allineati alla maggior parte degli altri valori in un determinato campo.
- Outlier: gli outlier sono valori significativamente esterni (sopra o sotto) alla distribuzione statistica dei dati. A volte gli outlier sono un'indicazione di un errore (ad esempio, un utente può avere un valore con uno zero aggiuntivo oppure omesso un separatore decimale) e talvolta sono valori originali insolitamente alti o bassi rispetto alla maggior parte delle osservazioni. In entrambi i casi, gli outlier estremi possono influire negativamente sul training di un modello di Machine Learning. Per questo, è in genere preferibile gestirli reimpostandoli su un valore soglia superiore o inferiore o rimuovendo i record che contengono outlier dal set di dati.
- Tipi di dati non corretti: gli algoritmi di Machine Learning possono essere sensibili ai tipi di dati assegnati ai valori delle funzionalità. È comune per i set di dati basati su file di testo contenenti errori o valori Null eseguire in modo errato il casting dei campi numerici in un tipo di dati string e spesso i valori che rappresentano valori interi discreti possono essere interpretati erroneamente come numeri decimali (o viceversa). È necessario esaminare lo schema dei dati e assegnare i tipi di dati appropriati che riflettono in modo più efficace i valori dei dati.
- Dati sbilanciati: il training di Machine Learning funziona meglio se i dati di training includono una rappresentazione adeguata per tutte le diverse combinazioni di caratteristiche e etichette che potrebbero essere rilevate. In un set di dati sbilanciato, i record che includono un particolare valore categorico o una specifica combinazione di campi sono sovrarappresentati e ciò può influenzare l'algoritmo di training e introdurre distorsioni nel modello. Una tecnica comune per correggere questo problema consiste nel sovracampionare i valori sottorappresentati includendo righe duplicate o sottocampionare le righe sovrarappresentate (rimuovendole dal set di dati).
In Azure Databricks, il modo più comune per rilevare e gestire questi tipi di problema consiste nello scrivere codice in un notebook che esplora e modifica i dati. La classe primaria usata per questo tipo di manipolazione dei dati è il dataframe Spark.
Ad esempio, il codice seguente carica i dati da un file di testo in un dataframe:
df = spark.read.format("csv").option("header", "true").load("/myfolder/mydata.csv")
In alternativa, se i dati sono stati caricati in una tabella delta nell'area di lavoro di Azure Databricks, è possibile usare una query SQL per caricare i dati in un dataframe:
df = spark.sql("SELECT * FROM mytable")
Dopo aver caricato i dati in un dataframe, è possibile usare i relativi metodi e altre funzioni nella libreria Spark SQL per esplorare e trasformare i dati. Ad esempio, il codice seguente usa il metodo dropna per rimuovere tutte le righe che includono valori Null e assegna tipi di dati specifici alle colonne nel dataframe.
clean_data = df.dropna().select(col("column1").astype("string"),
col("column2").astype("float"))
Suggerimento
Per altre informazioni sulla funzionalità dei dataframe Spark, vedere la documentazione sui dataframe Spark.
Ingegneria e pre-elaborazione delle funzionalità
Dopo aver verificato che il set di dati sia completo e pulito, è possibile iniziare a preparare le funzionalità per il Machine Learning. L'ingegneria delle funzionalità è un approccio iterativo che spesso comporta vari tentativi per determinare quali colonne di funzionalità hanno valore predittivo e come rappresentare meglio le funzionalità. Le attività comuni di ingegneria e pre-elaborazione delle funzionalità includono:
Derivazione di nuove funzionalità: spesso è possibile derivare funzionalità nuove e più predittive da quelle esistenti. Si supponga, ad esempio, che un set di dati includa una colonna data e si sospetta che la data completa non sia un fattore predittivo importante per identificare l'etichetta, ma che il giorno della settimana potrebbe esserlo. È possibile creare una nuova funzionalità day_of_week derivata dalla data e verificare la teoria.
Discretizzazione delle funzionalità numeriche: in alcuni casi, un valore numerico potrebbe rivelarsi più predittivo quando viene discretizzato in categorie che rappresentano intervalli di valori specifici. Ad esempio, è possibile prendere i valori numerici in una funzionalità prezzo e assegnarli alle categorie basso, medio e alto in base a soglie appropriate.
Codifica delle funzionalità categoriche: molti set di dati includono dati categorici rappresentati da valori stringa. Tuttavia, la maggior parte degli algoritmi di Machine Learning funziona meglio con i dati numerici. È quindi comune assegnare codici numerici per rappresentare categorie anziché stringhe. Ad esempio, un set di dati di dettagli dei prodotti può includere una funzionalità per il colore con il valore "Verde", "Rosso" o "Blu". È possibile codificare questi valori usando codici interi semplici, ad esempio 0 per "Verde", 1 per "Rosso" e 2 per "Blu". In alternativa, è possibile usare una tecnica di codifica one-hot in cui si crea una nuova colonna per ogni categoria possibile e assegnare il valore 1 o 0 a ogni colonna in modo appropriato per ogni riga, come illustrato di seguito:
Colonna del colore originale Verde Rosso Blu Verde 1 0 0 Blu 0 0 1 Rosso 0 1 0 Ridimensionamento (normalizzazione) dei valori numerici: i valori dei dati numerici usano spesso scale o unità di misura diverse tra loro. Gli algoritmi di Machine Learning li elaborano tutti come valori numerici assoluti e le funzionalità con valori più grandi spesso possono dominare il training del modello. Per risolvere questo problema, è comune ridimensionare tutte le colonne numeriche in modo che i singoli valori per una singola colonna mantengano la stessa relazione proporzionale tra loro, ma che tutte le colonne numeriche usino una scala simile. Si supponga, ad esempio, che un set di dati contenga valori di lunghezza e peso misurati in metri e chilogrammi. È possibile convertire entrambe queste funzionalità in un valore ridimensionato compreso tra 0 e 1 come segue:
length peso lunghezza_ridimensionata peso_ridimensionato 250,0 2.1 0.250 0,210 176,0 0.9 0,176 0,09
Molte librerie di Machine Learning includono classi che è possibile usare per eseguire attività comuni di ingegneria delle funzionalità. Ad esempio, la libreria Spark MLlib include la classe StringIndexer, che è possibile usare per applicare una codifica semplice basata su interi per i valori stringa.
from pyspark.ml.feature import StringIndexer
encoder = StringIndexer(inputCol="catCol", outputCol="catColCode")
encoded_data = encoder.fit(data).transform(data)
Nota
Vale la pena spiegare l'esempio di codice StringIndexer in maggiore dettaglio. Le classi Spark MLlib possono includere analizzatori che adattano un algoritmo per un'operazione di trasformazione specifica ad alcuni dati di esempio. In questo caso, StringIndexer adatta un algoritmo di codifica ai valori stringa discreti nella colonna catCol nel dataframe data per determinare i calcoli specifici necessari per generare una nuova colonna catColCode contenente i valori codificati. L'output di un analizzatore è un trasformatore che incapsula la funzione definita dall'analizzatore e che può applicare tale funzione ai dati e generare un nuovo dataframe. In questo esempio, gli stessi dati usati per determinare la funzione di codifica vengono passati al trasformatore risultante per applicare effettivamente la codifica.
In Spark MLLib è possibile concatenare una sequenza di analizzatori e trasformatori in una pipeline che esegue tutti i passaggi di ingegneria e pre-elaborazione delle funzionalità necessari per preparare i dati. La pipeline può terminare con un algoritmo di Machine Learning che funge da analizzatore per determinare le operazioni necessarie per la previsione di un'etichetta dalle funzionalità preparate. L'output della pipeline è un modello di Machine Learning, che è in realtà un trasformatore che può essere usato per applicare la funzione del modello alle funzionalità in un dataframe e prevedere i valori di etichetta corrispondenti.