import pandas as pd
import seaborn as sns
df = sns.load_dataset('titanic')
# Afficher le nombre de valeurs manquantes par colonne
print(df.isnull().sum())
1 Introduction
En science des données, on dit souvent : “Garbage In, Garbage Out” (Déchets en entrée, déchets en sortie). La qualité de vos modèles de Machine Learning dépend directement de la qualité de vos données. Le prétraitement des données (ou data preprocessing) est l’ensemble des techniques utilisées pour nettoyer, transformer et préparer les données brutes afin qu’elles soient exploitables par les algorithmes.
Objectifs de ce tutoriel :
- Comprendre les enjeux du prétraitement.
- Apprendre à gérer les données manquantes.
- Savoir encoder les variables catégorielles.
- Maîtriser la mise à l’échelle des variables (Standardisation et Normalisation).
- Appliquer ces techniques avec Pandas et Scikit-learn.
2 Partie 1 : Gestion des Données Manquantes
Les données manquantes sont un problème courant. La plupart des algorithmes ne peuvent pas fonctionner avec.
2.1 1. Identification
Utilisons le jeu de données du Titanic pour illustrer.
Nous voyons que age, deck, et embarked ont des valeurs manquantes.
2.2 2. Stratégies de Traitement
Suppression :
df.dropna(): Supprimer les lignes (ou colonnes) contenant des valeurs manquantes. Risqué, car on peut perdre beaucoup d’information.- À utiliser si les données manquantes sont très peu nombreuses.
Imputation (Remplacement) : La méthode la plus courante.
- Numérique : Remplacer par la moyenne ou la médiane. La médiane est plus robuste aux valeurs aberrantes.
- Catégorielle : Remplacer par le mode (la valeur la plus fréquente).
# Imputer 'age' avec la médiane
median_age = df['age'].median()
df['age'].fillna(median_age, inplace=True)
# Imputer 'embarked' avec le mode
mode_embarked = df['embarked'].mode()[0]
df['embarked'].fillna(mode_embarked, inplace=True)
# La colonne 'deck' a trop de valeurs manquantes (>75%), on la supprime
df.drop('deck', axis=1, inplace=True)
print(df.isnull().sum())3 Partie 2 : Encodage des Variables Catégorielles
Les modèles de Machine Learning sont des modèles mathématiques. Ils ont parfois besoin de nombres à la place chaînes de caractères.
3.1 1. One-Hot Encoding
Cette technique transforme chaque catégorie d’une variable en une nouvelle colonne binaire (0 ou 1). C’est la méthode la plus sûre et la plus utilisée. La fonction pd.get_dummies() est parfaite pour cela.
# Appliquer le One-Hot Encoding sur 'sex' et 'embarked'
1df_encoded = pd.get_dummies(df, columns=['sex', 'embarked'], drop_first=True)
df_encoded.head()- 1
-
drop_first=Trueévite la redondance en supprimant la première colonne après l’encodage.
3.2 2. Label Encoding
Cette technique assigne un entier unique à chaque catégorie (ex: “S” -> 0, “C” -> 1, “Q” -> 2). Attention : À n’utiliser que pour les variables ordinales (où un ordre existe, ex: “faible”, “moyen”, “élevé”), car cela peut introduire une relation d’ordre artificielle que le modèle pourrait mal interpréter.
Exemple 1
from sklearn.preprocessing import LabelEncoder
# Appliquer le Label Encoding sur 'class'
le = LabelEncoder()
df['class_encoded'] = le.fit_transform(df['class'])
df[['class', 'class_encoded']].head()4 Partie 3 : Mise à l’échelle des Variables (Feature Scaling)
Pourquoi ? De nombreux algorithmes (k-NN, SVM, réseaux de neurones, etc.) sont sensibles à l’échelle des variables. Une variable allant de 0 à 100 000 (comme un salaire) pèsera plus lourd qu’une variable allant de 0 à 100 (comme un âge), ce qui peut fausser le modèle.
Utilisons le jeu de données iris pour l’exemple.
from sklearn.preprocessing import StandardScaler, MinMaxScaler
iris = sns.load_dataset('iris')
X_iris = iris[['sepal_length', 'sepal_width', 'petal_length', 'petal_width']]4.1 1. Standardisation (Z-score Normalization)
Transforme les données pour qu’elles aient une moyenne de 0 et un écart-type de 1. C’est la technique la plus courante et la plus robuste.
- Centrer et réduire: \[z = \dfrac{x - \bar{x}}{s}\]
Où \(\bar{x}=\dfrac{1}{n}\sum_{i=1}^nx_i\) est la moyenne et \(s^2=\dfrac{1}{n-1}\sum_{i=1}^n(x_i - \bar{x})^2\) est l’écart-type.
scaler_std = StandardScaler()
X_scaled_std = scaler_std.fit_transform(X_iris)
print("Moyenne après standardisation (proche de 0):", X_scaled_std.mean(axis=0))
print("Écart-type après standardisation (proche de 1):", X_scaled_std.std(axis=0))4.2 2. Normalisation (Min-Max Scaling)
Met les données à l’échelle dans un intervalle fixe, généralement [0, 1].
Formule : \[x_{norm} = \dfrac{x - x_{min}}{x_{max} - x_{min}}\]
scaler_minmax = MinMaxScaler()
X_scaled_minmax = scaler_minmax.fit_transform(X_iris)
print("\nMin après normalisation (proche de 0):", X_scaled_minmax.min(axis=0))
print("Max après normalisation (proche de 1):", X_scaled_minmax.max(axis=0))Quand utiliser quoi ?
- Standardisation : Le choix par défaut. Moins sensible aux valeurs aberrantes.
- Normalisation : Utile quand l’algorithme requiert des données dans un intervalle borné (ex: traitement d’images où les pixels sont entre 0 et 255).
5 Partie 4 : Le Pipeline de Prétraitement Complet avec Scikit-learn
Nous avons vu les étapes de prétraitement de manière isolée. En pratique, il est crucial de les enchaîner dans un workflow propre et reproductible. C’est le rôle du Pipeline et du ColumnTransformer de Scikit-learn.
Pourquoi est-ce si important ?
- Prévention de la Fuite de Données (Data Leakage) : Le pipeline garantit que les informations du jeu de test ne “fuient” pas dans le jeu d’entraînement (par exemple, en calculant la moyenne sur l’ensemble des données avant de diviser).
- Reproductibilité : Le pipeline encapsule toutes vos étapes de prétraitement en un seul objet, facile à sauvegarder et à réutiliser.
- Simplicité : Vous pouvez entraîner et évaluer votre workflow complet en une seule ligne de code.
5.1 L’Atelier Pratique : Un Pipeline pour le Titanic
Objectif : Construire un pipeline qui gère l’imputation, l’encodage et la mise à l’échelle pour le jeu de données du Titanic.
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.model_selection import train_test_split
# 1. Recharger les données et séparer X et y
df = sns.load_dataset('titanic')
df.drop(['survived', 'alive', 'who', 'adult_male', 'class', 'embark_town', 'deck'], axis=1, inplace=True)
X = df.drop('pclass', axis=1) # pclass est notre cible pour cet exemple
y = df['pclass']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 2. Définir les pipelines pour chaque type de colonne
numeric_features = ['age', 'fare']
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')), # Gérer les valeurs manquantes
('scaler', StandardScaler()) # Mettre à l'échelle
])
categorical_features = ['sex', 'embarked']
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')), # Gérer les valeurs manquantes
('onehot', OneHotEncoder(handle_unknown='ignore')) # Encoder
])
# 3. Combiner les pipelines avec ColumnTransformer
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
],
remainder='passthrough' # Garder les autres colonnes (sibsp, parch)
)
# 4. Appliquer le pipeline de prétraitement
X_train_processed = preprocessor.fit_transform(X_train)
X_test_processed = preprocessor.transform(X_test)
print("Dimensions des données d'entraînement après prétraitement :", X_train_processed.shape)
print("Les données sont maintenant prêtes pour un modèle !")Gestion des données manquantes
Encodage des variables catégorielles
Séparation des features (X) et de la cible (y)
Mise à l’échelle des variables numériques
- On ne met à l’échelle que les colonnes qui en ont besoin.
- Important : On applique le
fit_transformsur les données d’entraînement et seulementtransformsur les données de test pour éviter la fuite de données (data leakage). Pour cet exemple, nous le faisons sur l’ensemble du jeu de données.
Vérification du résultat final
6 Conclusion
Le prétraitement des données est une étape fondamentale et souvent la plus longue d’un projet de Data Science. En maîtrisant la gestion des données manquantes, l’encodage des catégories et la mise à l’échelle des variables, vous augmentez considérablement les chances de succès de vos modèles.
Votre jeu de données X et votre cible y sont maintenant prêts à être utilisés pour entraîner un modèle de classification !
7 Exercices
Exercice 1
Selon le principe ‘Garbage In, Garbage Out’, pourquoi le prétraitement des données est-il une étape cruciale en Machine Learning ?
Quelle méthode Pandas est utilisée pour compter le nombre de valeurs manquantes dans chaque colonne d’un DataFrame df ?
Pour imputer une variable numérique qui contient des valeurs aberrantes (outliers), quelle est la stratégie la plus robuste ?
Quelle est la méthode standard pour imputer les valeurs manquantes d’une variable catégorielle ?
Si une colonne a un très grand pourcentage de valeurs manquantes (ex: 75%), quelle est souvent la meilleure stratégie ?
Pourquoi doit-on encoder les variables catégorielles avant de les utiliser dans la plupart des modèles de Machine Learning ?
Que fait le One-Hot Encoding sur une variable couleur ayant les catégories [‘Rouge’, ‘Vert’, ‘Bleu’] ?
Quel est le principal risque à utiliser le Label Encoding sur une variable nominale (non ordonnée) comme ville ?
Quelle fonction Pandas est la plus directe pour appliquer le One-Hot Encoding ?
Pour quels types d’algorithmes la mise à l’échelle des variables (Feature Scaling) est-elle particulièrement cruciale ?
Après avoir appliqué StandardScaler de Scikit-learn, quelles seront approximativement la moyenne et l’écart-type de chaque variable ?
Quel est le résultat de l’application de MinMaxScaler sur une variable ?
Pour éviter la fuite de données (data leakage), quand doit-on ajuster (fitter) un StandardScaler ?
drop_first
Dans pd.get_dummies(..., drop_first=True), à quoi sert le paramètre drop_first ?
Quelle méthode de mise à l’échelle est généralement considérée comme le choix par défaut car elle est moins sensible aux valeurs aberrantes ?
ColumnTransformer
Quel est le rôle principal de ColumnTransformer dans un pipeline de prétraitement ?
remainder
Dans ColumnTransformer(..., remainder='passthrough'), que signifie le paramètre remainder ?
Dans un pipeline typique pour des données numériques, quel est l’ordre correct des opérations pour éviter la fuite de données ?
En plus de prévenir la fuite de données, quel est un avantage majeur de l’utilisation d’un Pipeline pour le déploiement d’un modèle ?
handle_unknown='ignore'
Dans OneHotEncoder(handle_unknown='ignore'), à quoi sert le paramètre handle_unknown ?