Tous les processus de prétraitement utilisés dans cette leçon, ainsi que d’autres techniques plus avancées, sont détaillés dans le cours de
Préprocessing et Feature Engineering disponible sur ce site.
Pourquoi le pipeline rend le travail du data scientist plus simple et structuré?
Sans pipeline: un processus lourd et fragile
Lorsqu’on travaille sur un projet de machine learning, il faut souvent enchaîner plusieurs étapes: nettoyer les données, normaliser les colonnes numériques, encoder les variables catégorielles, puis entraîner un modèle. Chaque opération doit être appliquée séparément et dans le bon ordre. Cela implique d’écrire beaucoup de code répétitif, de gérer manuellement les transformations entre l’entraînement et le test, et de risquer des incohérences (par exemple, appliquer un scaler différent sur les données de test). En pratique, ce processus devient vite lourd, difficile à maintenir et source d’erreurs dès que le projet grandit ou qu’on veut réutiliser le modèle. C'est justement pour cette raison que l'utlisation du pipline s'avère utile.
Qu'est ce qu'un pipline en Machine Learning?
Le
pipeline en machine learning est une manière structurée d’enchaîner toutes les étapes nécessaires au traitement des données et à l’entraînement d’un modèle. Au lieu d’appliquer manuellement chaque transformation (normalisation, encodage...) avant de lancer l’algorithme, le pipeline regroupe ces opérations dans un seul flux cohérent. Cela garantit que les mêmes traitements sont appliqués de façon identique sur les données d’entraînement et de test, ce qui évite les erreurs et rend le code plus clair et reproductible.
Concrètement, un pipeline peut combiner plusieurs blocs: par exemple un préprocesseur qui normalise les colonnes numériques et encode les variables catégorielles, suivi d’un modèle comme la régression logistique. Une fois défini, il suffit d’appeler fit pour entraîner l’ensemble, puis predict pour obtenir des résultats. Cette approche simplifie le travail, améliore la lisibilité et permet de déployer facilement le modèle en production, car toutes les étapes sont encapsulées dans un seul objet.
ColumnTransformer: Appliquer des transformations ciblées aux colonnes
Le
ColumnTransformer est un outil de scikit‑learn qui permet d’appliquer des traitements différents selon la nature des colonnes d’un jeu de données. Plutôt que de transformer tout le tableau de la même manière, il offre la possibilité de normaliser certaines variables numériques, d’encoder des variables catégorielles, ou encore de laisser passer d’autres colonnes inchangées. En pratique, il agit comme un “chef d’orchestre” du prétraitement : tu définis une liste de colonnes et la transformation associée, puis le ColumnTransformer applique automatiquement la bonne opération à la bonne partie des données. Cela rend le code plus lisible, évite les erreurs et s’intègre parfaitement dans un pipeline de machine learning.
Exemple pratique sur le dataset Titanic
Le choix du dataset Titanic est particulièrement pertinent pour illustrer le rôle du pipeline et du ColumnTransformer. Ce jeu de données est simple, bien connu et contient à la fois des variables numériques (comme Age et Fare) et des variables catégorielles (comme Sex et Embarked). Il permet donc de montrer concrètement comment appliquer des transformations différentes selon la nature des colonnes, puis d’entraîner un modèle prédictif.
Je propose ce code:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, MinMaxScaler, OrdinalEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.metrics import classification_report
data=pd.read_csv("titanic.csv")
data=data.drop(
["PassengerId","Name","Ticket","Cabin"], axis=1
).dropna()
X=data.drop(["Survived"],axis=1)
y=data["Survived"]
preprocessor=ColumnTransformer(
transformers=[
("num1",StandardScaler(),["Age"]),
("num2",MinMaxScaler(),["Fare"]),
("cat",OrdinalEncoder(),["Sex","Embarked"])
]
)
pipeline = Pipeline([
('preprocessor', preprocessor),
('clf', LogisticRegression(max_iter=200))
])
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
pipeline.fit(X_train, y_train)
y_pred=pipeline.predict(X_test)
print(classification_report(y_test,y_pred))
Une grande partie du code vous est déjà familière. Nous allons donc concentrer notre attention sur les éléments nouvellement introduits, en particulier ceux qui concernent le pipeline et son fonctionnement:
En commençant par les imports, en plus des modules habituels, nous avons ajouté deux outils essentiels de scikit‑learn:
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
- Pipeline: ce module sert à enchaîner automatiquement plusieurs étapes (prétraitement + modèle) dans un flux unique.
- ColumnTransformer: ce module permet d’appliquer des transformations différentes selon les colonnes (scaler pour les numériques, encodage pour les catégorielles, etc.).
Ensuite, nous définissons le processeur via ColumnTransformer:
preprocessor=ColumnTransformer(
transformers=[
("num1",StandardScaler(),["Age"]),
("num2",MinMaxScaler(),["Fare"]),
("cat",OrdinalEncoder(),["Sex","Embarked"])
]
)
L’argument
transformers représente la liste des transformations à appliquer colonne par colonne. Chaque élément de cette liste est un "bloc" composé de trois parties:
- Un nom interne pour identifier la transformation ("num1", "num2" et "cat").
- L’outil de prétraitement choisi (StandardScaler, MinMaxScaler et OrdinalEncoder).
- Les colonnes du dataset concernées (celles qui subiront les transformations).
Dans ce préprocesseur, nous utilisons ColumnTransformer pour appliquer des transformations différentes selon les colonnes du dataset:
- ("num1", StandardScaler(), ["Age"]) : indique que la colonne Age sera normalisée avec un StandardScaler (centrage et réduction).
- ("num2", MinMaxScaler(), ["Fare"]): applique un MinMaxScaler uniquement sur la colonne Fare, afin de ramener ses valeurs entre 0 et 1.
- ("cat", OrdinalEncoder(), ["Sex","Embarked"]): encode les colonnes catégorielles Sex et Embarked en valeurs numériques ordonnées.
L’idée est que chaque type de donnée reçoit le traitement le plus adapté, tout en gardant un seul objet preprocessor qui pourra être intégré directement dans le pipeline.
Après, nous définissons un pipeline:
pipeline = Pipeline([
('preprocessor', preprocessor),
('clf', LogisticRegression(max_iter=200))
])
Ce pipeline est constitués de deux étapes:
- preprocessor: applique le ColumnTransformer que nous avons construit auparavant (normalisation, encodage...).
- clf: correspond au modèle de machine learning, ici une régression logistique avec un maximum de 200 itérations pour l’entraînement.
Le pipeline enchaîne automatiquement ces étapes: d’abord le prétraitement des données, puis l’apprentissage du modèle. Cela garantit que toutes les transformations sont appliquées de manière cohérente et que le code reste simple et reproductible.
Enfin, on entraine puis on fait des prédictions pour l'évaluation du modèle:
pipeline.fit(X_train, y_train)
y_pred=pipeline.predict(X_test)
- pipeline.fit(X_train, y_train): cette instruction entraîne le pipeline sur les données d’entraînement. Concrètement, le préprocesseur applique ses transformations (scaling et encodage) puis le modèle (régression logistique) apprend à partir des données transformées et des étiquettes (y_train).
- pipeline.predict(X_test): une fois entraîné, le pipeline peut être utilisé pour prédire. Ici, il applique automatiquement les mêmes transformations au jeu de test (X_test), puis génère les prédictions grâce au modèle entraîné.
L’avantage est que toutes les étapes (prétraitement et modèle) sont enchaînées de manière cohérente et transparente, sans risque d’oublier une transformation ou de créer une incohérence entre entraînement et test.