Transform Numerical Variables

First lesson of the Feature Engineering course, free to read: about 15 minutes, 3 exercises and 3 quiz questions. This is the catalogue's base lesson; in the student space, it is rewritten for your profile.

Objectives

  • Correct the skewness of a variable with log1p or PowerTransformer
  • Discretize a variable with KBinsDiscretizer
  • Create interactions and polynomial terms with PolynomialFeatures

Numerical transformationsDiscretizationInteractions and polynomials

Feature engineering means transforming raw data to make the information easier for the model to use. On tabular data, this is often where most of the performance is won. The value of a transformation depends on the model: a linear model benefits a lot, a decision tree much less, because it is insensitive to any monotonic transformation (one that preserves the order of values).

Correcting skewness

Income, purchase amounts, number of visits: these variables often have a long right tail. A few very large values overwhelm the others and pull on the coefficients of a linear model.

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())             # about 2.8: strong skewness
print(np.log1p(revenu).skew())   # close to 0 after transformation

np.log1p(x) computes log(1 + x) and accepts zeros. In a pipeline, you wrap it in a FunctionTransformer(np.log1p). For an automatically learned transformation:

  • PowerTransformer(method="yeo-johnson") (default) looks for the power that makes the distribution as Gaussian as possible, negative values included; method="box-cox" requires strictly positive values;
  • QuantileTransformer(output_distribution="normal") forces a target distribution based on ranks, very robust to extreme values.

If it is the regression target that is skewed, use TransformedTargetRegressor(regressor=..., func=np.log1p, inverse_func=np.expm1): the model learns on the log, and predictions are automatically brought back to the original scale.

Discretizing

KBinsDiscretizer splits a continuous variable into intervals:

from sklearn.preprocessing import KBinsDiscretizer

kb = KBinsDiscretizer(n_bins=4, encode="ordinal", strategy="quantile")
tranche = kb.fit_transform(revenu.to_frame())   # 0, 1, 2 or 3 (quartiles)
print(kb.bin_edges_[0])                          # edges learned from the data

strategy="quantile" creates bins with the same number of observations, "uniform" bins of the same width. With encode="onehot" (the default), each bin becomes a binary column, which lets a linear model learn a stepwise nonlinear effect. Discretization loses fine-grained information: use it when the effect really works by thresholds or for readability (age brackets).

Interactions and polynomials

A linear model adds up effects. If the effect of one variable depends on another (for example surface area × neighborhood), you must give it the product:

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)   # pure interaction

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

Beware of combinatorial explosion: with 50 features and degree=2, you get 1,325 columns. Use interaction_only=True to keep only the products, combine with regularization (Ridge), and standardize afterwards. SplineTransformer is often a more stable alternative to polynomials for modeling curves.

Exercises

Solutions and tests stay on the server. In the student space, your code is run and checked, and the tutor gives hints before the solution.

  1. CodeDifficulty 1Python in the browser1 hint

    Reduce skewness

    Compute the skewness (.skew()) of the Series montants in skew_avant, then apply np.log1p and store the transformed Series in montants_log and its skewness in 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. CodeDifficulty 2Python in the browser2 hints

    Capture an interaction

    The target depends on the product of the two features. Build poly, a PolynomialFeatures(degree=2, include_bias=False) + LinearRegression() pipeline, then store the mean cross-validated R² (cv=5) of a plain LinearRegression() in r2_lin and of poly in 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. Multiple choiceDifficulty 21 hint

    Transformation and trees

    Does applying np.log1p to a feature change the predictions of a decision tree?

    • Yes, strongly
    • No, or hardly at all: the transformation is monotonic and the tree depends only on the order of values
    • Yes, the tree requires Gaussian data
    • The tree rejects transformed values

End-of-lesson quiz

  1. Why prefer np.log1p over np.log?

    • It is faster
    • It handles zero values (log(1 + 0) = 0)
    • It does not change the data
    • It standardizes
  2. What is the main risk of PolynomialFeatures(degree=3) on 40 features?

    • None
    • An explosion in the number of columns and overfitting
    • Loss of missing values
    • Removal of interactions
  3. What does TransformedTargetRegressor do?

    • Transforms the features
    • Trains the model on a transformed target and brings predictions back to the original scale
    • Selects features
    • Discretizes the target

The rest of the course

  1. Encode Categorical Variables15 min
  2. Handle Missing Values15 min
  3. ColumnTransformer: Pipelines for Heterogeneous Data20 min
  4. Create Business and Time-Based Features15 min
  5. Select the Useful Features15 min

Feature Engineering · Advanced · 3 h 35 min