One-Hot Encoding: représenter chaque modalité par une colonne
Transformer les catégories en variables binaires en utilisant l'encodage One-Hot
Dans le leçon précéndente qui traite le
Label Encoding, nous avons encodé nos deux premiers champs catégoriels "Sex" et "Embarked" avec ette technique là. Maintenant, nous allons aborder une autre technique d’encodage. Il s'agit du
One-Hot Encoding, que nous appliquerons sur la variable "Pclass" du dataset Titanic.
Bien que la variable Pclass soit représentée par des nombres (1, 2, 3), il ne s’agit pas de valeurs quantitatives mais de catégories ordinales correspondant aux classes des passagers (Première, Deuxième, Troisième). Si nous laissons ces chiffres tels quels, le modèle risque de les interpréter comme une relation numérique continue en considérant par exemple que la classe 3 est "trois fois" la classe 1, ce qui est faux.
Justement, le One-Hot Encoding permet d’éviter cette confusion en créant autant de colonnes binaires qu’il existe de modalités, c'est à dire une colonne pour la Première classe, une pour la Deuxième, et une pour la Troisième. Chaque passager sera alors représenté par un vecteur où une seule colonne prend la valeur 1 et les autres 0, ce qui indique précisément son appartenance à une catégorie.
Cette transformation rend l’information explicite pour l’algorithme et supprime toute ambiguïté liée à une interprétation numérique. Contrairement au Label Encoding qui attribue un ordre implicite aux catégories, le One-Hot Encoding préserve la nature purement qualitative des données et s’avère particulièrement adapté lorsque les catégories ne doivent pas être comparées entre elles par des valeurs numériques.
Préparer les données Titanic: One-Hot Encoding de la variable Pclass
Dans cette nouvelle étape, nous conservons l’encodage Label Encoding pour les variables Sex et Embarked, exactement comme dans la leçon précédente, afin de rester cohérents avec notre approche initiale. En revanche, pour la variable Pclass, nous utilisons désormais un One-Hot Encoding qui permet de transformer chaque modalité en colonnes binaires distinctes. Le code complet sera présenté en une seule fois et nous prendrons ensuite le temps d’expliquer les nouveautés introduites par cette transformation.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
df = pd.read_csv("titanic.csv")
data = df[['Sex', 'Embarked', 'Pclass', 'Survived']].dropna()
X = data[['Sex', 'Embarked', 'Pclass']]
y = data['Survived']
# Encodage avec LabelEncoder pour Sex et Embarked
le_sex = LabelEncoder()
X['Sex'] = le_sex.fit_transform(X['Sex'])
le_embarked = LabelEncoder()
X['Embarked'] = le_embarked.fit_transform(X['Embarked'])
# One-Hot Encoding pour Pclass avec scikit-learn
ohe = OneHotEncoder(sparse_output=False)
pclass_encoded = ohe.fit_transform(X[['Pclass']])
# Créer un DataFrame pour les colonnes encodées
pclass_df = pd.DataFrame(pclass_encoded,
columns=ohe.get_feature_names_out(['Pclass']),
index=X.index)
# Fusionner avec X et supprimer la colonne originale
X = pd.concat([X.drop('Pclass', axis=1), pclass_df], axis=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print("Accuracy k-NN:", accuracy_score(y_test, y_pred))
print("Extrait One-Hot Encoding de Pclass:")
print(pclass_df.head(10))
Passons à l'explication du code.
On commence par importer les modules d'encodage LabelEncoder et
OneHotEncoder:
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
Ensuite, on encode la variable "Pclass":
ohe = OneHotEncoder(sparse_output=False)
pclass_encoded = ohe.fit_transform(X[['Pclass']])
Le paramètre
sparse_output=False sert à générer une
matrice dense (ou ableau NumPy dense). Par défaut, OneHotEncoder produit une matrice sparse, c’est-à-dire qu’il ne stocke que les positions des valeurs non nulles (les 1), ce qui permet de gagner beaucoup de mémoire lorsque la matrice contient une majorité de zéros. En revanche, en précisant sparse_output=False, on obtient un tableau dense où chaque valeur (0 ou 1) est explicitement représentée.
Le format dense est plus intuitif et directement exploitable avec pandas ou NumPy mais il peut devenir coûteux en mémoire si le nombre de catégories est élevé.
Après, on crée un DataFrame contenant les colonnes encodées en one-hot de Pclass avec des noms explicites et le même index que X:
pclass_df = pd.DataFrame(pclass_encoded,
columns=ohe.get_feature_names_out(['Pclass']),
index=X.index)
Expliquons rapidement le rôle de chacun des paramètres passées lors de la création du dataframe:
- columns=ohe.get_feature_names_out(['Pclass']): Donne des noms explicites aux colonnes créées par l’encodage one-hot. Par exemple ['Pclass_1', 'Pclass_2', 'Pclass_3'] au lieu de simples indices numériques.
- index=X.index: Assure que le DataFrame résultant garde le même index que X, ce qui permet d’aligner parfaitement les nouvelles colonnes encodées avec les lignes originales du dataset.
En fin, on supprime la colonne originale Pclass du DataFrame X (car elle est catégorielle brute), puis on concatène les colonnes encodées pclass_df à X. Le résultat est un DataFrame enrichi où Pclass est remplacée par ses versions one-hot encodées (Pclass_1, Pclass_2, Pclass_3).
X = pd.concat([X.drop('Pclass', axis=1), pclass_df], axis=1)
L'exécution du code entier produit ce résultat:
Accuracy k-NN: 0.7640449438202247
Extrait One-Hot Encoding de Pclass:
Pclass_1 Pclass_2 Pclass_3
0 0.0 0.0 1.0
1 1.0 0.0 0.0
2 0.0 0.0 1.0
3 1.0 0.0 0.0
4 0.0 0.0 1.0
5 0.0 0.0 1.0
6 1.0 0.0 0.0
7 0.0 0.0 1.0
8 0.0 0.0 1.0
9 0.0 1.0 0.0
Notez que OneHotEncoder de scikit-learn renvoie par défaut des valeurs en float (0.0 et 1.0) plutôt qu’en entiers (0 et 1).
One-Hot Encoding à l'aide de la méthode get_dummies de Pandas
Il est tout à fait possible d’utiliser la fonction
get_dummies de pandas à la place de OneHotEncoder de scikit-learn pour réaliser un encodage one-hot. Cette approche génère automatiquement des colonnes binaires (par exemple Pclass_1, Pclass_2, Pclass_3) sans avoir besoin de définir un encodeur ni d’appeler fit_transform.
L’avantage de cette technique est sa simplicité et sa rapidité, ce qui la rend particulièrement adaptée aux tâches exploratoires ou aux petits projets. En revanche, l’inconvénient est que get_dummies n’est pas intégré dans les pipelines scikit-learn, ce qui le rend moins pratique si l’on souhaite automatiser tout le prétraitement dans un workflow de machine learning.
On peut utiliser la méthode get_dummies comme ceci:
pclass_df = pd.get_dummies(X['Pclass'], prefix='Pclass')