Come scegliere il miglior metodo per codificare variabili categoriali

ai
data-science
python
Author

Federico Viscioletti

Published

July 3, 2024

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

Il set di dati iniziale contenente le variabili id ​​e color

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

Il set di dati iniziale contenente le variabili id ​​e color

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

Esempio di set di dati di LabelEncoder

  • 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

Esempio di set di dati con Encoding ordinale

  • 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

Esempio dataset con funzione di hashing

  • 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

Il set di dati di input per il Leave-One-Out encoding

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

La tabella risultato

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:

Code Snippets: Python - How to sort dictionary values

In this blog post, we will explore two methods to sort dictionary values, demonstrating their implementation and usage.