Transformer les variables numériques

Première leçon du cours Feature engineering, en accès libre : environ 15 minutes, 3 exercices et 3 questions de quiz. C'est la leçon de base du catalogue ; dans l'espace étudiant, elle est réécrite pour ton profil.

Objectifs

  • Corriger l'asymétrie d'une variable avec log1p ou PowerTransformer
  • Discrétiser une variable avec KBinsDiscretizer
  • Créer des interactions et des termes polynomiaux avec PolynomialFeatures

Transformations numériquesDiscrétisationInteractions et polynômes

Le feature engineering (ingénierie des variables) consiste à transformer les données brutes pour rendre l’information plus facile à exploiter par le modèle. Sur des données tabulaires, c’est souvent là que se joue l’essentiel de la performance. L’intérêt d’une transformation dépend du modèle : un modèle linéaire en profite beaucoup, un arbre de décision beaucoup moins, car il est insensible à toute transformation monotone (qui conserve l’ordre des valeurs).

Corriger l’asymétrie

Revenus, montants d’achat, nombres de visites : ces variables ont souvent une longue traîne à droite. Quelques très grandes valeurs écrasent les autres et tirent les coefficients d’un modèle linéaire.

import numpy as np
import pandas as pd

rng = np.random.default_rng(0)
revenu = pd.Series(rng.lognormal(mean=10, sigma=1, size=1000))
print(revenu.skew())             # environ 2.8 : forte asymétrie
print(np.log1p(revenu).skew())   # proche de 0 après transformation

np.log1p(x) calcule log(1 + x) et accepte les zéros. Dans un pipeline, on l’encapsule dans un FunctionTransformer(np.log1p). Pour une transformation apprise automatiquement :

  • PowerTransformer(method="yeo-johnson") (défaut) cherche la puissance qui rend la distribution la plus gaussienne possible, valeurs négatives comprises ; method="box-cox" exige des valeurs strictement positives ;
  • QuantileTransformer(output_distribution="normal") force une distribution cible à partir des rangs, très robuste aux valeurs extrêmes.

Si c’est la cible de régression qui est asymétrique, utilisez TransformedTargetRegressor(regressor=..., func=np.log1p, inverse_func=np.expm1) : le modèle apprend sur le log, et les prédictions sont automatiquement ramenées à l’échelle d’origine.

Discrétiser

KBinsDiscretizer découpe une variable continue en intervalles :

from sklearn.preprocessing import KBinsDiscretizer

kb = KBinsDiscretizer(n_bins=4, encode="ordinal", strategy="quantile")
tranche = kb.fit_transform(revenu.to_frame())   # 0, 1, 2 ou 3 (quartiles)
print(kb.bin_edges_[0])                          # bornes apprises sur les données

strategy="quantile" crée des tranches de même effectif, "uniform" des tranches de même largeur. Avec encode="onehot" (défaut), chaque tranche devient une colonne binaire, ce qui permet à un modèle linéaire d’apprendre un effet non linéaire par paliers. La discrétisation fait perdre de l’information fine : utilisez-la quand l’effet est réellement par seuils ou pour la lisibilité (tranches d’âge).

Interactions et polynômes

Un modèle linéaire additionne les effets. Si l’effet d’une variable dépend d’une autre (par exemple surface × quartier), il faut lui fournir le produit :

from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import cross_val_score

X = rng.uniform(-2, 2, size=(400, 2))
y = 3 * X[:, 0] * X[:, 1] + X[:, 0] + rng.normal(0, 0.3, 400)   # interaction pure

lineaire = LinearRegression()
poly = make_pipeline(PolynomialFeatures(degree=2, include_bias=False), LinearRegression())
print(cross_val_score(lineaire, X, y, cv=5).mean())   # environ 0.05
print(cross_val_score(poly, X, y, cv=5).mean())       # environ 0.99
print(poly.fit(X, y)[0].get_feature_names_out(["a", "b"]))   # ['a' 'b' 'a^2' 'a b' 'b^2']

Attention à l’explosion combinatoire : avec 50 features et degree=2, on obtient 1 325 colonnes. Utilisez interaction_only=True pour ne garder que les produits, combinez avec une régularisation (Ridge) et standardisez ensuite. SplineTransformer est une alternative souvent plus stable aux polynômes pour modéliser des courbes.

Exercices

Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.

  1. CodeDifficulté 1Python dans le navigateur1 indice

    Réduire l'asymétrie

    Calculez l’asymétrie (.skew()) de la Series montants dans skew_avant, puis appliquez np.log1p et stockez la Series transformée dans montants_log et son asymétrie dans skew_apres.

    import numpy as np
    import pandas as pd
    
    rng = np.random.default_rng(42)
    montants = pd.Series(rng.lognormal(mean=4, sigma=1.2, size=2000))
    skew_avant = ...
    montants_log = ...
    skew_apres = ...
  2. CodeDifficulté 2Python dans le navigateur2 indices

    Capturer une interaction

    La cible dépend du produit des deux features. Construisez poly, un pipeline PolynomialFeatures(degree=2, include_bias=False) + LinearRegression(), puis stockez les R² moyens de validation croisée (cv=5) d’une LinearRegression() seule dans r2_lin et de poly dans r2_poly.

    import numpy as np
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.linear_model import LinearRegression
    from sklearn.pipeline import make_pipeline
    from sklearn.model_selection import cross_val_score
    
    rng = np.random.default_rng(0)
    X = rng.uniform(-2, 2, size=(400, 2))
    y = 3 * X[:, 0] * X[:, 1] + X[:, 0] + rng.normal(0, 0.3, 400)
    poly = ...
    r2_lin = ...
    r2_poly = ...
  3. QCMDifficulté 21 indice

    Transformation et arbres

    Appliquer np.log1p à une feature change-t-il les prédictions d’un arbre de décision ?

    • Oui, fortement
    • Non, ou presque pas : la transformation est monotone et l'arbre ne dépend que de l'ordre des valeurs
    • Oui, l'arbre exige des données gaussiennes
    • L'arbre refuse les valeurs transformées

Quiz de fin de leçon

  1. Pourquoi préférer np.log1p à np.log ?

    • Il est plus rapide
    • Il gère les valeurs nulles (log(1 + 0) = 0)
    • Il ne change pas les données
    • Il standardise
  2. Quel est le principal risque de PolynomialFeatures(degree=3) sur 40 features ?

    • Aucun
    • L'explosion du nombre de colonnes et le surapprentissage
    • La perte des valeurs manquantes
    • La suppression des interactions
  3. Que fait TransformedTargetRegressor ?

    • Transforme les features
    • Entraîne le modèle sur une cible transformée et ramène les prédictions à l'échelle d'origine
    • Sélectionne des features
    • Discrétise la cible

La suite du cours

  1. Encoder les variables catégorielles15 min
  2. Traiter les valeurs manquantes15 min
  3. ColumnTransformer : des pipelines pour données hétérogènes20 min
  4. Créer des features métier et temporelles15 min
  5. Sélectionner les features utiles15 min

Feature engineering · Avancé · 3 h 35