Trasformazione delle funzionalità per l'apprendimento automatico, una guida per principianti

Quando ho iniziato a imparare come ottimizzare i modelli di apprendimento automatico, spesso, dopo essere arrivato alla fase di costruzione del modello, avrei dovuto continuare a rivisitare i dati per gestire meglio i tipi di funzionalità presenti nel set di dati. Nel corso del tempo ho scoperto che uno dei primi passi da compiere prima di creare i modelli è di esaminare attentamente i tipi di variabili presenti nei dati e di cercare di determinare in anticipo il miglior processo di trasformazione da adottare per ottenere le prestazioni ottimali del modello.

Nel seguente post descriverò il processo che prendo per identificare e trasformare quattro tipi di variabili comuni. Userò un set di dati tratto dal concorso di riscaldamento "machine learning with a heart" ospitato sul sito Web https://www.drivendata.org/. Il set di dati completo può essere scaricato qui https://www.drivendata.org/competitions/54/machine-learning-with-a-heart/data/. DrivenData ospita regolarmente sfide online basate sulla risoluzione di problemi sociali. Di recente ho iniziato a partecipare ad alcune di queste competizioni nel tentativo di utilizzare alcune delle mie capacità per una buona causa e anche di acquisire esperienza con set di dati e problemi che di solito non incontro nel mio lavoro quotidiano.

Identificazione dei tipi di variabili

In statistica le variabili numeriche possono essere caratterizzate in quattro tipi principali. Quando si avvia un progetto di apprendimento automatico, è importante determinare il tipo di dati contenuti in ciascuna delle funzionalità in quanto ciò può avere un impatto significativo sul rendimento dei modelli. Ho provato a dare una semplice descrizione dei quattro tipi seguenti.

  • Le variabili continue sono variabili che possono avere un numero infinito di valori possibili, al contrario di variabili discrete che possono avere solo un intervallo di valori specificato. Un esempio di una variabile continua sarebbe il numero di miglia percorse da un'auto nella sua vita.
  • Le variabili nominali sono valori categoriali che hanno 2 o più valori possibili, ma in cui l'ordine di tali valori non ha significato. Ad esempio, potremmo usare una rappresentazione numerica per interpretare i tipi di auto che sostengono che compact ha un valore di 1, MPV ha un valore di 2 e la convertibile ha un valore di 3. Tuttavia, il fatto che l'auto compatta abbia un valore di 1 e il convertibile ha un valore di 2 non significa che matematicamente il gruppo convertibile sia in qualche modo più grande del MPV. È semplicemente una rappresentazione numerica della categoria.
  • Le variabili dicotomiche sono di nuovo categoriche, ma hanno solo 2 possibili valori generalmente 0 e 1. Ad esempio, potremmo classificare la proprietà dell'auto come 1 (che significa sì) o 0 (che significa no). Quando convertiamo le variabili in colonne fittizie (cosa che faremo più avanti in questo post) anche le nuove funzionalità prodotte diventano dicotomiche.
  • Le variabili ordinali sono simili al nominale in quanto hanno 2 o più valori possibili, la differenza principale è che questi valori hanno un ordine o un rango significativi. Quindi nel nostro esempio di auto questo potrebbe essere qualcosa di simile alla cilindrata del motore in cui queste categorie potrebbero essere ordinate in termini di potenza, 1.2, 1.6, 1.8.

Preparazione dei dati

Userò il nostro machine learning con un set di dati del cuore per seguire il processo di identificazione e trasformazione dei tipi di variabili. Ho scaricato e letto i file CSV in un taccuino Jupyter. Quindi eseguo la seguente funzione per ottenere un'istantanea della composizione dei dati.

importare i panda come pd
def quick_analysis (df):
 stampa ("Tipi di dati:")
 stampa (df.dtypes)
 stampa ("Righe e colonne:")
 stampa (df.shape)
 stampa ("Nomi colonna:")
 stampa (df.columns)
 print ("Null Values:")
 print (df.apply (lambda x: sum (x.isnull ()) / len (df)))
quick_analysis (treno)

Questo produce il seguente output.

Questo mi dice che ho un piccolo set di dati di solo 180 righe e che ci sono 15 colonne. Una delle funzionalità non è numerica e pertanto dovrà essere trasformata prima di applicare la maggior parte delle librerie di machine learning. Non ci sono valori nulli, quindi non devo preoccuparmi di trattarli. Prima di elaborare il set di dati, per ora rilascia anche la colonna "patient_id" poiché non è numerica e non verrà utilizzata in nessuna delle fasi di addestramento o previsione.

Quindi eseguo la funzione di descrizione dei panda per produrre alcune statistiche descrittive rapide.

train.describe ()

Per classificare i tipi di variabili nel set di dati, eseguo il seguente codice che produce istogrammi di tutte le caratteristiche numeriche. Dall'output risultante si può facilmente vedere quali funzionalità sono continue e dicotomiche. Le funzioni continue mostrano un modello di distribuzione continua, mentre le funzioni dicotomiche hanno solo due barre. Le variabili nominali e ordinali possono talvolta essere più difficili da determinare e possono richiedere ulteriori conoscenze sul set di dati o alcune conoscenze specifiche sul dominio. Nel caso di una competizione di apprendimento automatico come questa, suggerirei di fare riferimento a qualsiasi dizionario di dati che potrebbe essere fornito, se non ce n'è uno (come nel caso qui), potrebbe essere necessaria una combinazione di intuizione, prova ed errore.

