SHAP Report
Beyond the standard per-source / per-feature / per-value JSON and PNG outputs (see Interpretation overview), interpret() can render a parallel SHAP-library-style report designed for client hand-off. It writes beeswarm, global bar, heatmap, per-entity waterfall, and interactive force plots under a shap/ subdirectory, plus a single static shap_report.html index that links everything — no Jupyter runtime required.
Prerequisite
The SHAP report requires the optional shap extra. Install with poetry install -E interpretability (or pip install '.[interpretability]'). The default attribution flow does not depend on it — shap is imported lazily, only when save_shap_plots=True.
One-Call Rendering
Add save_shap_plots=True to interpret(). GradientSHAP is the recommended companion method for denser, SHAP-shaped attributions, but the report renders identically with Integrated Gradients.
from pathlib import Path
from datetime import datetime, timezone
from monad.interpretability import interpret
interpret(
predictions_path=Path("./predictions.tsv"),
output_path=Path("./interpretations"),
checkpoint_path=Path("./my_model"),
device="cuda",
method="gradient_shap",
save_shap_plots=True,
prediction_date=datetime(2024, 6, 1, tzinfo=timezone.utc),
)
The standard interpretation outputs land at the root of output_path/, and the SHAP-style artifacts go under output_path/shap/:
interpretations/
├── source_importance.json
├── source_importance.png
├── {data_source}/
│ └── ...
└── shap/ # Added by save_shap_plots=True
├── shap_beeswarm.png
├── shap_bar_global.png
├── shap_heatmap.png # Only when n_entities ≥ 10
├── shap_waterfall_top1.png
├── shap_waterfall_top2.png
├── ...
├── shap_force_top1.html
├── shap_force_top2.html
├── ...
└── shap_report.html # Static index — open this first
Open shap/shap_report.html in a browser; it embeds the PNGs and links to each interactive force plot.
Rendering from Existing Attributions
When you already have attributions in memory — for example from a batched custom pipeline that calls a GradientShapInterpreter directly — skip re-running interpret() and render the report from the two public helpers:
from pathlib import Path
from datetime import datetime, timezone
from monad.core import load_from_checkpoint
from monad.interpretability import (
ClassificationGradientShapInterpreter,
MonadExplainer,
attributions_to_shap_explanation,
save_shap_report,
)
checkpoint_path = Path("./my_model")
predictions_path = Path("./predictions.tsv")
output_path = Path("./interpretations")
training_module = load_from_checkpoint(checkpoint_path=checkpoint_path)
interpreter = ClassificationGradientShapInterpreter(
training_module=training_module,
checkpoint_path=checkpoint_path,
predictions_path=predictions_path,
resample=False,
group_size=500,
)
attributions = interpreter.get_attributions(
prediction_date=datetime(2024, 6, 1, tzinfo=timezone.utc),
target=0,
limit_batches=None,
device="cuda",
)
explainer = MonadExplainer(
attributions=attributions,
trained_features=training_module.data_provider.dataset_provider.data.trained_features,
)
explanation = attributions_to_shap_explanation(
attributions=attributions,
feature_slicer=explainer.feature_slicer,
base_value=0.0, # Or compute E[f(baseline)] yourself
output_name="target_0",
)
save_shap_report(
explanation=explanation,
output_path=output_path,
top_n_waterfalls=5,
)
This is the right shape when you want to render the report against a custom subset of entities or alongside other downstream consumers of the raw attributions tensors.
Plot Reference
| Artifact | What it shows |
|---|---|
shap_beeswarm.png |
Per-feature signed distribution across all entities — positive vs. negative contributions at a glance. |
shap_bar_global.png |
Global mean-absolute attribution per feature — the SHAP equivalent of source_importance.png, but at the feature level. |
shap_heatmap.png |
Per-entity × per-feature signed heatmap. Rendered only when n_entities ≥ 10, since the layout assumes a reasonable number of rows. |
shap_waterfall_top{i}.png |
Single-entity additive breakdown — how each feature pushes the prediction up or down from the base value. One file per entity in the top-N by total \|Σ values\|. |
shap_force_top{i}.html |
Interactive HTML version of the waterfall for the same top-N entities. Each file embeds ~2 MB of shap.js, so the count is capped low by default. |
shap_report.html |
Single static index linking everything above. Self-contained — safe to email or zip. |
Individual plot failures (e.g., a SHAP version mismatch on heatmap) are logged and skipped rather than aborting the whole report — shap_report.html only links what successfully rendered.
Tuning
top_n_waterfalls(default5): controls how many highest-impact entities get a dedicated waterfall + force plot. Each force HTML embeds ~2 MB ofshap.js, so keep this modest unless the bundle size doesn't matter.- GradientSHAP knobs (
n_samples,stdevs,seed): not exposed throughinterpret(). To tune them, instantiateGradientShapInterpreterdirectly and callsave_shap_report()yourself (see the example above).
For the full parameter list of the helpers, see Reference: Interpretability — SHAP-Style Report.