MODELCATALOG

Why did it decide that.

sklearn.inspection

inspection

Why did it decide that.

1 Get data Something to practise on
2 Split & tune An honest test set
3 Prepare Into numbers a model accepts
4 Compose One object, no leakage
5 Model The algorithm itself
6 Unsupervised No labels available
7 Measure Is it any good, and why
8 Utilities Glue and extension

What it is for

Model-agnostic explanation without adding a dependency. permutation_importance in particular is more trustworthy than the feature_importances_ attribute on tree models, which is biased toward high-cardinality features.

Contents

permutation_importance bank Shuffle a column, measure the damage. Model-agnostic
partial_dependence, PartialDependenceDisplay How predictions move as one feature varies
DecisionBoundaryDisplay Visualise a 2-D decision boundary

Worked examples 2

Runnable, with the arguments that change the outcome called out. Output shapes are shown as comments where they help.

Permutation importance, computed correctly

On the test set, with the metric you actually care about. Running it on training data measures memorisation instead.

from sklearn.inspection import permutation_importance
import numpy as np

r = permutation_importance(
    model, X_test, y_test,           # TEST, not train
    n_repeats=20,
    scoring="average_precision",     # the metric that matters here
    n_jobs=-1, random_state=42,
)

order = r.importances_mean.argsort()[::-1]
for i in order[:12]:
    mean, std = r.importances_mean[i], r.importances_std[i]
    flag = "" if mean - 2 * std > 0 else "   (not distinguishable from 0)"
    print(f"  {feature_names[i]:28} {mean:+.4f} +/- {std:.4f}{flag}")

# Features whose importance is within two standard deviations of zero
# are not doing measurable work. That is a defensible reason to drop
# them, and it reads well in a model document.
#
# Caveat: with two highly correlated features, permuting either alone
# does little because the other carries the signal, so BOTH look
# unimportant. Check correlations before concluding.

Partial dependence: the shape of a relationship

Shows whether the model learned something monotonic and sensible, or something jagged that will not survive contact with new data.

from sklearn.inspection import PartialDependenceDisplay
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(11, 4))
PartialDependenceDisplay.from_estimator(
    model, X_test,
    features=["months_delinquent", "income", ("income", "age")],
    kind="both",             # 'average' plus individual lines (ICE)
    subsample=200,
    ax=ax,
)
plt.tight_layout()

# What to look for: does risk rise monotonically with months
# delinquent? If the curve wiggles, the model has fitted noise, and
# a monotonic constraint in the booster will both improve
# generalisation and make the model defensible.

Worth knowing

  1. For per-row explanations you still want SHAP, which is a separate library. permutation_importance answers the population-level question.

  2. Run permutation_importance on the TEST set, not the training set — otherwise you measure memorisation.