ovvero non usare one-hot encoding dappertutto.
In questo articolo esamineremo come codificare le variabili categoriali ed evitare problemi di dimensionalità.
Introduzione
Durante i colloqui per i ruoli di Data Scientist, chiedo ai candidati di completare un compito. L’obiettivo è creare un modello di Machine Learning, spesso un classificatore binario. Questa sarà una parte importante del loro lavoro quotidiano. Come parte dei passaggi per completare l’esercizio, è necessario trattare variabili categoriche.
Nella maggior parte dei casi i candidati scelgono la tecnica del one-hot encoding per trattare queste variabili.
Che cos’è il one-hot encoding
Ci sono molti libri e articoli che suggeriscono una tecnica semplice. Questa tecnica trasforma una variabile categoriale in variabili binarie. La variabile binaria indica la presenza di ciascuna categoria nel record.
Facciamo un esempio.
Utilizzando il seguente codice
import pandas as pd
df = pd.DataFrame({
'ID': [1, 2, 3, 4, 5],
'colour': ['black', 'yellow', 'red', 'white', 'purple']
})
possiamo creare la tabella
ID | colore |
---|---|
1 | nero |
2 | giallo |
3 | rosso |
4 | bianco |
5 | viola |
Immagina di avere un set di dati semplice come quello sopra, con variabili id e colore. Devi cambiare il colore in una funzione codificata a caldo. Ciò significa che vuoi trasformare il set di dati in qualcosa di simile alla tabella seguente.
ID | colore_nero | colore_giallo | colore_rosso | colore_bianco | colore_viola |
---|---|---|---|---|---|
1 | 1 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | 0 | 0 | 0 |
3 | 0 | 0 | 1 | 0 | 0 |
4 | 0 | 0 | 0 | 1 | 0 |
5 | 0 | 0 | 0 | 0 | 1 |
Come puoi vedere, abbiamo creato 3 variabili da quella categorica iniziale. Ogni variabile rappresenta un colore, una categoria della variabile originale. Ora capisco perché questo metodo è così popolare. Se ci pensi, è una riga di codice, devi solo eseguirla
df = pd.get_dummies(df)
e tu ti occupi di tutto, vero? Sì, ma questo ha un costo, poiché non esiste un pranzo gratis .
Il costo di codificare tutto con una sola operazione
Quando si trasforma una variabile categoriale utilizzando la codifica one-hot, la maledizione della dimensionalità è il costo principale. Con questo termine ci riferiamo a vari fenomeni che insorgono quando si ha a che fare con dati organizzati in spazi ad alta dimensione.
Possiamo riassumere i principali effetti avversi come:
- Maggiore scarsità dei dati. Questo è abbastanza intuitivo guardando l’esempio precedente. Abbiamo dovuto creare 3 variabili per rappresentare la variabile originale con 3 categorie. Immagina di avere un set di dati con milioni di record. Ha decine di variabili categoriali, ciascuna con da 10 a 100 categorie. Usando questa tecnica, puoi creare matrici di dati con molti zeri. Ogni record avrà solo una variabile che rappresenta il valore categoriale come 1. Ciò crea una cosiddetta matrice sparsa. La scarsità della matrice rende le attività di clustering e classificazione più impegnative
- I calcoli diventano più dispendiosi in termini di risorse. A causa della maggiore complessità computazionale con più variabili.
- L’aggiunta di più dimensioni a un modello di machine learning aumenta il rischio di overfitting . Ciò accade perché più dimensioni danno al modello più gradi di libertà. Pertanto, il modello potrebbe finire per adattare il rumore nei dati anziché il segnale effettivo.
- Quando le dimensioni aumentano, i modelli di machine learning generalmente hanno prestazioni peggiori . Quando sono presenti più dimensioni, il modello necessita di più dati per funzionare meglio. All’aumentare del numero di dimensioni, lo spazio occupato dei dati cresce rapidamente.
Codificare Variabili Categoriali: Alternative
Quindi, quali alternative abbiamo rispetto alla codifica one-hot? Esploriamo alcuni di essi:
- Label Encoding :
- Descrizione : Assegniamo un numero intero a ciascuna categoria
- Pro : consente di risparmiare spazio poiché utilizza una singola colonna
- Contro : può introdurre relazioni ordinali dove non ne esistono
- Esempio :
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
df['Label_Encoded'] = le.fit_transform(df['colour'])
ID | colore | Etichetta_codificata |
---|---|---|
1 | nero | 0 |
2 | giallo | 4 |
3 | rosso | 2 |
4 | bianco | 3 |
5 | viola | 1 |
- Encoding ordinale :
- Descrizione : le variabili ordinali hanno un ordine logico, quindi possiamo usare la codifica ordinale invece della codifica delle etichette.
- Pro : mantiene la natura ordinale della variabile
- Contro : Non adatto per variabili nominali
- Esempio : Diciamo che i colori sono in ordine alfabetico e hanno una classifica.
df['colour'].astype('category').cat.codes
ID | colore | Ordinale_codificato |
---|---|---|
1 | nero | 0 |
2 | giallo | 4 |
3 | rosso | 2 |
4 | bianco | 3 |
5 | viola | 1 |
- Encoding della frequenza (o conteggio) :
- Descrizione : le categorie si rappresentano attraverso le loro occorrenze o il conteggio della frequenza.
- Pro : mantiene gestibile la forma del set di dati.
- Contro : Collisioni in cui categorie diverse hanno la stessa frequenza.
- Esempio :
df['Frequency_Encoded'] = df['colour'].map(df['colour'].value_counts())
ID | colore | Frequenza_codificata |
---|---|---|
1 | nero | 1 |
2 | giallo | 1 |
3 | rosso | 1 |
4 | bianco | 1 |
5 | viola | 1 |
Esempio di set di dati della codifica di frequenza
Nota : in questo esempio, tutti i colori appaiono solo una volta, quindi la frequenza è 1 per tutti.
- Codifica target (valore medio) :
- Descrizione : il valore medio del valore target per la categoria sostituisce la categoria.
- Pro : acquisisce informazioni sulla relazione tra la categoria e la variabile di destinazione.
- Contro : rischio di perdita di dati; non adatto per set di dati con un numero limitato di osservazioni.
- Esempio :
# Python snippet for target encoding
df['Target_Encoded'] = df['colour'].map(df.groupby('colour')['target'].mean())
ID | colore | bersaglio | Target_Encoded |
---|---|---|---|
1 | nero | 10 | 10.0 |
2 | giallo | 20 | 15.0 |
3 | rosso | 30 | 30.0 |
4 | bianco | 40 | 40.0 |
5 | viola | 50 | 50,0 |
6 | giallo | 10 | 15.0 |
- Hashing :
- Descrizione : utilizza una funzione hash per assegnare un numero a diverse categorie. Lo chiamiamo trucco dell’hashing.
- Pro: utile per gestire molte categorie; larghezza fissa, riducendo la complessità.
- Contro : collisioni in cui diverse categorie vengono mappate sullo stesso hash.
- Esempio :
df['Hashed_Value'] = df['colour'].apply(lambda x: hash(x) % 5)
ID | colore | Valore_hashed |
---|---|---|
1 | nero | 1 |
2 | giallo | 3 |
3 | rosso | 0 |
4 | bianco | 0 |
5 | viola | 4 |
- Leave-One-Out Encoding:
- Mi piace usare questo metodo per codificare una categoria, perché mostra la connessione alla variabile target. Per evitare data leakage, troviamo il valore medio del target per una particolare categoria, senza includere il valore target della riga corrente.
- Pro : riduce il rischio rispetto alla codifica target.
- Contro : Il calcolo è più intenso.
- Esempio : in questo esempio aggiungiamo una variabile target
import pandas as pd
df = pd.DataFrame({
'ID': [1, 2, 3, 4, 5, 6],
'colour': ['black', 'yellow', 'red', 'white', 'purple', 'yellow'],
'target': [10, 20, 30, 40, 50, 10]
})
ID | colore | target |
---|---|---|
1 | nero | 10 |
2 | giallo | 20 |
3 | rosso | 30 |
4 | bianco | 40 |
5 | viola | 50 |
6 | giallo | 10 |
def loo_encode(row, df, column, target):
temp_df = df[df[column] == row[column]]
temp_df = temp_df[temp_df.index != row.name]
if temp_df.empty:
return df[target].mean()
else:
return temp_df[target].mean()
df['LOO_Encoded'] = df.apply(loo_encode, args=(df, 'colour', 'target'), axis=1)
ID | colore | target | LOO_Codificato |
---|---|---|---|
1 | nero | 10 | 26.666667 |
2 | giallo | 20 | 10.000000 |
3 | rosso | 30 | 26.666667 |
4 | bianco | 40 | 26.666667 |
5 | viola | 50 | 26.666667 |
6 | giallo | 10 | 20.000000 |
Spunti di riflessione
Quando si sceglie un metodo di codifica, considerare il tipo di dati (nominali o ordinali), il tipo di modello (ad albero o lineare) e qualsiasi potenziale problema (fuga di dati, relazioni indesiderate). Durante i colloqui, mostrare la conoscenza di queste tecniche può far risaltare un candidato. Dimostra che comprendono bene l’ingegneria delle funzionalità.
Se ti e’ piaciuto questo articolo potrebbe anche piacerti questo: