Machine Learning · Insper

Explainability

Fundamental approach

Which features does a model rely on, with what shape, and why did it make this prediction?

A good prediction nobody can read

  • Random forests, gradient boosting and neural networks won the last lessons.
  • A boosted ensemble of 200 trees predicts well, but "why this number?" has no answer you could write on a page.

global

which features does the model rely on, overall?

local

why did it make this prediction for this row?

Running example: California housing, the median house value of a district from its income, its houses and its position. The lab: why was this loan applicant flagged as high risk?

Why explain a model?

debugging

a model that looks too good usually is: a leaked column shows up at the top of every importance ranking

trust

a doctor, a credit analyst or a judge will not act on a number they cannot question

regulation

Brazil's General Data Protection Law (LGPD, Lei 13.709/2018, art. 20): the right to ask for a review of automated decisions, with "clear and adequate information" about the criteria; Europe's General Data Protection Regulation (GDPR, art. 22) points the same way

science

sometimes the model is a tool to learn about the world, and the explanation is the result

The toolbox of this part

methodquestion it answersscope
coefficients, tree rulesthe model itselfglobal
impurity importance (MDI, mean decrease in impurity)which features did the training splits use most?global, trees
permutation importancehow much does the score depend on each feature?global
partial dependence plot (PDP)how does the average prediction change with one feature?global
ICE curves (individual conditional expectation)... and for each row?local, many rows
SHAP values (SHapley Additive exPlanations)how much did each feature move this prediction from the average?local → global

Model-specific methods read the internals; model-agnostic ones only call predict. LIME, a second local method, is in the advanced approach.

The path of this part

  1. Readable firstcoefficients, tree rules, the price of readability
  2. What matterspermutation importance, on held-out data
  3. With what shapepartial dependence and ICE curves
  4. Why this predictionShapley values, SHAP waterfalls and beeswarms
  5. Read with carenot causation; right for the wrong reasons
Each stage answers one question: do we need a black box at all? → which features does the score need? → how does the prediction change with one feature? → why this prediction, for this row? → what can an explanation honestly claim?
Stage 1 · do we need a black box at all?

First: do you need a black box?

Three candidates on the same five folds, from fully readable to not readable at all.

Predict. A linear regression, a depth-3 tree and gradient boosting with 200 trees. How much R² do the two readable models give up?

Readability has a price, here

linear regression

0.602
CV R² ± 0.017

tree, depth 3

0.526
CV R² ± 0.016

gradient boosting

0.823
CV R² ± 0.007 · test 0.825
Twenty-two points of R² is too much to give away: here the black box wins. The gap is not always there: in the lab, on credit data, a logistic regression and a random forest are statistically tied, and then the interpretable model should be used (Rudin, 2019).

What the readable models say

eight coefficients

$10,000 more income → +$44,140 (with the others fixed); one degree north → −$41,300.

rooms −11.65 and bedrooms +63.55 have opposite signs: they are correlated (0.85), so "one more bedroom at a fixed number of rooms" means converting a room.

eight rules

Anyone can follow a district down the tree:

income above $78,000 → $457,900.

From now on model is the black box: 200 trees with up to 16 leaves each. The rest of the lesson opens it.
Stage 2 · which features does the score need?

Permutation importance: shuffle one column

  1. Take held-out data and the model's score on it.
  2. Shuffle one column: its values stay, its link with the target and with the rest of each row breaks.
  3. Measure the drop in the score. Repeat for every column (Breiman, 2001).

for col in X_test.columns:
    X_perm = X_test.copy()
    X_perm[col] = rng.permutation(X_perm[col].to_numpy())
    drops[col] = base - r2_score(y_test, model.predict(X_perm))
  
If the model relied on the column, it now receives garbage and the score falls; if it ignored the column, nothing happens.

Permutation importance, by hand

4,087 held-out districts, R² = 0.825 with nothing shuffled; each column shuffled 5 times. Predict. Can shuffling one column cost more than 0.825?

Two rankings of the same model

permutationMDI
latitude1.3460.103
longitude1.1870.117
income0.5320.567
occupancy0.1340.130
rooms0.0560.024
population0.0030.009

