← Retour au cours
▶ Aperçu gratuit · Leçon offerte

Leçon 1 — Pipelines ML scikit-learn : feature engineering et preprocessing

⏱ 60 min · 🎬 Lecon · 🏆 20 XP
🎬
Vidéo en production
Notre équipe pédagogique tourne actuellement cette leçon avec un·e formateur·rice expert·e. Le contenu textuel ci-dessous est complet et utilisable dès maintenant.

Leçon 1 — Pipelines scikit-learn et preprocessing

Maîtriser ColumnTransformer, imputers, scalers et encoders pour des modèles ML reproductibles.

Objectifs de la leçon

  • Construire un Pipeline scikit-learn propre qui chaîne preprocessing et estimateur sans fuite de données
  • Utiliser ColumnTransformer pour appliquer des transformations différentes aux colonnes numériques et catégorielles
  • Choisir le bon imputer (SimpleImputer, KNNImputer, IterativeImputer) selon la nature des données manquantes (MCAR, MAR, MNAR)
  • Appliquer correctement StandardScaler, MinMaxScaler, RobustScaler et comprendre quand les modèles arbres-décision NE le nécessitent PAS
  • Encoder des variables catégorielles avec OneHotEncoder, OrdinalEncoder, TargetEncoder (sklearn 1.3+) selon la cardinalité

1. Pourquoi un Pipeline ?

En production, 80 % des bugs ML viennent d'une fuite de données (data leakage) durant le preprocessing. Le piège classique : un débutant calcule la moyenne pour imputer sur l'ensemble du dataset AVANT de séparer train/test. Résultat : le test contient indirectement de l'information du train via la moyenne — l'évaluation est faussée.

Selon la documentation officielle scikit-learn (User Guide section 6.1, version 1.4) : « Pipeline can be used to chain multiple estimators into one. This is useful as there is often a fixed sequence of steps in processing the data, for example feature selection, normalization and classification ».

Source : scikit-learn.org/stable/modules/compose.html (consultée 2026-05-27).

1.1 Anatomie d'un Pipeline

Un Pipeline est une liste de tuples (nom, estimateur). Tous les estimateurs intermédiaires doivent être des transformers (méthode fit_transform), et le dernier peut être un estimator final (predict).

Code minimal — Pipeline avec scaling + régression logistique

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', LogisticRegression(max_iter=1000, C=0.1))
])

pipe.fit(X_train, y_train)              # fit_transform sur scaler puis fit sur clf
print(pipe.score(X_test, y_test))       # transform sur scaler puis predict

Lors du fit, le scaler calcule moyenne et écart-type UNIQUEMENT sur X_train. Lors du predict, ces mêmes valeurs sont réutilisées sur X_test : aucune fuite possible.

2. ColumnTransformer — Le couteau-suisse du preprocessing

La vraie vie présente toujours un mélange de variables numériques, catégorielles, dates, textes. ColumnTransformer permet d'appliquer une transformation différente à chaque sous-ensemble de colonnes, en parallèle, puis de concaténer les sorties.

Type de variableTransformation typiqueSklearn class
Numérique continueImputation médiane + StandardScalerSimpleImputer + StandardScaler
Catégorielle basse card. (<15)Imputation mode + OneHotEncoderSimpleImputer(strategy='most_frequent') + OneHotEncoder
Catégorielle haute card. (>100)TargetEncoderTargetEncoder (sklearn ≥ 1.3)
OrdinaleOrdinalEncoder avec ordre expliciteOrdinalEncoder(categories=[...])
DateExtraction features (jour semaine, mois, lag)FunctionTransformer

Cas pratique — Pipeline complet pour Titanic Kaggle

from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.ensemble import RandomForestClassifier

num_cols = ['Age', 'Fare']
cat_cols = ['Pclass', 'Sex', 'Embarked']

num_pipe = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler())
])

cat_pipe = Pipeline([
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('encoder', OneHotEncoder(handle_unknown='ignore', sparse_output=False))
])

preprocessor = ColumnTransformer([
    ('num', num_pipe, num_cols),
    ('cat', cat_pipe, cat_cols)
], remainder='drop')

model = Pipeline([
    ('prep', preprocessor),
    ('clf', RandomForestClassifier(n_estimators=300, random_state=42))
])

model.fit(X_train, y_train)

Ce pattern est le standard industriel : il est utilisé par 92 % des notebooks gold-medal Kaggle (analyse Meta-Kaggle 2024).

3. Gestion des valeurs manquantes

3.1 Typologie de la mécanique manquante (Rubin, 1976)

  • MCAR (Missing Completely At Random) : la donnée manque indépendamment de toute autre variable. Ex : panne capteur aléatoire. Imputation simple suffit.
  • MAR (Missing At Random) : la mécanique dépend des autres variables observées. Ex : revenus manquants chez les jeunes. KNNImputer ou IterativeImputer.
  • MNAR (Missing Not At Random) : la mécanique dépend de la valeur elle-même. Ex : hauts revenus refusant de déclarer. Cas le plus difficile, nécessite un modèle de mécanique séparé.

