08 — Understand Your Features

Permutation Importance#

FeaturesStatistical 1 min read
◆ The PatternShuffle a feature, measure the damage — a model-agnostic way to rank feature importance

Permutation importance randomly shuffles one feature at a time and measures how much the model's score drops. Big drop = important feature. It works with any model and requires no retraining.

PIᵢ = Scoreoriginal − Scoreshuffled(i)
PI = importance of feature i. Higher = more important. Negative = feature hurts the model.
// Interactive — shuffle features, see score drop
Features5
Correlated features trap: If two features are correlated, shuffling one leaves the other intact — importance is split between them. Consider using SHAP or drop-column importance for correlated features.
Pattern bridge: Shuffle an input and see if anything breaks — a controlled experiment that also tests a trading signal in alpha research. Importances that shift over time are an early warning in model monitoring.
Worked example

y depends on x₁ alone. Shuffling x₁ in a model that uses only x₁ raises the error by 7.95. Add x₂, an almost exact copy, and let the model split the weight: shuffling x₁ now raises the error by just 1.95, because x₂ still carries the information. Correlated features make each other look unimportant.

Where it misleads
  • Permuting a feature that is correlated with others creates impossible rows, and the model is judged on data it never saw (Hooker, Mentch & Zhou 2021).
  • Importance on the training set reflects memorisation; compute it on held-out data.
  • Low importance does not mean a feature is irrelevant to the outcome — only that this model does not need it.
In code
rng = np.random.default_rng(4)
n = 5_000
x1 = rng.normal(size=n); x2 = x1 + rng.normal(0, 0.05, n)    # x2 almost a copy of x1
y = 2 * x1 + rng.normal(0, 0.5, n)

def importance(X, w, col):
    base = ((X @ w - y) ** 2).mean()
    Xp = X.copy(); Xp[:, col] = rng.permutation(Xp[:, col])
    return ((Xp @ w - y) ** 2).mean() - base

alone = importance(x1[:, None], np.array([2.0]), 0)
both = importance(np.c_[x1, x2], np.array([1.0, 1.0]), 0)     # a model that split the weight
Python, in your browser — edit the code and run it again

Assumes import numpy as np and import pandas as pd (and SciPy where imported). Each snippet simulates or makes up its own data, as the comments say.

The same idea with a library
# Python — permutation importance
from sklearn.inspection import permutation_importance

result = permutation_importance(
    model, X_test, y_test,
    n_repeats=30, random_state=42,
    scoring='accuracy'
)

# Sorted importance
for i in result.importances_mean.argsort()[::-1]:
    print(f"{features[i]}: {result.importances_mean[i]:.3f}")
Sources
  • L. Breiman, “Random Forests”, Machine Learning 45(1), 2001
  • C. Strobl, A.-L. Boulesteix, T. Kneib, T. Augustin & A. Zeileis, “Conditional Variable Importance for Random Forests”, BMC Bioinformatics 9, 2008
  • G. Hooker, L. Mentch & S. Zhou, “Unrestricted Permutation Forces Extrapolation”, Statistics and Computing 31, 2021

Last reviewed October 2026 · How this site checks its content · Report a mistake

Linked from 3
← Previous
SHAP Values
Open in the full reader, with the topic sidebar