Un piège réel : l'importance trompeuse d'une feature
Comme le module 3, cette leçon documente un résultat réellement obtenu en préparant ce cours, pas un exemple construit pour la démonstration.
Un premier entraînement, en apparence concluant
Section titled “Un premier entraînement, en apparence concluant”from sklearn.ensemble import RandomForestClassifierfrom sklearn.preprocessing import StandardScaler
feature_cols = ["taux_retard_recent", "montant_moyen_recent", "ecart_taux_secteur", "secteur_BTP", "secteur_Commerce", "secteur_Industrie", "secteur_Services"]
X_train_scaled = scaler.fit_transform(X_train)X_test_scaled = scaler.transform(X_test)
clf = RandomForestClassifier(n_estimators=200, random_state=42)clf.fit(X_train_scaled, y_train)
for name, imp in sorted(zip(feature_cols, clf.feature_importances_), key=lambda x: -x[1]): print(f"{name}: {imp:.4f}")montant_moyen_recent: 0.8246secteur_BTP: 0.0498taux_retard_recent: 0.0459ecart_taux_secteur: 0.0450secteur_Services: 0.0190secteur_Commerce: 0.0099secteur_Industrie: 0.0057Le montant moyen récent des factures capte à lui seul 82 % de l’importance totale. Un résultat qui devrait immédiatement éveiller les soupçons : rien, dans la construction des données de ce module, ne relie le montant d’une facture au fait qu’elle soit payée en retard — seul le secteur du client détermine réellement le risque.
Pourquoi cette feature ressort-elle autant ?
Section titled “Pourquoi cette feature ressort-elle autant ?”feature_importances_ d’un RandomForestClassifier mesure, par défaut, la réduction moyenne d’impureté (Gini) apportée par chaque feature à chaque nœud de chaque arbre — une métrique connue pour être biaisée en faveur des features continues à forte cardinalité. montant_moyen_recent prend potentiellement une valeur différente par ligne, ce qui offre à l’algorithme d’innombrables seuils de coupure possibles pour, involontairement, mémoriser des particularités du jeu d’entraînement plutôt qu’apprendre un signal réel — quand bien même le split est fait par client (leçon précédente). Une variable catégorielle à 4 modalités (secteur) n’offre, elle, que quelques coupures possibles.
La correction : écarter la feature sans signal
Section titled “La correction : écarter la feature sans signal”feature_cols = ["taux_retard_recent", "ecart_taux_secteur", "secteur_BTP", "secteur_Commerce", "secteur_Industrie", "secteur_Services"]# ... reentrainement ...secteur_BTP: 0.3408taux_retard_recent: 0.2202ecart_taux_secteur: 0.2172secteur_Services: 0.1235secteur_Commerce: 0.0588secteur_Industrie: 0.0396Une fois montant_moyen_recent écartée, le classement retrouve du sens : secteur_BTP domine, cohérent avec le taux de retard du BTP (40 %) très supérieur aux autres secteurs dans les données générées pour ce module.
La leçon à retenir
Section titled “La leçon à retenir”Une feature avec une importance anormalement élevée mérite d’être questionnée avant d’être célébrée. Elle peut révéler une vraie découverte… ou un artefact statistique (biais de cardinalité, fuite de données, corrélation avec l’identité d’une entité plutôt qu’avec le phénomène étudié).
Dans un contexte professionnel, une piste pour trancher plus rigoureusement est la permutation importance (sklearn.inspection.permutation_importance), moins sensible à ce biais qu’une importance basée sur l’impureté — une piste volontairement laissée pour approfondissement plutôt que traitée ici en détail.
Prochaine étape
Section titled “Prochaine étape”👉 Entraîner une forêt aléatoire et lire une matrice de confusion
Junior TSAFACK – 12/09/2026