MINI-COURS #25 ⏱️ 30 à 40 minutes de lecture
🔒 Contenu réservé aux membres du Cercle des Experts
Débloque la leçon complète et tous les autres mini-cours.
Introduction
J’ai eu l’opportunité de travailler sur de nombreux projets de machine learning en conditions réelles — d’abord comme data scientist à plein temps, puis en tant qu’indépendant, où j’accompagnais des entreprises sur leurs projets data.
Construire des projets de data science de bout en bout — du nettoyage des données jusqu’au déploiement des modèles — m’a confronté à une multitude de pièges, de biais et de bonnes pratiques… que je n’ai quasiment jamais vus formalisés clairement.
Honnêtement, tout ce que je vais partager ici, ce sont des leçons que j’aurais aimé apprendre beaucoup plus tôt.
La bonne nouvelle, c’est que tu n’as pas besoin de passer par les mêmes erreurs.
Dans ce mini-cours, j’ai rassemblé 8 pièges que tu rencontreras très probablement, ainsi que les réflexes à adopter pour les éviter.
D’après mon expérience, ces pièges sont presque toujours présents — mais rarement visibles au premier coup d’œil. Et c’est précisément ce qui fait dérailler un grand nombre de projets.
Commençons !
1) Inspecter ses arbres de décision
Si l’on visualise les règles de décision (les conditions évaluées à chaque nœud) de n’importe quel arbre de décision, on constate qu’elles sont toujours perpendiculaires aux axes des features, comme ci‑dessous :

En d’autres termes, un arbre de décision segmente progressivement l’espace des features au moyen de frontières perpendiculaires pour séparer les données.
En soi, ce n’est pas un “problème”.
C’est même précisément cette manière de découper l’espace qui rend l’arbre de décision capable de sur‑apprendre à la perfection n’importe quel dataset (voir la section sur l’expérience d’overfitting pour plus de détails).
Mais cela soulève un point intéressant, souvent ignoré lorsqu’on ajuste des arbres de décision.
Plus précisément : que se passe‑t‑il si notre dataset est séparé par une frontière de décision diagonale, comme ci‑dessous ?

Il est alors assez intuitif de voir que la frontière de décision construite par un arbre prendra cette forme :

En visualisant cet arbre, on constate qu'il est contraint de multiplier les divisions pour s'adapter à un dataset pourtant très simple à séparer. À l'inverse, un algorithme comme la régression logistique, un SVM (Support Vector Machine) ou un réseau de neurones basique résoudrait ce problème de façon beaucoup plus élégante :

Cela devient encore plus évident si l’on zoome sur cet arbre et qu’on observe à quel point les seuils de split sont proches les uns des autres :

Et là, c’est un peu inquiétant : on voit clairement que l’arbre essaie laborieusement de mimer une frontière diagonale, ce qui laisse penser que ce n’est peut‑être pas le meilleur modèle pour ce problème.
Pour vérifier cette intuition, voici une méthode de diagnostic simple que j'utilise régulièrement :
Préparation : On part de notre jeu d'entraînement classique, avec la matrice de features
XX de dimensions
n × m)la cible
y(de dimensionn × 1).
Rotation de l'espace : On applique une Analyse en Composantes Principales (PCA) sur
X. L'objectif ici n'est pas de réduire la dimension, mais de projeter les données dans un nouvel espace orthogonal. On obtient ainsiX_pca, qui conserve les mêmes dimensions(n × m).Modélisation et visualisation : On entraîne un nouvel arbre de décision sur ces données transformées (
X_pca). Profitons du grand atout des arbres : leur interprétabilité visuelle ! On affiche donc le graphe de l'arbre obtenu.Diagnostic : Si la profondeur de ce nouvel arbre est drastiquement inférieure à celle de l'arbre initial, le diagnostic est confirmé : la frontière de décision était bien diagonale par rapport aux axes d'origine.
Par exemple, voici les projections PCA du dataset utilisé plus haut :

Il apparaît distinctement que, suite à la projection, la frontière de décision devient quasi orthogonale à la seconde composante principale (X2).
L'ajustement d'un arbre de décision sur la matrice X_pca s'en trouve alors grandement simplifié, ce qui se traduit par une réduction drastique de sa complexité et de sa profondeur.
L'illustration ci-dessous en témoigne :