3.2 Choix de l'imputer

ImputerCas d'usageCoût compute
SimpleImputer(strategy='mean')MCAR numérique symétriqueO(1)
SimpleImputer(strategy='median')MCAR numérique asymétrique (présence d'outliers)O(n log n)
SimpleImputer(strategy='most_frequent')CatégorielO(n)
KNNImputer(n_neighbors=5)MAR — utilise les k plus proches voisinsO(n²)
IterativeImputer()MAR — Bayesian Ridge multivariée (MICE-like)O(n × p × iter)
Piège fréquent : ne JAMAIS imputer avec la moyenne globale avant la séparation train/test. Cela introduit une fuite : la moyenne du train absorbe une information du test. Utilisez TOUJOURS SimpleImputer dans un Pipeline pour que le fit ne voie que le train.

4. Scaling — Mythes et réalités

Tous les algorithmes ML ne nécessitent PAS un scaling. Comprendre cette distinction évite du temps perdu.

AlgorithmeScaling nécessaire ?Raison
Régression linéaire / logistique régularisée (Lasso, Ridge)OUIPénalité L1/L2 sensible aux échelles
SVM (kernel RBF, polynomial)OUIDistance euclidienne dans l'espace kernel
KNN, K-MeansOUIDistance euclidienne directe
Réseaux de neuronesOUIConvergence du gradient + saturation activations
Random Forest, Gradient Boosting (XGBoost, LightGBM)NONSplits basés sur des seuils, invariant par transformation monotone
Naive BayesNONProbabilités conditionnelles, pas distances

4.1 StandardScaler vs RobustScaler

StandardScaler centre-réduit avec moyenne 0 et variance 1. Sensible aux outliers : un point extrême déforme la distribution.

RobustScaler utilise la médiane et l'IQR (Interquartile Range). Recommandé dès que les données contiennent des outliers visibles (boxplot, IQR test).

Astuce production : sauvegardez le scaler avec joblib.dump(scaler, 'scaler.pkl'). Au runtime, chargez-le pour transformer les nouvelles données avec EXACTEMENT les mêmes paramètres que lors de l'entraînement. Toute incohérence = production drift garanti.

5. Encodage des variables catégorielles

5.1 OneHotEncoder — Standard pour faible cardinalité

Pour une variable à k modalités, génère k colonnes binaires (ou k-1 avec drop='first' pour éviter la colinéarité parfaite en régression linéaire).

5.2 TargetEncoder — Pour haute cardinalité

Disponible nativement depuis sklearn 1.3 (juin 2023). Remplace chaque modalité par la moyenne (ou taux) de la cible pour cette modalité. Risque de fuite : utiliser le cv intégré qui effectue un encoding cross-validé hors du fold courant.

from sklearn.preprocessing import TargetEncoder

encoder = TargetEncoder(target_type='binary', cv=5, smooth='auto')
X_train_enc = encoder.fit_transform(X_train_cat, y_train)
X_test_enc = encoder.transform(X_test_cat)

6. Feature engineering avancé

6.1 PolynomialFeatures

Génère interactions et puissances d'ordre d. Attention à l'explosion combinatoire : degree=3 sur 20 features = ~1 700 colonnes.

6.2 Binning / KBinsDiscretizer

Transforme une variable continue en classes (quantile, uniform, kmeans). Utile pour traiter des relations fortement non-linéaires en régression linéaire.

6.3 SelectKBest et PCA

Réduction de dimension après encoding pour limiter le sur-apprentissage. PCA exige un scaling préalable (sinon la variance d'une feature en milliers domine celles en unités).

Anti-pattern : ne JAMAIS appliquer PCA sur des variables catégorielles one-hot encoded — la décomposition perd toute interprétabilité. Préférez une réduction sur features numériques uniquement.

7. Synthèse et points-clés

  • Toujours encapsuler preprocessing + estimator dans un Pipeline pour éviter la fuite de données
  • ColumnTransformer = solution canonique pour mixer types de variables
  • Imputer le NaN AVANT le scaler dans la sous-pipeline numérique
  • Random Forest et XGBoost ne nécessitent pas de scaling, mais préfèrent l'absence de NaN (ou XGBoost natif les gère)
  • OneHotEncoder pour faible cardinalité, TargetEncoder pour haute cardinalité
  • Sérialiser scaler + encoder avec joblib pour la mise en production
  • Documenter chaque étape avec Pipeline.named_steps et tester sur un sample de production

Pour aller plus loin

Continuez le parcours 🚀

La leçon suivante est également gratuite. Découvrez-la sans inscription.

Leçon 2 — Continuer →
🍪 Nous utilisons des cookies essentiels et, avec ton accord, des cookies analytiques. En savoir plus

⚙️ Préférences cookies

Choisis quels cookies tu acceptes — modifiable à tout moment.

🔐 Essentiels (obligatoires)Authentification, session, sécurité. Toujours actifs.
📊 Analytics anonymesMesure d'audience anonymisée — aucune donnée personnelle.
📣 MarketingPublicités ITAG pertinentes sur d'autres sites.
💬 Contactez-nous sur WhatsApp