Concepts / Feature Selection Methods

Feature Selection Methods

Every feature is drawn independently from a Gaussian distribution, and the response is also drawn from a Gaussian distribution.

  • Programming

A High Score on Data With No Signal

Cross-validation is supposed to tell you how well a model will perform on data it has never seen. That promise only holds if the test folds stay untouched by the training process. When some information from the test data quietly shapes how the model is built, the score you measure is inflated. This failure is called information leakage, and it is the central idea of this article.

Many people assume that a preprocessing step such as feature selection is harmless as long as the model itself is evaluated with cross-validation. The reasoning goes like this: the selector only chooses columns, the Ridge regressor is what does the learning, and so the cross-validation score reflects the regressor's real ability. This belief is what we are going to test.

The article works through a deliberately unusual case. The data contains no real signal at all, so any model that scores well on it is scoring well for the wrong reason. Watching how such a score can appear is the clearest way to understand how leakage works and where to look for it.

What do you think happens?

Before reading further, commit to a guess. Suppose the features and the target were generated completely independently, so nothing in the inputs can really explain the target. You select the most correlated features using the whole dataset, then run cross-validation on a Ridge regressor using only those selected features. What kind of score do you expect?

Reveal answer
Answer:

The score looks better than it should. Although the data has no signal, the cross-validation score comes out optimistic, and a realistic estimate on this random data should be close to nothing.

The selection step saw every row, including the rows that later served as test folds. It chose features whose correlation with the target was partly chance, and the test folds then appeared to confirm those chance patterns.

The Data Used in This Case

The starting point is a synthetic regression task with 100 samples and a large number of features. Every feature is drawn independently from a Gaussian distribution, and the response is also drawn from a Gaussian distribution. Because of how the data was created, there is no relationship between the features and the target. In principle, nothing can be learned from it.

The leak in this case is subtle because nothing looks wrong on the surface. The code still splits the data into folds, still trains a regressor on training rows, and still scores it on held-out rows. The problem is hidden earlier in the workflow, in a step that touched every row before the split happened.

Tracing the Improper Workflow

The improper workflow runs in a fixed order. First, feature selection is fitted on the full dataset, so every row, including the rows that will later serve as test folds, contributes to deciding which features survive. Second, the reduced dataset is handed to cross-validation, which splits it into folds and fits the Ridge regressor on each training portion. The diagram below traces how data flows through those two stages and shows where the test rows first affect the selector.

Full datasetall rows, including futuretest rowsFeature selectionfitted on every rowReduced datasetonly the selected featuresCross-validationsplitfolds created afterselectionRidge fiton each training portionScoreon held-out test rowsall rows usedfeatures kepttraining foldstest folds
In the improper workflow, at which step does test-fold data first influence the feature selector, and how does that carry into the model fit?

The highlighted step is where the leak enters. The test folds were not held out before selection, so the selector could pick features that happen to be correlated with the target across both the training and the test rows. When the Ridge regressor is later scored on those test rows, the score reflects a pattern that was partly chosen using the test rows themselves. The regressor never saw the test rows during fitting, but the features it was given were already shaped by them.

Why Selection on All Rows Finds Chance Patterns

The reason this matters is that random data always contains some accidental correlations. Among thousands of random features, some will be correlated with the target purely by chance. A selector that looks at all the rows will find those chance correlations and keep them. The test folds then appear to confirm them, because the test rows are part of the same pool that produced the selection.

Worked example

Following one chance feature through the improper workflow

A dataset has many random features and a random target. One feature happens to correlate with the target across all rows, including the rows reserved for testing. What happens to that feature under the improper workflow?

  1. 1
    Step 1: Selection runs on the full dataset

    The selector measures each feature's correlation with the target using every row. The chance feature shows a strong correlation, so it ranks high and is kept.

  2. 2
    Step 2: The split happens after selection

    Cross-validation now divides the reduced dataset into folds. The chance feature is in every fold because it was already chosen.

  3. 3
    Step 3: The regressor is scored on test rows

    The test rows that helped make the feature look strong are used to score the model. The correlation shows up again in the test rows, so the score looks good.

  4. 4
    Step 4: Compare with what the data supports

    The target was generated independently of every feature, so the honest expectation is no real predictive power. The good-looking score is a product of the leak, not of learning.

Result

The improper workflow turns a chance correlation into an apparently confirmed pattern, which inflates the cross-validation score.

