codifica one-hot

Codifica one-hot e caratteristiche nominali

Nell’articolo precedente abbiamo parlato del mappaggio dei dati per convertire in interi la caratteristica ordinale delle dimensioni. In questo nuovo articolo analizziamo la codifica one-hot e riprendiamo in mano la classe LabelEncoder per codificare le etichette in valori interi per quanto riguarda la nostra caratteristica nominale color

				
					X = df[['color', 'size', 'price']].values

color_le = LabelEncoder()
X[:, 0] = color_le.fit_transform(X[:, 0])
X
				
			

Il risultato dell’esecuzione :

				
					>> array([[1, 1, 10.1],
          [2, 2, 13.5],
          [0, 3, 15.3]], dtype=object)
				
			

Vediamo che ora la colonna colori è stata trasformata in valori numerici interi:

  • Blu = 0
  • Verde = 1
  • Rosso = 2

Capito il procedimento, se ora dovessimo inviare tutto al nostro classificatore, commetteremo un errore comune nella gestione dei dati categorici. Infatti, anche se i valori relativi a un colore specifico non hanno alcun ordine, un algoritmo di apprendimento supporrà che il verde sia maggiore di blu e che rosso sia maggiore di verde

L’algoritmo produce un risultato, che per quanto giusto sia non restituisce risultati ottimali

Codifica one-hot

La soluzione a questo problema si chiama codifica one-hot. Consiste nel creare una nuova caratteristica fittizia per ogni valore univoco nella colonna della caratteristica nominale. Convertire qui la caratteristica color in tre nuove  caratteristiche (verde, rosso e blu). A questo punto possono essere utilizzati valori binari per indicare lo specifico colore di un campione.

Chiariamo con un esempio il concetto di codifica one-hot : 

  • un campione blu può essere codificato come blu = 1, verde = 0 e rosso = 0. Per svolgere la trasformazione utilizziamo la classe OneHotEncoder di scikit-learn.preprocessing o utilizziamo il metodo più intuito get_dummies implementato nei pandas. Applicato ad un DataFrame converte solo le colonne stringa e lascia intatte le altre:
				
					pd.get_dummies(df[['price', 'color', 'size']])
				
			
codifica one-hot

Partizionamento di un dataset nei set di addestramento e di test

Vediamo ora come preparare il dataset Wine andando a pre-elaborare il dataset e sviluppando conoscenze sulla capacità di riduzione della dimensionalità. Esso è costituito da ben 178 vini con 13 caratteristiche che descrivono la loro proprietà. 

				
					import pandas as pd
import numpy as np

df_wine = pd.read_csv('https://archive.ics.uci.edu/'
                      'ml/machine-learning-databases/wine/wine.data',
                      header=None)

df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash',
                   'Alcalinity of ash', 'Magnesium', 'Total phenols',
                   'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins',
                   'Color intensity', 'Hue', 'OD280/OD315 of diluted wines',
                   'Proline']

print('Class labels', np.unique(df_wine['Class label']))
df_wine.head()
				
			
codifica one-hot

I campioni appartengono a tre classi diverse (1, 2, 3) e si riferiscono a tre tipi di vitigni che crescono in diverse regioni italiane. Per suddividere il dataset casualmente in uno di test e uno di addestramento possiamo utilizzare la funzione train_test_split del modulo model_selection di scikit-learn:

				
					from sklearn.model_selection import train_test_split

X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values

X_train, X_test, y_train, y_test = \
    train_test_split(X, y, test_size=0.3, random_state=0)

				
			

Ad X assegniamo la rappresentazione ad array delle colonne delle caratteristiche da 1 a 13 e a y abbiamo assegnato le etichette delle classi. Tramite funzione train_test_split abbiamo suddiviso in maniera random X e y nei dataset di addestramento e test. Il 30% dei campioni a test e il rimanente 70% ad addestramento

Portare tutte caratteristiche su stessa scala

Abbiamo visto già negli articoli passati che cosa significa ridurre a stessa scala le caratteristiche. Vi sono due approcci fondamentalmente:

  • Normalizzazione
  • Standardizzazione

La normalizzazione fa riferimento al cambiamento di scala della caratteristica in un intervallo [0, 1], che è uno speciale caso di riduzione in scala di un min-max. Attraverso la funzione in scikit-learn – MinMaxScaler – otteniamo:

				
					from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler()
X_train_norm = mms.fit_transform(X_train)
X_test_norm = mms.transform(X_test)
				
			

La normalizzazione è molto intuita e semplice da applicare. La standardizzazione però, può essere più pratica per alcuni algoritmi di Machine Learning. La regressione logistica e la SVM inizializzano i pesi a 0 o a piccoli valori casuali vicino allo 0. Con la standardizzazione centriamo la colonna della caratteristica alla media 0 con deviazione standard 1 in modo che la colonna della caratteristica assuma la forma di una distribuzione normale dalla quale è più facile ottenere i pesi. Essa, inoltre, mantiene informazioni utili riguardo alle anomalie e rende l’algoritmo meno sensibile a questo problema. 

Scikit-learn implementa anche una classe per la standardizzazione appunto:

				
					from sklearn.preprocessing import StandardScaler
stdsc = StandardScaler()
X_train_std = stdsc.fit_transform(X_train)
X_test_std = stdsc.transform(X_test)
				
			

Adattiamo la StandarScaler ai dati di addestramento e poi utilizziamo questi stessi parametri per trasformare il set di test o ogni nuovo punto dei dati. 

Condividi il post

Condividi su facebook
Condividi su google
Condividi su twitter
Condividi su email
Condividi su whatsapp