import matplotlib.pyplot come plt
treno [train.dtypes [(train.dtypes == "float64") | (train.dtypes == "Int64")]
                        .index.values] .hist (figsize = [11,11])

Ho caratterizzato le caratteristiche nei quattro tipi nella tabella seguente. Ora posso prendere alcune decisioni in merito alle fasi di trasformazione che prenderò al fine di preparare i dati per la formazione e la previsione.

False variabili

Come accennato in precedenza in questo post, tutti i valori non numerici devono essere convertiti in numeri interi o float per poter essere utilizzati nella maggior parte delle librerie di machine learning. Per le variabili a bassa cardinalità l'approccio migliore è in genere quello di trasformare la funzione in una colonna per valore univoco, con uno 0 dove il valore non è presente e uno 1 dove si trova. Questi sono indicati come variabili fittizie.

Questa tecnica è di solito anche meglio applicata a qualsiasi variabile nominale. Poiché questi non hanno un ordine intrinseco, se non lo applichiamo per primi, l'algoritmo di machine learning potrebbe erroneamente cercare una relazione nell'ordine di questi valori.

Pandas ha una bella funzione per questo chiamato get_dummies (). Nel codice seguente l'ho usato per convertire tutte le funzioni nominali e non numeriche in nuove colonne. Dall'output è possibile vedere che sono state create diverse nuove colonne e che le colonne originali sono state eliminate.

dummy_cols = ['thal', 'chest_pain_type', 'num_major_vessels',
              'esercizio_indotto_angina', 'fasting_blood_sugar_gt_120_mg_per_dl',
              'resting_ekg_results', 'slope_of_peak_exercise_st_segment']
train = pd.get_dummies (train, colonne = dummy_cols)

Ridimensionamento delle funzioni

Le variabili continue nel nostro set di dati sono su scale variabili. Ad esempio, se fai riferimento agli istogrammi sopra, puoi vedere che la variabile "oldpeak_eq_st_depression" varia da 0 a 6, mentre "max_heart_rate_achieved" varia da 100 a 200. Ciò pone un problema per molti algoritmi di apprendimento automatico popolari che spesso usano la distanza euclidea tra i punti dati per fare le previsioni finali. La standardizzazione della scala per tutte le variabili continue può spesso comportare un aumento delle prestazioni dei modelli di apprendimento automatico.

Esistono numerosi metodi per eseguire il ridimensionamento delle funzionalità in Python. Il mio metodo preferito è utilizzare la funzione Sci-Kit Learn MinMaxScaler. Il che trasforma la scala in modo che tutti i valori nelle caratteristiche siano compresi tra 0 e 1. Ho incluso un codice che lo fa di seguito.

dalla preelaborazione dell'importazione sklearn
n_test = train [['serum_cholesterol_mg_per_dl', 'max_heart_rate_achieved',
                'oldpeak_eq_st_depression', 'resting_blood_pressure']]
cols_to_norm = ['serum_cholesterol_mg_per_dl', 'max_heart_rate_achieved',
                'oldpeak_eq_st_depression', 'resting_blood_pressure']
x = n_test.values
min_max_scaler = preprocessing.MinMaxScaler ()
x_scaled = min_max_scaler.fit_transform (x)
n_test = pd.DataFrame (x_scaled, colonne = cols_to_norm)
l_test = train.drop (['serum_cholesterol_mg_per_dl', 'max_heart_rate_achieved',
                'oldpeak_eq_st_depression', 'resting_blood_pressure'], axis = 1)
train = pd.concat ([n_test, l_test], axis = 1)
train.columns

binning

Noterai dal codice sopra che non ho incluso la variabile continua "age" nella trasformazione del ridimensionamento delle funzionalità. La ragione di ciò è che l'età è un esempio di un tipo di caratteristica che potrebbe trarre vantaggio dalla trasformazione in una variabile discreta. In questo esempio possiamo usare il bucket o il binning per trasformare la funzione in un elenco di categorie significative.

Nel codice seguente ho specificato le categorie intuitive in base alla distribuzione nei dati. Questo utilizza la funzione di taglio panda che include un elenco di bin, group_names e il frame di dati. Questa funzione restituisce il frame di dati originale con una nuova funzionalità "age_categories". Questa colonna può quindi essere trasformata in un numero di colonne fittizie utilizzando il metodo precedentemente descritto.

bin = = 30, 40, 50, 60, 70, 80]
group_names = ['30 -39 ', '40 -49', '50 -59 ', '60 -69', '70 -79 ']
age_categories = pd.cut (train ['age'], bin, labels = group_names)
train ['age_categories'] = pd.cut (train ['age'], bin, labels = group_names)
age_categories
pd.value_counts (treno [ 'age_categories'])

Ciò che abbiamo ora è un set di dati in cui tutte le colonne sono non numeriche. Abbiamo creato diverse nuove funzionalità e trasformato le funzionalità esistenti in formati che dovrebbero aiutare a migliorare le prestazioni di tutti i modelli di apprendimento automatico che ora possiamo usare. La trasformazione delle funzioni è un primo passo importante nel processo di apprendimento automatico e spesso può avere un impatto significativo sulle prestazioni del modello. Ho delineato qui i primi passi che intraprenderei nel processo per pensare logicamente a come trattare le diverse variabili che ho. Una volta nella fase di costruzione del modello, tornerò quasi sempre a modificare i dati utilizzando metodi diversi per cercare di migliorare l'accuratezza dei modelli. Tuttavia, trovo che seguendo questi passaggi all'inizio ciò spesso riduca il tempo che dedico a tornare alle fasi di trasformazione.