Feature Engineering

Feature engineering changes the representation so a model can express the relevant relationship. It is especially important for linear models, where the model may be simple but the features can encode nonlinearities, interactions, lags, bins, or domain aggregates.

Why representation matters

A simple model can only use what the representation makes visible. If the target is quadratic in a raw input, a straight-line model fails; adding gives the same estimator the right coordinate system. Common transformations each expose a different kind of structure:

TransformationExampleStructure it exposes
Polynomialcurvature
Interactionjoint effects
Binningage → age bracketnon-monotone effects
Lag / rolling, moving averagetemporal structure
Target-aware encodingcategory → mean of high-cardinality categories (leakage-prone)

The feature map

A model trained on engineered features predicts , where is a fixed feature map that transforms the raw input and is the learned model. Polynomial features, for example, expand a single variable to degree : . Feature maps alter both approximation power and risk. More features can reduce bias, but they increase variance and often require regularization. Every learned transformation must be fit inside the training split to avoid data leakage.

Worked example

The code uses a target that is quadratic in one raw feature. It compares a plain linear model with the same model after adding a degree-2 polynomial feature.

import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
 
rng = np.random.default_rng(16)
X = rng.uniform(-2, 2, size=(160, 1))
y = 3 * X[:, 0] ** 2 + rng.normal(0, .5, size=160)
Xtr, Xte, ytr, yte = train_test_split(X, y, random_state=16)
for name, pipe in [("linear", LinearRegression()),
                   ("poly2", make_pipeline(PolynomialFeatures(2, include_bias=False), LinearRegression()))]:
    pipe.fit(Xtr, ytr)
    print(name, "test_r2", round(pipe.score(Xte, yte), 3))

Observed output:

linear test_r2 -0.106
poly2 test_r2 0.991

The raw linear model misses the U-shape completely. The quadratic feature makes the structure available without changing the final estimator class.

Caveats

Target encodings, rolling aggregates, and normalization are high-risk leakage points. High-cardinality categorical expansion can create sparse features that overfit rare categories. Feature engineering should be evaluated through the same model selection protocol as model hyperparameters.

References