PreProcessing dei dati per il Machine Learning

Nel contesto dell’analisi dei dati con PreProcessing intendiamo l’insieme delle attività propedeutiche all’applicazione di algoritmi di Machine Learning. Le tecniche di Data PreProcessing riguardano principalmente la trasformazione e la pulizia dei dati di input e rappresentano uno step necessario e fondamentale per ottenere l’accuratezza richiesta nell’output finale.

In questo articolo vedremo applicati step by step le fasi più comuni del PreProcessing, a partire dal noto Dataset Iris, attraverso il linguaggio di programmazione Python e in particolare la sua libreria scikit-learn (sklearn). Se vuoi approfondire la parte di import dei dati puoi leggere questo mio articolo https://www.yimp.it/import-dati-python-e-pandas/. Qui riporto soltanto il codice per importare una versione del Dataset salvata sul mio repository di Github.

import pandas as pd
f = "https://raw.githubusercontent.com/iantomasinicola/Machine-Learning-con-SQL/main/IrisDataset.csv"
iris = pd.read_csv(filepath_or_buffer = f,
                   sep = ";", 
                   header = None,
                   names = ["rownumber",
                            "sepal_length",
                            "sepal_width",
                            "petal_length",
                            "petal_width",
                            "class"],
                   skiprows = 4)

Gli step qui riportati fanno riferimento a una particolare classe di algoritmi di Machine Learning, forse la più semplice e diffusa: la classificazione supervisionata. Tuttavia molte delle attività descritte possono essere applicate anche ad altre tipologie di algoritmi.

Creazione di un array di numpy a partire da un DataFrame

La maggior parte degli algoritmi di Machine Learning prende in input dati strutturati come array della libreria numpy. Le procedure di import di pandas creano invece i DataFrame, una struttura dati diversa di tipo tabellare. Il primo passo sarà dunque quello di convertire le colonne del DataFrame di interesse in array di numpy, separando le colonne contenenti le variabili di input (features) da quella con la variabile di output da classificare (target).

x = iris[["sepal_length","sepal_width","petal_length","petal_width"]].values
y = iris[["class"]].values

PreProcessing con Python: codifica della variabile target

Quasi tutti gli algoritmi di Machine Learning accettano in input esclusivamente valori numerici. Di conseguenze occorre codificare il contenuto della variabile y (le stringhe iris-setosa, iris-virginica e iris-versicolor) in numeri. Possiamo svolgere facilmente questa attività aiutandoci con la libreria scikit-learn. Ecco il codice:

from sklearn.preprocessing import LabelEncoder
codifica_target = LabelEncoder()
y = codifica_target.fit_transform(y.ravel())

L’array y conterrà ora una sequenza di 0, 1 e 2.

Data PreProcessing: suddivisione dei dati in training e test

In estrema sintesi possiamo affermare che gli algoritmi di Machine Learning di classificazione supervisionata costruiscono una formula matematica che predice un valore target a partire da una serie di valori di partenza (features). Questa formula sarà creata basandosi su una serie di dati storici in cui conosco i valori di tutte le variabili (target e features).

Per valutare l’accuratezza di questa formula è fondamentale utilizzare per la sua costruzione solo una parte dei dati a disposizione. Gli altri infatti dovranno essere usati per testare se la formula trovata si generalizza bene anche a nuovi dati, per i quali non conosco il valore target. Anche in questo caso posso utilizzare un modulo di sklearn per creare quattro variabili:

  • x1 contenente le variabili features di training;
  • y1 contenente la variabile target di training;
  • x2 contenente le variabili features di test;
  • y2 contenente la variabile target di test.
from sklearn.model_selection import train_test_split
x1,x2,y1,y2 = train_test_split(x, 
                               y,
                               test_size = 0.3, 
                               shuffle = True, 
                               random_state = 1)

Il parametro shuffle = True ci ricorda che in questa fase è eseguito anche un mescolamento casuale dei dati, che sarà ripetibile in modo identico in altri esperimenti tramite l’utilizzo del parametro random_state = 1.

PreProcessing: valorizzazione dei null

Tutti i null presenti nel Dataset devono essere gestiti in qualche modo. In alcuni casi, se una colonna contiene un’alta percentuale di null,  possiamo anche valutare di escluderla dall’elenco delle variabili utilizzate per definire la formula matematica di predizione.

In questo paragrafo presentiamo invece un approccio diverso, in cui sostituiamo i null con la media della relativa colonna nel Dataset di training. L’idea è quella di sostituire i null con un valore statisticamente neutroin modo che non influenzi più di tanto i parametri della formula di predizione.

from sklearn.impute import SimpleImputer
valorizza_null = SimpleImputer(missing_values = np.nan, 
                               strategy = "mean")
valorizza_null.fit(x1)
x1 = valorizza_null.transform(x1)
x2 = valorizza_null.transform(x2)

Facciamo due osservazioni importanti:

  • la variabile target non è oggetto di modifica in questa fase. Le righe con un null nella variabile target devono essere semplicemente filtrate nel DataFrame di partenza. In questo articolo puoi approfondire le operazioni di filtro su pandas https://www.yimp.it/analisi-dei-dati-con-pandas-e-confronto-con-sql/;
  • la media deve essere calcolata a partire dai soli dati di training e poi utilizzata per sostituire i null sia nei dati di training che in quelli di test. Questa implementazione è la più realistica per valutare l’accuratezza dell’algoritmo quando saranno presenti nuovi dati da classificare, senza che la variabile target sia conosciuta.

Normalizzazione dei dati con Python e sklearn

Variabili diverse saranno quasi sicuramente distribuite secondo scale e unità di misura differenti. Ci aspettiamo ad esempio che la variabile altezza vari in un range da 150 a 200, mentre lo stipendio mensile da 1000 a 4000. Queste differenze potrebbero influenzare il processo di creazione della formula matematica di classificazione. Molto spesso dunque è consigliato riportare tutte le variabili features in una stessa scala. Ciò può essere fatto con tecniche diverse come mostrato in questo articolo https://www.andreaminini.com/ai/machine-learning/lo-scaling-nel-machine-learning. Nel nostro caso vi riporto il codice per implementare con scikit-learn una tecnica puramente statistica che sostituisce il valore di partenza con un numero che rappresenta di quante deviazioni standard il dato si discosta dalla media di quella colonna, secondo la formula

x_new =  (x_orig – Media) / DeviazioneStandard

from sklearn.preprocessing import StandardScaler
normalizzatore = StandardScaler()
normalizzatore.fit(x1)
x1 = normalizzatore.transform(x1)
x2 = normalizzatore.transform(x2)

Anche in questo caso è corretto calcolare media e deviazione standard a partire dai soli dati di training.

Altre attività di PreProcessing

Per il file Iris in questione le attività di PreProcessing presentate in questo articolo sono sufficienti. Altre attività di PreProcessing svolte frequentemente sono:

Continua a imparare

Scroll to Top
Torna su