permutation_importance runs the same loop: the by-hand numbers (latitude 1.330, income 0.539, population 0.002) agree to about two decimals.

Shuffling latitude "costs" 1.330: R² from 0.825 to about −0.5, much worse than predicting the average for everybody.

Why it can exceed 0.825 is in the advanced approach: impossible rows.

Held-out data, not training data

A forest with two noise columns: a continuous one and a coin flip.

A random forest with two noise columns: MDI gives the continuous noise 0.018 against 0.002 for the coin flip; permutation on the training set gives it 0.016, on the test set 0.000
MDI: noise 0.018, coin 0.002. It rewards many distinct values.
permutation on train: noise 0.016. Fooled the same way.
permutation on test: noise −0.000. The number to report.
Stage 3 · how does the prediction change with one feature?

Partial dependence: in which direction, with what shape?

Set feature \(j\) to a value \(v\) in every row, keep the rest, average the predictions (Friedman, 2001):

\[ \mathrm{PD}_j(v) = \frac{1}{n}\sum_{i=1}^{n} \hat f\bigl(x_{i,1}, \dots,\, v,\, \dots, x_{i,d}\bigr) \]

\(n\): number of rows (4,087 test districts); \(x_{i,k}\): feature \(k\) of row \(i\), unchanged except feature \(j\), replaced by \(v\); \(\hat f\): the model's prediction.


by_hand = [model.predict(X_test.assign(income=v)).mean() for v in grid]
  

The PDP of income, by hand

Grid: income 1.5 to 10 ($10,000). Each step gives every one of the 4,087 rows that income. Predict. Does the predicted value grow steadily with income, or does it saturate?

ICE: one curve per row

ICE curves for income: every district gains when income rises from $20k to $80k, on average +208k, but from +139k to +269k depending on the district

Income from $20,000 to $80,000: +$208,000 on average (the PDP), but from +$139,000 to +$269,000 district by district (5th to 95th percentile).

Parallel ICE curves: the PDP tells the whole story. Fanning out: the model learned interactions, and the average hides them.
Stage 4 · why this prediction, for this row?

SHAP: why this prediction, for me?

Split one prediction into contributions, one per feature, that add up exactly:

\[ \hat f(x) = \underbrace{\phi_0}_{\text{base value}} + \phi_1 + \phi_2 + \dots + \phi_d \]
  • \(\phi_0\): the average prediction over a background dataset; \(\phi_j\): the share of feature \(j\) in the gap \(\hat f(x) - \phi_0\).
  • Features are players; the prediction is the team's payout (Shapley, 1953; Lundberg & Lee, 2017).
  • Value of a coalition \(S\), written \(v(S)\): set the features in \(S\) to the row's values, take the others from the background, average.
  • \(\phi_j\): the average of \(v(S \cup \{j\}) - v(S)\) over the coalitions \(j\) can join, every order of arrival equally likely.

A toy model, small enough for a calculator

\[ f = 100 + 80\,\text{rich} + 60\,\text{coastal} + 40\,\text{rich}\cdot\text{coastal} + 20\,\text{big} \quad (\$1{,}000) \]
  • Background: four districts, worth 120, 180, 160 and 100. So \(v(\varnothing) = 140\).
  • We explain a rich, coastal, not big district: \(f(x) = 280\).
Predict. Being rich and coastal is worth 40 more than the two separately. How should Shapley split those 40?

Follow the arrows where "rich" joins

The 8 coalitions of the toy model with their values; the four arrows where rich joins a coalition contribute +70, +90, +70, +90

\(v(\{\text{rich}\})\): set rich = 1 in the four districts: 200, 180, 280, 180, average 210.

\[ \phi_{\text{rich}} = \tfrac13(210-140) + \tfrac16(285-195) + \tfrac16(205-135) + \tfrac13(280-190) = 80 \]

Every number makes sense

rich: 80

main effect 80 × (1 − ¼) = 60, plus half of the interaction, 20

coastal: 65

45 + 20: the interaction is split equally

big: −5

20 × (0 − ¼): not big, while a quarter of the background is