Leakage is not caused by the regressor. In this example the divergence is in the earlier feature selection step, and the Ridge regressor behaves normally on the data it receives. This is why checking the regressor first would waste time: the error is upstream of it.

Order of Operations Compared

The difference between the two workflows is only the position of one step, but that step decides whether test rows influence training. In the improper version, selection happens before the split. In the proper version, the split happens first, and selection is repeated for each training fold. The flowchart below places the two sequences side by side so you can see which step moves earlier or later.

Select featureson all rowsSplit into foldsFit Ridgeon training portionScoreon test portionSplit into foldsSelect featureson training fold onlyFit Ridgeon same training foldScoreon untouched test foldper fold
What is the sequence of steps in each workflow, and which step moves earlier or later in the proper version?

In the proper version, selection moves later, after the split and inside each training portion. The test fold is never consulted while choosing features. The same rule applies to any other step that fits itself to data: if it is fitted on rows that later appear as test rows, the score can no longer be trusted as an estimate of performance on unseen data.

Repeating Selection Inside Each Fold with a Pipeline

A pipeline is a sequence of data processing steps that run together. When a pipeline with a feature selector followed by a Ridge regressor is passed to cross-validation, each fold repeats the whole sequence using only that fold's training rows. The selector is therefore fitted inside the loop, and the test fold is never consulted while choosing features. The diagram below shows how the same selector is fitted on training data and then only applied to the test data.

Training foldrows used for learningFeature selectorfitted on training rowsRidge regressorfitted on selected featuresTest foldheld out from selectionSelected featureschosen without the testfoldScorehonest estimatefitfeaturestransform onlypredict
How does a Pipeline make the feature selector refit separately on each training fold, so that each fold's test data is never used to choose features?
python
Notes on the code
  • The improper version fits the selector on the full X and y before cross-validation starts
  • The proper version places the selector inside a pipeline so cross-validation refits it on each training fold
  • k=10 is an arbitrary illustrative choice for how many features to keep

Mistakes That Hide Leakage

  • Common mistake

    Assuming a preprocessing step is harmless because the final model is evaluated with cross-validation

    What it looks like

    Selecting the most correlated features on the full dataset and then running cross-validation only on the regressor

    Why it fails

    The selector learned from rows that later became test rows, so the evaluation no longer measures performance on unseen data

    Do this instead

    Place the selector inside a Pipeline so it is refit on each training fold

  • Common mistake

    Trusting a high score without checking when each data-dependent step was fitted

    Why it fails

    A score that looks too good can come from a step that saw the test rows, and the model's own behavior may be perfectly normal

    Do this instead

    Trace the workflow step by step and check which rows each data-dependent step was fitted on

  • Common mistake

    Checking the regressor first when a score looks suspicious

    What it looks like

    Tuning the Ridge regularization while the leak sits in an earlier selection step

    Why it fails

    In this case the regressor behaves normally, so the error is upstream and the search wastes time

    Do this instead

    Start the audit at the earliest data-dependent step and work forward

  • Common mistake

    Treating a lower cross-validation score after fixing a leak as a regression rather than a more honest measurement

Practice: Locating the Leak

MEDIUM

A colleague reports a cross-validation score that is much higher than expected on a dataset where you know the target was generated independently of all features. The workflow is: fit a feature selector on the full dataset, then pass the selected features to cross-validation with a Ridge regressor. Without changing the regressor, which step should you examine first, at what point does test-fold data first affect the feature selector, and how would you restructure the workflow so that the selector is refit on each training fold?

Hints
  • List every step in the order it runs and mark each one that is fitted to data
  • For each fitted step, ask which rows it saw, and check whether any of those rows later appear as test rows
  • The fix is to move the selector inside a Pipeline so that cross-validation repeats it on each training fold

Key Takeaways

  • Information leakage occurs when information from the test folds influences training, which makes cross-validation scores overly optimistic.
  • Feature selection done on the full dataset before cross-validation can keep features that correlate with the target by chance, and the test folds then appear to confirm them even when the data is random.
  • Locate a leak by tracing the workflow step by step and checking which rows each data-dependent step was fitted on, starting with the earliest such step.
  • A Pipeline keeps feature selection inside each cross-validation loop so the selector only sees training folds, and a lower score from this correct workflow is the more honest estimate.

Related concepts

More concepts starting with F