ML Systems Lab Open interactive version →
Intermediate 45 min read feature selectioncurse of dimensionalityLASSORFEmutual information

Feature Selection

Reduce dimensionality to fight overfitting, cut training cost, and build models that generalize.

A data warehouse dumps 500 features into your fraud model — transaction details, user behaviour, device fingerprints, merchant info, and hundreds of derived aggregates. Training on all 500 takes four hours, inference crawls at 900ms per request, and the serving box runs out of memory. You need to get under 50 features. But *which* 50?

There are four families of ways to choose, trading speed for smartness — and one trap that snares all of them.


Filter methods — score each feature alone

The fastest approach ranks each feature on its own — how strongly does it relate to fraud, by correlation or mutual information — and keeps the top ones. Cheap and parallel. The catch is baked in: it judges features *one at a time*, so it will happily throw away two features that are useless alone but powerful *together*. Interactions are invisible to it.


Wrapper methods — let the model judge

These actually train the model on different feature subsets and keep whichever scores best. Recursive feature elimination trains on all 500, drops the single weakest, retrains, and repeats down to 50 — around 450 model fits, but every decision is *model-aware*, so it can tell when two features are redundant given the others.


Embedded methods — select while training

L1 (Lasso) regularisation drives useless features' weights to exactly zero *during* fitting, so selection and training happen in one run — no separate step. The reason is geometric: L1's penalty region is a diamond whose corners sit exactly on the axes, so the optimum often lands on a corner — a weight at exactly zero. (Ridge/L2's penalty region is a smooth sphere with no corners, so the optimum rarely lands on an axis; weights shrink toward zero but almost never reach it, so it does not select.)


Permutation importance — the honest referee

Train any model, then *shuffle* one feature's values and see how much performance drops on held-out data. A big drop means the feature was pulling its weight; no drop means it was redundant or noise. This is the method to trust, because it measures real, out-of-sample usefulness — and it catches a nasty trap that tree-based importance falls into. That trap: a tree's built-in importance is biased toward *high-cardinality* columns. Feed it a `customer_id` and it will "split" on individual IDs to memorise the training set, scoring the ID as hugely important — while on new customers it is worth exactly nothing. Permutation importance on validation data exposes this instantly (shuffling the ID changes nothing), where the tree's own numbers are fooled.


The trap that snares all four: correlation is not importance

It is tempting to say "these two features are 95% correlated, drop one." Resist it. Two correlated features can still both help — keeping both can make the model steadier when one of them drifts at serving time. Correlation describes the *inputs*; it does not tell you the *predictive contribution*. So decide what to keep by measuring importance directly — permutation importance on validation data — not by eyeballing a correlation matrix.


A separate problem for linear models: multicollinearity

Keeping correlated features helps *predictive* stability, but for a *linear* model specifically, near-duplicates (`height_cm` and `height_inches`, correlated 0.97) create a different failure. The design matrix is nearly singular, so infinitely many weight combinations — a large positive weight on one feature, a canceling negative weight on the other — fit the training data almost equally well. Predictions stay fine; the *individual coefficients* become wildly unstable and impossible to interpret. This is multicollinearity, measured by VIF (variance inflation factor: `VIF = 1 / (1 - R²)`, where R² comes from regressing that feature on the rest) — a high VIF flags exactly this instability, a separate concern from the importance-vs-correlation trap above.


Selection is preprocessing — do it inside the CV folds

The trap that quietly inflates every method above: feature selection uses the labels, so it leaks if done on the full data before splitting. Rank features by correlation/MI/importance across the whole dataset, then cross-validate, and the "held-out" folds already helped choose the features — your score is optimistic. Selection (filter, wrapper, embedded, RFE, target-based) must run inside each CV fold on the training portion only, exactly like a scaler or encoder. Wrap it in a Pipeline so it can't be skipped.


Is the selection stable?

A feature set from one run can be a fluke of that sample. Stability selection reruns the choice across bootstraps or folds and keeps only the features chosen *consistently* — a feature that appears in 90% of runs is real signal, one that flickers in and out is noise dressed as signal. This matters most with correlated features, where which one gets picked can flip run to run (Lasso is notorious for this). Stable selections generalise; one-run selections often don't.


Caveats on the tools you'll reach for

Mutual information catches non-linear dependence (unlike correlation) but as usually applied is univariate (misses features that only matter in combination) and is noisy and sample-size/binning sensitive. SHAP attributes predictions well but splits credit among correlated features (a truly important feature can look weak because its twin absorbed the attribution) and shows what the *model* used, not causation — high SHAP ≠ causal. Embedded tree selection isn't just "use importance": the tree's own knobs (`min_child_weight`, `gamma`, `max_depth`, `colsample_bytree`, feature subsampling) *are* a form of regularised selection, pruning weak features during training. Read all of them with the correlation caveat.


Selection versus reduction, and the cost you forget

Keep feature selection (keeps a subset of your *original, explainable* features) separate from dimensionality reduction like PCA (invents new latent components — compact but no longer interpretable). Choose selection when you must explain the model, reduction when you only need fewer numbers. And selection isn't only about accuracy: weigh the operational cost of each feature — its serving latency, freshness requirements, compute cost, upstream data-dependency risk, and whether it's even available at prediction time. A feature that adds 0.1% AUC but depends on a flaky third-party call at serving time is usually not worth keeping. Finally, on redundancy: correlated features can actually *help stability* (keep both as insurance against drift), but genuine duplicates, proxies, and leaky features should still be removed.

Key points

Takeaway

Feature selection is a bias-variance decision: too many features and the model memorizes noise; too few and it misses signal — and because correlation is not importance, the right ranking method matters as much as the threshold.

Recap

Check your understanding

Q1. You filter features by Pearson correlation with target and retain only top 20. Your model performs worse than with all 100 features. What most likely went wrong?

Q2. Why does LASSO shrink some coefficients to exactly zero while Ridge (L2) rarely does?

Q3. You compute feature importance from a gradient boosted tree and find that 'customer_id' is the second most important feature. Which TWO of the following are true about what happened and the fix?

Q4. A linear model has two features that are 0.97 correlated (e.g., 'height_cm' and 'height_inches'). What specific failure mode does this cause and fix?

Q5. You rank all 500 features by mutual information with the target on the full dataset, keep the top 50, then run cross-validation and report the CV score. Why is that score optimistic?

Q6. A feature adds a genuine but tiny 0.1% AUC improvement, but computing it at serving time requires a call to a flaky third-party API with 300ms latency. A colleague insists on keeping it "because it helps." How should you frame the decision?

Try it interactively

ML Systems Lab is a free interview-prep platform for ML engineers — work through the full interactive module, quizzes, and drills.

Open ML Systems Lab →