80 + 65 − 5 = 140 = 280 − 140. The only attribution with these four properties:

efficiency (they add up) · symmetry · dummy (no effect → 0) · additivity (a sum of models → a sum of values)

shap.TreeExplainer on a tree that reproduces the formula returns [80, 65, −5] and base value 140.

Simulator: every coalition, every arrival order

Predict. Turn coastal off. Does the interaction still split in half? Does the waterfall still land on the prediction?

On the real model: a San Francisco district

  • 8 features: \(2^8 = 256\) coalitions × 100 background districts = 25,600 predictions.
  • Brute force and TreeExplainer agree to the sixth decimal (largest difference 2e-06).
\[ \underbrace{207.39}_{\text{base value}} + \underbrace{222.35}_{\sum \phi} = 429.74 = \texttt{model.predict} \]
With 20 features brute force would need a million coalitions per row. TreeExplainer gets the same exact numbers by walking each tree once per row (Lundberg et al., 2020).

Reading a waterfall

Waterfalls for two districts: San Francisco, predicted 430k from a base of 207k; Fresno, predicted 271k

San Francisco (430k): longitude +185.6 and latitude −64.6, so location +121.0; low occupancy +66.3; old houses +34.2; an ordinary income, +2.6.

Fresno (271k): a high income (7.22) adds +145.2; location −88.3.

The same feature pushes up in one row and down in another: a local explanation is about this row.

Global: local explanations, stacked

Beeswarm of 300 districts: high incomes push the prediction up, high occupancy and northern latitudes push it down

300 districts × 8 SHAP values. Mean |SHAP|, in $1,000: latitude 76.6, longitude 64.1, income 44.2, occupancy 22.5 ...

The beeswarm shows direction too: high incomes on the right, high occupancies and northern latitudes on the left.

Stage 5 · what can an explanation honestly claim?

Explanation ≠ causation

  • "Low occupancy (1.98 people per household) adds $66,300 to the predicted price of the San Francisco district" (its SHAP value) is a true statement about the model.
  • It does not mean that moving people out of a house makes it more expensive: crowded households are a marker of poorer neighborhoods.
  • For auditing: if a credit model leans on the postcode, it may use it as a proxy for income or ethnicity.
To claim that a feature causes an outcome you need experiments or causal inference, not SHAP.

Right for the wrong reasons

Hospital A: patients too sick to stand get the portable scanner. Hospital B: scanners assigned at random.

Predict. A model trained on hospital A scores 93.4% on a validation split of A. What does it score on hospital B?

hospital B

53.8%
barely better than a coin

permutation importance

scanner 0.393; medical markers 0.012 at most

markers only

73.0% on A, 74.7% on B

No validation on A could have warned you. The explanation did; only domain knowledge says the reliance will not survive.

Summary

  1. Readable first: if an interpretable model is as good on the same folds, use it.
  2. Permutation importance, on held-out data: how much the score needs each feature.
  3. PDP for the average shape of an effect, ICE for the rows behind it; fanning curves mean interactions.
  4. SHAP: contributions that add up exactly to prediction − base value; stacked, a global ranking with directions.
  5. An explanation describes the model, not the world; when one feature dominates, ask when is this value recorded?
questionmethod
which features does the score need?permutation importance, held-out
how does the prediction change with one feature?PDP + ICE
why this prediction, for this row?SHAP waterfall
Fundamental lab · about 40 min, in pairs

Explaining credit decisions, steps 1 to 7

  • German credit: 1,000 loans, 20 attributes, 30% went bad.
  • Scorecard or forest, on the same folds (ROC AUC, area under the receiver operating characteristic curve); then open the forest: MDI against permutation, PDP and ICE, SHAP globally and for the riskiest applicant.
  • Download the lab notebook and open it in Jupyter or Colab (File → Upload notebook).
  • At every step, answer the Predict before running.
  • Simulations: permutation on the training rows (step 4) and a background of good loans only (step 7).

Pace: steps 1 to 3 in 10 min; step 4 and the first simulation in 10 min; steps 5 and 6 in 10 min; step 7 and the second simulation in 10 min.