Ce constat nous amène à une conclusion claire : face à de telles données, nous aurions tout intérêt à changer d'algorithme.
L'alternative serait d'investir du temps dans un feature engineering spécifique, afin de fournir à l'arbre des variables sur lesquelles il pourra appliquer ses découpes orthogonales efficacement.
Une question légitime se pose alors : pourquoi ne pas simplement déployer en production l'arbre entraîné sur X_pca ?
Si rien ne l'interdit techniquement, n'oublions pas le prix à payer : la perte d'interprétabilité. Les composantes principales étant des combinaisons linéaires abstraites, nous sacrifions le sens métier des variables d'origine, ce qui est souvent rédhibitoire en entreprise.
Le mot de la fin : Ne considère jamais un arbre de décision comme une boîte noire ; prends toujours le temps d'inspecter sa structure.
Mon but n'est évidemment pas de te dissuader de les utiliser — ils restent, après tout, les briques fondatrices des modèles ensemblistes les plus puissants du marché (Random Forest, XGBoost...).
L'objectif est plutôt d'apprendre à 'penser' comme l'algorithme, pour maîtriser ses limites géométriques et savoir exactement quand il est le bon outil pour le bon problème.
2) Séparation aléatoire des données
Dans quasiment tous les cours d’introduction au machine learning, on nous explique qu’il faut séparer les données de façon ALÉATOIRE en un ensemble d’entraînement et un ensemble de validation :

La séparation aléatoire peut sembler pertinente : elle répartit les données sans biais apparent.
Mais dans de nombreux cas, elle devient en réalité problématique — voire contre-productive — pour construire un modèle fiable. Et c’est un point souvent sous-estimé.
Et je ne parle même pas ici des données temporelles.
Voyons cela plus en détail.
Scénario
Imaginons que tu construises un modèle qui génère des légendes pour des images :

En raison de la nature du langage, une même image peut avoir de nombreuses légendes différentes :

Tu le vois sans doute venir : le principal problème apparaît au moment clé de la séparation entre l’entraînement et la validation (train/val split).
Si l'on se contente de diviser ce dataset de manière purement aléatoire, que va-t-il se passer ?
Les multiples lignes générées à partir d'une seule et même image vont inévitablement se retrouver éparpillées à la fois dans l'ensemble d'entraînement et dans l'ensemble de validation.

Il s'agit là d'un cas d'école de fuite de données (data leakage), garantissant un surapprentissage massif de ton modèle.
Dans le jargon de la Data Science, on appelle plus précisément ce phénomène le group leakage (fuite par groupe).
Solution
Au regard de ce qui précède, l’origine du problème est claire : elle provient de la séparation aléatoire des données.
Pour y remédier, on utilise plutôt une séparation par groupes (group shuffle split).
L’approche se déroule en deux étapes :
Regrouper toutes les instances liées à une même entité (une image, ou toute autre clé susceptible d’introduire une fuite : patient, utilisateur, session, etc.)
Une fois ces groupes définis, affecter chaque groupe en bloc soit au train, soit à la validation — mais jamais aux deux
Au vu de ce qui précède, l’origine du problème est claire : elle vient de la séparation aléatoire des données (random split).
Pour y remédier, on utilise une séparation par groupes.
L’approche se fait en deux étapes :
Regrouper toutes les instances associées à une même entité (une image, ou toute autre clé susceptible d’introduire une fuite : patient, utilisateur, session, etc.)
Une fois ces groupes définis, affecter chaque groupe en bloc soit à l’entraînement (train), soit à la validation — mais jamais aux deux

Cela permet d’éviter les fuites entre groupes observés plus haut et de limiter le surapprentissage.
À noter : dans notre exemple de génération de légendes, toutes les features (les pixels de l’image) participent au critère de regroupement.
Mais plus généralement, seul un sous-ensemble de variables peut être utilisé pour définir ces groupes et réaliser une séparation correcte des données.
Par exemple, prenons un dataset d’imagerie médicale. Chaque échantillon peut contenir plusieurs images (différentes vues d’une même zone anatomique), et le modèle doit estimer la sévérité d’une pathologie.
Dans ce cas, il est essentiel de regrouper toutes les images appartenant à un même patient, puis de séparer les données par patient. Sinon, cela introduit une fuite d’information, et le modèle aura du mal à généraliser à de nouveaux patients.
Implémentation
Avec scikit‑learn, la classe GroupShuffleSplit implémente exactement cette idée.

Imaginons que nous ayons un dataset du type :

x1etx2sont les features,yest la variable cible,groupreprésente le critère de regroupement.
On peut créer ce dataset comme suit :

Ensuite, on importe GroupShuffleSplit depuis sklearn et on instancie l’objet :

Ici, on précise notamment :
n_splits: le nombre d’itérations de rééchantillonnage (re-tirage) / de séparationtest_size: la proportion de groupes à allouer à l’ensemble de test (arrondie à l’entier supérieur)
La méthode split() permet ensuite d’effectuer la séparation en respectant ces groupes :

Cette méthode renvoie un générateur, que l’on peut déballer pour obtenir :

Comme on peut le constater :
Toutes les observations des groupes « A » et « C » sont regroupées dans l’ensemble d’entraînement
Toutes les observations du groupe « B » sont regroupées dans l’ensemble de validation / test
De cette façon, on évite la fuite de données observée précédemment.
3) KernelPCA vs PCA
Le problème du PCA
Lors d’une réduction de dimension, l’Analyse en Composantes Principales (PCA) cherche à projeter les données dans un sous-espace linéaire de plus faible dimension, tout en conservant au mieux leur structure.
Par exemple, considérons le dataset simplifié suivant :

