Feature Explanation¶
Feature explanation helps us understand how individual features impact the output — critical for feature selection, bias detection, and explaining decisions.
Information Value (IV) Plots¶
IV Plots combine Weight of Evidence (WoE) and Information Value (IV) to quantify a feature's predictive power.
Weight of Evidence (WoE)¶
Where events = favourable outcomes, non-events = unfavourable outcomes, and \(i\) represents a bin of the feature.
WoE Interpretation
- WoE > 0: Bin has more events than expected → favourable
- WoE < 0: Bin has fewer events than expected → unfavourable
- WoE = 0: No predictive power in this bin
Information Value (IV)¶
| IV Range | Predictive Power |
|---|---|
| < 0.02 | Not useful |
| 0.02 – 0.1 | Weak |
| 0.1 – 0.3 | Medium |
| 0.3 – 0.5 | Strong |
| > 0.5 | Suspicious (too good — check for overfitting) |
import numpy as np
import pandas as pd
def compute_woe_iv(df, feature, target, bins=10):
"""Compute WoE and IV for a feature."""
# Bin continuous features
if df[feature].nunique() > bins:
df['bin'] = pd.qcut(df[feature], q=bins, duplicates='drop')
else:
df['bin'] = df[feature]
grouped = df.groupby('bin')[target].agg(['sum', 'count'])
grouped.columns = ['events', 'total']
grouped['non_events'] = grouped['total'] - grouped['events']
# Distribution
total_events = grouped['events'].sum()
total_non_events = grouped['non_events'].sum()
grouped['dist_events'] = grouped['events'] / total_events
grouped['dist_non_events'] = grouped['non_events'] / total_non_events
# WoE and IV
grouped['woe'] = np.log(
grouped['dist_events'].clip(0.0001) /
grouped['dist_non_events'].clip(0.0001)
)
grouped['iv'] = (grouped['dist_events'] - grouped['dist_non_events']) * grouped['woe']
iv_total = grouped['iv'].sum()
df.drop('bin', axis=1, inplace=True)
return grouped, iv_total
Partial Dependence Plots (PDP)¶
PDPs show the marginal effect of a feature on the predicted outcome, averaging over all other features.
Where \(x_s\) is the feature of interest and \(x_c\) are all other features.
from sklearn.inspection import PartialDependenceDisplay
import matplotlib.pyplot as plt
# After training a model
PartialDependenceDisplay.from_estimator(
model, X_test, features=[0, 1, 2],
kind='average', grid_resolution=50
)
plt.tight_layout()
plt.show()
SHAP Values¶
SHAP (SHapley Additive exPlanations) assigns each feature an importance value based on game theory — how much does each feature contribute to moving the prediction from the baseline?
import shap
# Train your model first
explainer = shap.Explainer(model, X_train)
shap_values = explainer(X_test)
# Summary plot
shap.summary_plot(shap_values, X_test)
# Individual prediction
shap.waterfall_plot(shap_values[0])
SHAP for Fairness
Compare SHAP values across protected groups. If a protected feature (or its proxy) has high SHAP importance, your model may be learning bias.
Next: Model Explanation →