Si l’on trace ce dataset, on obtient :

On voit assez clairement qu’il existe un sous‑espace linéaire le long duquel on peut représenter les données tout en conservant un maximum de variance :

Mais que se passe‑t‑il si nos données s’alignent sur un sous‑espace de faible dimension, mais non linéaire ?
Par exemple, considérons ce dataset non linéaire :

En le traçant, on obtient :

Ici, le sous‑espace de faible dimension n’est pas évident au premier coup d’œil.
Pourtant, la figure suivante montre qu’il existe bien un sous‑espace non linéaire de faible dimension sur lequel nos données pourraient être projetées :

La courbe représente un sous‑espace continu, non linéaire et de faible dimension, sur lequel nos données pourraient être décrites.
Pourquoi ne pas simplement faire ça ?
Le problème est que le PCA est incapable d’identifier ce type de structure car les points ne sont pas alignés selon une relation linéaire.
En d’autres termes, le PCA est une technique linéaire de réduction de dimension — et elle montre ses limites dans ce type de situation.
Pourtant, face à ce dataset non linéaire, on pressent qu’une représentation en une seule dimension serait possible… à condition de capturer correctement cette structure courbe :

KernelPCA
KernelPCA (ou « l’astuce du noyau ») a justement été conçu pour pallier cette limitation du PCA.
Le principe est assez simple :
on projette d’abord les données dans un espace de dimension (potentiellement) plus élevée à l’aide d’une fonction noyau, de manière à ce qu’elles deviennent linéairement séparables. Scikit‑learn fournit une classe
KernelPCAavec de nombreux noyaux populaires.on applique ensuite un PCA standard dans cet espace transformé.
Voyons maintenant l’efficacité de KernelPCA par rapport au PCA.
Commençons par ajuster un PCA sur le dataset non linéaire précédent :

Dans ce code :
Avant d’appliquer PCA, on standardise généralement les données pour que chaque feature ait une moyenne nulle et une variance unité. On utilise pour cela
StandardScalerde scikit‑learn.On applique ensuite le PCA sur les données standardisées, avec
n_components=1pour réduire à une seule dimension.Après PCA, on peut reconstruire les données dans l’espace d’origine avec
inverse_transformappliqué aux données projetées. Autrement dit, on obtient unX_originaltel que son transformé PCA seraitX.
En traçant data_standardized en nuage de points et data_pca_reconstructed en courbe, on obtient :

On voit que, même si les données sont non linéaires, le PCA produit malgré tout un sous‑espace linéaire pour la projection.
Passons maintenant au KernelPCA sur le même dataset :

Dans ce code :
KernelPCA est appliqué aux données standardisées, avec
n_components=2pour réduire à deux dimensions,kernel='polynomial'pour le noyau polynomial, etgammacomme paramètre du noyau choisi. L’optionfit_inverse_transform=Truepermet d’activer l’inverse transform.Après KernelPCA, on peut revenir dans l’espace original avec la méthode
inverse_transformdeKernelPCA.
En traçant data_standardized en nuage de points et data_kpca_reconstructed en courbe, on obtient cette fois :

KernelPCA parvient cette fois à produire un sous‑espace non linéaire, cohérent avec ce que nous avions visualisé auparavant :

Le revers de la médaille
Le prix à payer, c’est le temps de calcul.
Rappelons que la complexité en temps de PCA est déjà cubique par rapport au nombre de dimensions.

KernelPCA, quant à lui, repose sur l’astuce du noyau, dont la complexité est quadratique par rapport au nombre d’observations n.
Au final, cela accroît encore le temps de calcul global.
C’est donc un aspect à garder en tête avant d’utiliser le KernelPCA.
💡 En continuant, tu vas découvrir :
Pourquoi visualiser un dataset en 2D avec le PCA peut être trompeur, et comment vérifier avec la variance expliquée cumulée que les deux premières composantes suffisent vraiment
Pourquoi la distance euclidienne se trompe quand les features sont corrélées, et comment la distance de Mahalanobis corrige cela, par exemple pour repérer des outliers
Pourquoi la corrélation ne mesure pas le pouvoir prédictif, et comment le Predictive Power Score et la corrélation de Spearman comblent ses limites
Pourquoi les statistiques de synthèse et les boxplots peuvent cacher des distributions très différentes, et quels graphiques utiliser en complément
Comment détecter un covariate shift multivarié que les tests variable par variable ne voient pas, grâce à la reconstruction de données avec un autoencodeur
La suite de ce mini-cours est réservée aux membres du Cercle des Experts.
Tu as déjà le début. Pour accéder à l’explication complète et aux autres mini-cours, rejoins le Cercle des Experts.
Rejoindre le Cercle des ExpertsEn devenant membre, tu débloques :
- L’intégralité de ce mini-cours, sans coupure
- Tous les mini-cours et les ressources associées
- Chaque nouveau mini-cours dès sa sortie
