Skill Tracer
Skills › Scientific Agent Skills › shap › explainers.md

explainers.md

413 lines · skills/shap/references/explainers.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# SHAP Explainers
2
3This reference targets SHAP 0.52.0. Prefer the callable interface (`explanation = explainer(X)`) so results retain values, baselines, data, feature names, and output names in a `shap.Explanation`.
4

SHAP Explainers

This reference targets SHAP 0.52.0. Prefer the callable interface (explanation = explainer(X)) so results retain values, baselines, data, feature names, and output names in a shap.Explanation.

Raw lines 1 to 4
5## Selection Checklist
6
7Before choosing an explainer, answer:
8
91. What exact callable or model output is being explained?
102. Is the model natively supported by a specialized explainer?
113. What does "missing" mean for each input feature?
124. Are features independent, correlated, grouped, sequential, or spatial?
135. How many model evaluations are affordable per row?
146. Is the output scalar or multi-output?
157. Is an exact result required under the chosen game, or is a sampled estimate acceptable?

Selection Checklist

Before choosing an explainer, answer:

  1. What exact callable or model output is being explained?
  2. Is the model natively supported by a specialized explainer?
  3. What does "missing" mean for each input feature?
  4. Are features independent, correlated, grouped, sequential, or spatial?
  5. How many model evaluations are affordable per row?
  6. Is the output scalar or multi-output?
  7. Is an exact result required under the chosen game, or is a sampled estimate acceptable?
Raw lines 5 to 16
17## Recommended Decision Path
19| Model/input | First choice | Alternative | Main risk |
20|---|---|---|---|
21| Supported tree ensemble | `TreeExplainer` | `GPUTreeExplainer` (experimental) | Output units and feature-dependence semantics |
22| Linear model | `LinearExplainer` | `ExactExplainer` | Correlation assumptions |
23| Small tabular feature set | `ExactExplainer` | `PermutationExplainer` | Exponential cost without a partition tree |
24| General tabular callable | `PermutationExplainer` | `PartitionExplainer`, `KernelExplainer` | Evaluation cost and off-manifold masks |
25| Hierarchically grouped inputs | `PartitionExplainer` | `PermutationExplainer` with `Partition` masker | Attributions are Owen values for the constrained game |
26| Differentiable TensorFlow/PyTorch model | `DeepExplainer` or `GradientExplainer` | `PartitionExplainer` | Operator support, background, and output shape |
27| Text or image callable | `PartitionExplainer` with domain masker | Framework-specific deep explainer | Masking semantics dominate interpretation |

Recommended Decision Path

Model/inputFirst choiceAlternativeMain risk
Supported tree ensembleTreeExplainerGPUTreeExplainer (experimental)Output units and feature-dependence semantics
Linear modelLinearExplainerExactExplainerCorrelation assumptions
Small tabular feature setExactExplainerPermutationExplainerExponential cost without a partition tree
General tabular callablePermutationExplainerPartitionExplainer, KernelExplainerEvaluation cost and off-manifold masks
Hierarchically grouped inputsPartitionExplainerPermutationExplainer with Partition maskerAttributions are Owen values for the constrained game
Differentiable TensorFlow/PyTorch modelDeepExplainer or GradientExplainerPartitionExplainerOperator support, background, and output shape
Text or image callablePartitionExplainer with domain maskerFramework-specific deep explainerMasking semantics dominate interpretation
Raw lines 17 to 28
29## `shap.Explainer`
31`shap.Explainer` combines a model, masker, link, and algorithm. With `algorithm="auto"`, it returns a compatible specialized subclass.
33```python
34explainer = shap.Explainer(
35 model,
36 masker=background,
37 algorithm="auto",
38 output_names=output_names,
39 feature_names=feature_names,
40 seed=7,
42explanation = explainer(X_eval)
43```
45The 0.52.0 selector advertises `auto`, `permutation`, `partition`, `tree`, `linear`, `deep`, `exact`, and `additive`. However, its `algorithm="deep"` dispatch forwards unsupported keywords to `DeepExplainer` and raises `TypeError`; construct `shap.DeepExplainer(model, background)` directly. `auto` is not a general framework detector.
47Use the auto-selector when:
49- the model/masker pair is conventional;
50- default output semantics are acceptable;
51- no algorithm-specific parameter is needed.
53Instantiate the specialized class when:
55- tree `model_output` or `feature_perturbation` must be explicit;
56- a particular approximation or evaluation budget is part of the analysis;
57- a framework-specific deep model requires a precise input/layer form.
59Passing a background matrix is shorthand for a standard tabular masker. Prefer an explicit masker when its semantics need to appear in an audit record.

shap.Explainer

shap.Explainer combines a model, masker, link, and algorithm. With algorithm="auto", it returns a compatible specialized subclass.

explainer = shap.Explainer(
    model,
    masker=background,
    algorithm="auto",
    output_names=output_names,
    feature_names=feature_names,
    seed=7,
)
explanation = explainer(X_eval)

The 0.52.0 selector advertises auto, permutation, partition, tree, linear, deep, exact, and additive. However, its algorithm="deep" dispatch forwards unsupported keywords to DeepExplainer and raises TypeError; construct shap.DeepExplainer(model, background) directly. auto is not a general framework detector.

Use the auto-selector when:

  • the model/masker pair is conventional;
  • default output semantics are acceptable;
  • no algorithm-specific parameter is needed.

Instantiate the specialized class when:

  • tree model_output or feature_perturbation must be explicit;
  • a particular approximation or evaluation budget is part of the analysis;
  • a framework-specific deep model requires a precise input/layer form.

Passing a background matrix is shorthand for a standard tabular masker. Prefer an explicit masker when its semantics need to appear in an audit record.

Raw lines 29 to 60
Starts an agent dispatch :45
61## `TreeExplainer`
63Common constructor arguments (the deprecated `approximate` parameter and unused link controls are intentionally omitted):
65```python
66shap.TreeExplainer(
67 model,
68 data=None,
69 model_output="raw",
70 feature_perturbation="auto",
71 feature_names=None,
73```
75Supported families include XGBoost, LightGBM, CatBoost, PySpark trees, and most scikit-learn tree models. Support varies by model version and categorical configuration, so test a small batch after dependency changes.

TreeExplainer

Common constructor arguments (the deprecated approximate parameter and unused link controls are intentionally omitted):

shap.TreeExplainer(
    model,
    data=None,
    model_output="raw",
    feature_perturbation="auto",
    feature_names=None,
)

Supported families include XGBoost, LightGBM, CatBoost, PySpark trees, and most scikit-learn tree models. Support varies by model version and categorical configuration, so test a small batch after dependency changes.

Raw lines 61 to 76
77### Feature perturbation
79`feature_perturbation` defines how hidden features are integrated:
81- `"interventional"` requires background data. Runtime scales approximately linearly with background size.
82- `"tree_path_dependent"` uses training counts stored in tree leaves and does not require a separate background.
83- `"auto"` uses interventional semantics when `data` is supplied and tree-path-dependent semantics otherwise. This has been the default since 0.47.
85These options answer different questions and can allocate credit differently for dependent features. Neither turns an ordinary predictive model into a causal model.

Feature perturbation

feature_perturbation defines how hidden features are integrated:

  • "interventional" requires background data. Runtime scales approximately linearly with background size.
  • "tree_path_dependent" uses training counts stored in tree leaves and does not require a separate background.
  • "auto" uses interventional semantics when data is supplied and tree-path-dependent semantics otherwise. This has been the default since 0.47.

These options answer different questions and can allocate credit differently for dependent features. Neither turns an ordinary predictive model into a causal model.

Raw lines 77 to 86
87### Output space
89`model_output` can be:
91- `"raw"`: model-specific raw tree output;
92- `"probability"`: transformed probability output;
93- `"log_loss"`: a model-specific loss transform; for supported binary margin models this is negative log likelihood, while squared-error objectives use squared loss;
94- a supported model method name such as `"predict_proba"`.
96`"probability"` and `"log_loss"` currently require `feature_perturbation="interventional"` and background data.
98Raw output is model-dependent:
100- regression commonly uses the predicted target value;
101- XGBoost binary classification commonly uses a margin/log-odds value;
102- scikit-learn tree classifiers commonly expose one probability output per class.
104Always inspect shape and verify the additive reconstruction against the exact model output.

Output space

model_output can be:

  • "raw": model-specific raw tree output;
  • "probability": transformed probability output;
  • "log_loss": a model-specific loss transform; for supported binary margin models this is negative log likelihood, while squared-error objectives use squared loss;
  • a supported model method name such as "predict_proba".

"probability" and "log_loss" currently require feature_perturbation="interventional" and background data.

Raw output is model-dependent:

  • regression commonly uses the predicted target value;
  • XGBoost binary classification commonly uses a margin/log-odds value;
  • scikit-learn tree classifiers commonly expose one probability output per class.

Always inspect shape and verify the additive reconstruction against the exact model output.

Raw lines 87 to 105
106### Calling and validation
108```python
109explainer = shap.TreeExplainer(
110 model,
111 data=background,
112 feature_perturbation="interventional",
113 model_output="probability",
115all_outputs = explainer(X_eval)
116class_exp = all_outputs[..., class_index]
118reconstructed = class_exp.base_values + class_exp.values.sum(axis=1)
119expected = model.predict_proba(X_eval)[:, class_index]
120np.testing.assert_allclose(reconstructed, expected, rtol=1e-5, atol=1e-6)
121```
123The built-in tree additivity check applies to raw output paths; explicitly validate probability and loss reconstructions. Loss baselines can be label-dependent callables: see the concrete loss workflow in [workflows.md](workflows.md). A bare DataFrame background is capped at 100 rows; retain a larger selected sample with `data=shap.maskers.Independent(background, max_samples=len(background))` and record the effective size.

Calling and validation

explainer = shap.TreeExplainer(
    model,
    data=background,
    feature_perturbation="interventional",
    model_output="probability",
)
all_outputs = explainer(X_eval)
class_exp = all_outputs[..., class_index]

reconstructed = class_exp.base_values + class_exp.values.sum(axis=1)
expected = model.predict_proba(X_eval)[:, class_index]
np.testing.assert_allclose(reconstructed, expected, rtol=1e-5, atol=1e-6)

The built-in tree additivity check applies to raw output paths; explicitly validate probability and loss reconstructions. Loss baselines can be label-dependent callables: see the concrete loss workflow in workflows.md. A bare DataFrame background is capped at 100 rows; retain a larger selected sample with data=shap.maskers.Independent(background, max_samples=len(background)) and record the effective size.

Raw lines 106 to 124
125### Approximate tree values
127Do not pass `approximate` to the constructor. If the speed/quality trade-off is intentional:
129```python
130approx_exp = explainer(X_eval, approximate=True)
131```
133This uses a single-ordering approximation associated with Saabas values. It does not retain the consistency guarantee of Tree SHAP and can over-weight lower tree splits. Label the result as approximate.

Approximate tree values

Do not pass approximate to the constructor. If the speed/quality trade-off is intentional:

approx_exp = explainer(X_eval, approximate=True)

This uses a single-ordering approximation associated with Saabas values. It does not retain the consistency guarantee of Tree SHAP and can over-weight lower tree splits. Label the result as approximate.

Raw lines 125 to 134
135### Interaction values
137Use a separate **raw, tree-path-dependent** explainer for supported tree interactions:
139```python
140interaction_explainer = shap.TreeExplainer(
141 model, feature_perturbation="tree_path_dependent", model_output="raw",
143interaction = interaction_explainer.shap_interaction_values(X_eval)
144ordinary = interaction_explainer(X_eval)
145np.testing.assert_allclose(interaction.sum(axis=2), ordinary.values, atol=1e-6)
146```
148Probability/log-loss explainers reject interaction calls. The interventional C++ path does not implement interactions and can emit zeros with a warning; never interpret those as absent interactions. Compare against ordinary values from this same path-dependent game, not an earlier interventional explanation. Each symmetric off-diagonal cell carries half the pair contribution.
150Shapes:
152- one output: `(samples, features, features)`;
153- multiple outputs: `(samples, features, features, outputs)`.
155Since 0.45, multiple outputs use a NumPy array rather than a list. Interaction computation can be much larger than ordinary explanations; subset rows and features deliberately.

Interaction values

Use a separate raw, tree-path-dependent explainer for supported tree interactions:

interaction_explainer = shap.TreeExplainer(
    model, feature_perturbation="tree_path_dependent", model_output="raw",
)
interaction = interaction_explainer.shap_interaction_values(X_eval)
ordinary = interaction_explainer(X_eval)
np.testing.assert_allclose(interaction.sum(axis=2), ordinary.values, atol=1e-6)

Probability/log-loss explainers reject interaction calls. The interventional C++ path does not implement interactions and can emit zeros with a warning; never interpret those as absent interactions. Compare against ordinary values from this same path-dependent game, not an earlier interventional explanation. Each symmetric off-diagonal cell carries half the pair contribution.

Shapes:

  • one output: (samples, features, features);
  • multiple outputs: (samples, features, features, outputs).

Since 0.45, multiple outputs use a NumPy array rather than a list. Interaction computation can be much larger than ordinary explanations; subset rows and features deliberately.

Raw lines 135 to 156
157### GPU tree explainer
159`GPUTreeExplainer` is experimental and requires a source build with CUDA support. Validate parity against CPU `TreeExplainer`, especially for missing values, multiclass baselines, and categorical splits.

GPU tree explainer

GPUTreeExplainer is experimental and requires a source build with CUDA support. Validate parity against CPU TreeExplainer, especially for missing values, multiclass baselines, and categorical splits.

Raw lines 157 to 160
161## `LinearExplainer`
163Use for linear or logistic models:
165```python
166masker = shap.maskers.Independent(background)
167explainer = shap.LinearExplainer(model, masker)
168explanation = explainer(X_eval)
169```
171With independent/interventional masking, a linear attribution is related to:
173```text
174coefficient_i * (x_i - reference_mean_i)
175```
177For correlation-aware allocation, use an `Impute` masker:
179```python
180masker = shap.maskers.Impute(background, method="linear")
181explainer = shap.LinearExplainer(model, masker)
182```
184For logistic regression, these linear attributions reconstruct `model.decision_function(X_eval)` in log-odds units, not `predict_proba` or predicted class labels. Explain a probability callable with a model-agnostic method when probability-space attribution is required.
186Correlation-aware values share credit among correlated inputs and can assign attribution to a feature that the fitted model does not directly use. This is a property of the conditional game, not evidence of a direct model coefficient or causal effect. SHAP 0.52 warns when the estimated covariance matrix is singular.

LinearExplainer

Use for linear or logistic models:

masker = shap.maskers.Independent(background)
explainer = shap.LinearExplainer(model, masker)
explanation = explainer(X_eval)

With independent/interventional masking, a linear attribution is related to:

coefficient_i * (x_i - reference_mean_i)

For correlation-aware allocation, use an Impute masker:

masker = shap.maskers.Impute(background, method="linear")
explainer = shap.LinearExplainer(model, masker)

For logistic regression, these linear attributions reconstruct model.decision_function(X_eval) in log-odds units, not predict_proba or predicted class labels. Explain a probability callable with a model-agnostic method when probability-space attribution is required.

Correlation-aware values share credit among correlated inputs and can assign attribution to a feature that the fitted model does not directly use. This is a property of the conditional game, not evidence of a direct model coefficient or causal effect. SHAP 0.52 warns when the estimated covariance matrix is singular.

Raw lines 161 to 187
188## `ExactExplainer`
190`ExactExplainer` enumerates coalitions with optimizations:
192```python
193masker = shap.maskers.Independent(background)
194explainer = shap.ExactExplainer(model_fn, masker)
195explanation = explainer(X_eval)
196```
198Use it for:
200- small feature spaces;
201- correctness checks against an approximate explainer;
202- partition games where the hierarchy sharply reduces evaluation cost.
204Avoid it for unconstrained high-dimensional inputs.

ExactExplainer

ExactExplainer enumerates coalitions with optimizations:

masker = shap.maskers.Independent(background)
explainer = shap.ExactExplainer(model_fn, masker)
explanation = explainer(X_eval)

Use it for:

  • small feature spaces;
  • correctness checks against an approximate explainer;
  • partition games where the hierarchy sharply reduces evaluation cost.

Avoid it for unconstrained high-dimensional inputs.

Raw lines 188 to 205
206## `PermutationExplainer`
208`PermutationExplainer` is the general modern model-agnostic default:
210```python
211masker = shap.maskers.Independent(background, max_samples=100)
212explainer = shap.PermutationExplainer(
213 model_fn,
214 masker,
215 feature_names=feature_names,
216 seed=7,
219minimum_budget = 2 * len(feature_names) + 1
220explanation = explainer(
221 X_eval,
222 max_evals=minimum_budget * 10,
223 error_bounds=True,
225```
227One forward/reverse pass guarantees additivity and is exact for models with interactions no higher than second order. Repeating random permutations improves estimates for higher-order interactions.
229Cost scales with:
231- evaluation rows;
232- feature count;
233- number of permutations;
234- background rows;
235- model latency.
237Batch the model callable where possible. Preserve the seed and budget. `error_bounds=True` estimates variation across sampled paths; it is not a confidence interval for model correctness or biological effects.

PermutationExplainer

PermutationExplainer is the general modern model-agnostic default:

masker = shap.maskers.Independent(background, max_samples=100)
explainer = shap.PermutationExplainer(
    model_fn,
    masker,
    feature_names=feature_names,
    seed=7,
)

minimum_budget = 2 * len(feature_names) + 1
explanation = explainer(
    X_eval,
    max_evals=minimum_budget * 10,
    error_bounds=True,
)

One forward/reverse pass guarantees additivity and is exact for models with interactions no higher than second order. Repeating random permutations improves estimates for higher-order interactions.

Cost scales with:

  • evaluation rows;
  • feature count;
  • number of permutations;
  • background rows;
  • model latency.

Batch the model callable where possible. Preserve the seed and budget. error_bounds=True estimates variation across sampled paths; it is not a confidence interval for model correctness or biological effects.

Raw lines 206 to 238
239## Links and output units
241For a probability callable, a supported model-agnostic link changes the additive units:
243```python
244explainer = shap.Explainer(
245 probability_fn, background, algorithm="permutation",
246 link=shap.links.logit, seed=7,
248exp = explainer(X_eval, max_evals=(2 * X_eval.shape[1] + 1) * 5)
249np.testing.assert_allclose(
250 exp.base_values + exp.values.sum(axis=1),
251 shap.links.logit(probability_fn(X_eval)), atol=1e-6,
253```
255This fragment assumes a scalar probability strictly between 0 and 1. Check finiteness on masked inputs too; exact endpoints make log-odds infinite. With default link linearization, the baseline is `logit(mean(background probabilities))`, not the mean background logit. Record `linearize_link`; applying a link inside the model callable defines a different game. This is distinct from the force plot's display-only link. `TreeExplainer`'s link constructor arguments are unused in 0.52.0; configure its supported `model_output` instead.

Links and output units

For a probability callable, a supported model-agnostic link changes the additive units:

explainer = shap.Explainer(
    probability_fn, background, algorithm="permutation",
    link=shap.links.logit, seed=7,
)
exp = explainer(X_eval, max_evals=(2 * X_eval.shape[1] + 1) * 5)
np.testing.assert_allclose(
    exp.base_values + exp.values.sum(axis=1),
    shap.links.logit(probability_fn(X_eval)), atol=1e-6,
)

This fragment assumes a scalar probability strictly between 0 and 1. Check finiteness on masked inputs too; exact endpoints make log-odds infinite. With default link linearization, the baseline is logit(mean(background probabilities)), not the mean background logit. Record linearize_link; applying a link inside the model callable defines a different game. This is distinct from the force plot's display-only link. TreeExplainer's link constructor arguments are unused in 0.52.0; configure its supported model_output instead.

Raw lines 239 to 256
257## `PartitionExplainer`
259`PartitionExplainer` follows a hierarchical clustering of input features:
261```python
262masker = shap.maskers.Partition(
263 background,
264 max_samples=100,
265 clustering="correlation",
267explainer = shap.PartitionExplainer(
268 model_fn,
269 masker,
270 output_names=output_names,
272explanation = explainer(X_eval, max_evals=1000)
273```
275With a partition tree, the values are Owen values for a constrained cooperative game. This is useful when:
277- groups should enter a coalition together;
278- correlated tabular inputs should be organized hierarchically;
279- tokens or image regions have natural structure;
280- unconstrained exact enumeration is too expensive.
282Do not call partition values equivalent to unconstrained Shapley values without noting the changed game.

PartitionExplainer

PartitionExplainer follows a hierarchical clustering of input features:

masker = shap.maskers.Partition(
    background,
    max_samples=100,
    clustering="correlation",
)
explainer = shap.PartitionExplainer(
    model_fn,
    masker,
    output_names=output_names,
)
explanation = explainer(X_eval, max_evals=1000)

With a partition tree, the values are Owen values for a constrained cooperative game. This is useful when:

  • groups should enter a coalition together;
  • correlated tabular inputs should be organized hierarchically;
  • tokens or image regions have natural structure;
  • unconstrained exact enumeration is too expensive.

Do not call partition values equivalent to unconstrained Shapley values without noting the changed game.

Raw lines 257 to 283
284## `KernelExplainer`
286Kernel SHAP fits a weighted linear surrogate over sampled coalitions:
288```python
289explainer = shap.KernelExplainer(
290 model_fn,
291 background,
292 link="identity",
293 feature_names=feature_names,
295legacy_values = explainer.shap_values(
296 X_eval, nsamples="auto", l1_reg="num_features(10)",
298```
300Use it when:
302- maintaining a validated Kernel SHAP analysis;
303- a specific identity/logit link behavior is required;
304- another explainer cannot represent the model/masker combination.
306`KernelExplainer(X)` also returns an `Explanation`, but its 0.52.0 call signature only exposes `l1_reg` and `silent`; use `.shap_values(..., nsamples=...)` for an explicit sampling budget. The default `l1_reg="num_features(10)"` selects at most ten features (changed in 0.47), so omitted features are not evidence of zero model use. Choose and record regularization; `l1_reg=0` removes this selection when the sampled system is sufficiently determined.
308For new general tabular work, consider `PermutationExplainer` for its direct evaluation-budget control.
310Kernel SHAP can be slow and may create unrealistic masked samples. Summarizing background data changes the estimand as well as runtime.

KernelExplainer

Kernel SHAP fits a weighted linear surrogate over sampled coalitions:

explainer = shap.KernelExplainer(
    model_fn,
    background,
    link="identity",
    feature_names=feature_names,
)
legacy_values = explainer.shap_values(
    X_eval, nsamples="auto", l1_reg="num_features(10)",
)

Use it when:

  • maintaining a validated Kernel SHAP analysis;
  • a specific identity/logit link behavior is required;
  • another explainer cannot represent the model/masker combination.

KernelExplainer(X) also returns an Explanation, but its 0.52.0 call signature only exposes l1_reg and silent; use .shap_values(..., nsamples=...) for an explicit sampling budget. The default l1_reg="num_features(10)" selects at most ten features (changed in 0.47), so omitted features are not evidence of zero model use. Choose and record regularization; l1_reg=0 removes this selection when the sampled system is sufficiently determined.

For new general tabular work, consider PermutationExplainer for its direct evaluation-budget control.

Kernel SHAP can be slow and may create unrealistic masked samples. Summarizing background data changes the estimand as well as runtime.

Raw lines 284 to 311
312## `DeepExplainer`
314Deep SHAP approximates attributions for supported differentiable TensorFlow and PyTorch models.
316Before constructing a PyTorch explainer, switch the `nn.Module` to evaluation mode using its standard `eval` method. This is a PyTorch state change, not Python's built-in code-evaluation function.
318PyTorch:
320```python
321explainer = shap.DeepExplainer(model, background_tensor)
322values = explainer.shap_values(test_tensor)
323```
325TensorFlow/Keras:
327```python
328explainer = shap.DeepExplainer(model, background_array)
329values = explainer.shap_values(test_array)
330```
332Model forms:
334- TensorFlow: a model, or an `(inputs, output)` tensor pair with a single-dimensional output;
335- PyTorch: an `nn.Module`, or `(model, layer)` to attribute the selected layer's input.
337Background cost is linear in sample count. Official guidance describes roughly 100 samples as a useful estimate and 1000 as a more accurate but costlier estimate; test convergence for the actual model.
339Output shapes since 0.45:
341- one input, one output: inspect for `(samples, *input_shape)` **or a final singleton output axis**; the 0.52.0 PyTorch Deep implementation stacks even a single output;
342- one input, multiple outputs: `(samples, *input_shape, outputs)`;
343- multiple inputs: a list, one array per input.
345Pass `ranked_outputs=k` to `.shap_values(...)`, not the constructor. It returns both values and selected output indexes. Never assume a binary model returns a two-element list.
347For PyTorch, return `(batch, outputs)`, including `(batch, 1)` for a scalar-output wrapper; a squeezed `(batch,)` result fails the Deep backend's output-axis handling. Deep explainers support only known operators and architecture patterns. Additivity failures can indicate unsupported operations rather than a tolerance problem.

DeepExplainer

Deep SHAP approximates attributions for supported differentiable TensorFlow and PyTorch models.

Before constructing a PyTorch explainer, switch the nn.Module to evaluation mode using its standard eval method. This is a PyTorch state change, not Python's built-in code-evaluation function.

PyTorch:

explainer = shap.DeepExplainer(model, background_tensor)
values = explainer.shap_values(test_tensor)

TensorFlow/Keras:

explainer = shap.DeepExplainer(model, background_array)
values = explainer.shap_values(test_array)

Model forms:

  • TensorFlow: a model, or an (inputs, output) tensor pair with a single-dimensional output;
  • PyTorch: an nn.Module, or (model, layer) to attribute the selected layer's input.

Background cost is linear in sample count. Official guidance describes roughly 100 samples as a useful estimate and 1000 as a more accurate but costlier estimate; test convergence for the actual model.

Output shapes since 0.45:

  • one input, one output: inspect for (samples, *input_shape) or a final singleton output axis; the 0.52.0 PyTorch Deep implementation stacks even a single output;
  • one input, multiple outputs: (samples, *input_shape, outputs);
  • multiple inputs: a list, one array per input.

Pass ranked_outputs=k to .shap_values(...), not the constructor. It returns both values and selected output indexes. Never assume a binary model returns a two-element list.

For PyTorch, return (batch, outputs), including (batch, 1) for a scalar-output wrapper; a squeezed (batch,) result fails the Deep backend's output-axis handling. Deep explainers support only known operators and architecture patterns. Additivity failures can indicate unsupported operations rather than a tolerance problem.

Raw lines 312 to 348
349## `GradientExplainer`
351`GradientExplainer` implements expected gradients, an extension of integrated gradients:
353```python
354explainer = shap.GradientExplainer(
355 model,
356 background_tensor,
357 batch_size=50,
358 local_smoothing=0,
360values = explainer.shap_values(test_tensor, nsamples=200, rseed=7)
361```
363Use it when:
365- the model is differentiable;
366- DeepExplainer lacks an operator rule;
367- expected-gradients semantics are appropriate.
369It remains an approximation. Report `nsamples`, seed, background, and any smoothing.

GradientExplainer

GradientExplainer implements expected gradients, an extension of integrated gradients:

explainer = shap.GradientExplainer(
    model,
    background_tensor,
    batch_size=50,
    local_smoothing=0,
)
values = explainer.shap_values(test_tensor, nsamples=200, rseed=7)

Use it when:

  • the model is differentiable;
  • DeepExplainer lacks an operator rule;
  • expected-gradients semantics are appropriate.

It remains an approximation. Report nsamples, seed, background, and any smoothing.

Raw lines 349 to 370
371## Other Public Explainers
373- `AdditiveExplainer`: first-order additive models with an `Independent` masker; do not use for models containing interaction terms.
374- `SamplingExplainer`: Shapley sampling/IME-style approximation; mainly relevant to existing workflows.
375- `CoalitionExplainer`: custom coalition-tree workflows using Winter (recursive Owen) values; its `partition_tree` contract is separate from `PartitionExplainer`, and text/image inputs are not implemented. Treat a new application as illustrative until checked against 0.52.0 source and a tiny known game.
376- `shap.explainers.other.*`: wrappers and diagnostic baselines, not the default for a SHAP audit.

Other Public Explainers

  • AdditiveExplainer: first-order additive models with an Independent masker; do not use for models containing interaction terms.
  • SamplingExplainer: Shapley sampling/IME-style approximation; mainly relevant to existing workflows.
  • CoalitionExplainer: custom coalition-tree workflows using Winter (recursive Owen) values; its partition_tree contract is separate from PartitionExplainer, and text/image inputs are not implemented. Treat a new application as illustrative until checked against 0.52.0 source and a tiny known game.
  • shap.explainers.other.*: wrappers and diagnostic baselines, not the default for a SHAP audit.
Raw lines 371 to 377
378## Multi-Output Handling
380Modern tabular explanations normally put outputs on the final axis:
382```python
383print(explanation.values.shape)
384print(explanation.output_names)
386one_output = explanation[..., output_index]
387# If output_names were supplied:
388one_output = explanation[..., list(explanation.output_names).index("output_name")]
389```
391In 0.52.0, `Explainer(..., algorithm="permutation", output_names=...)` may discard those names during subclass dispatch. Set `explanation.output_names` from the verified model mapping after checking output count. Avoid ellipsis plus a string index, which can raise `IndexError`; resolve the name to an integer as above.
393For ranked deep outputs, use the returned indexes; they can differ by sample.
395Do not:
397- use `explanation[output_index]` to select a class (that selects a row);
398- average signed values across outputs;
399- compare output magnitudes in different units;
400- pass a 3-D multi-output tabular explanation directly to a plot requiring `(samples, features)`.

Multi-Output Handling

Modern tabular explanations normally put outputs on the final axis:

print(explanation.values.shape)
print(explanation.output_names)

one_output = explanation[..., output_index]
# If output_names were supplied:
one_output = explanation[..., list(explanation.output_names).index("output_name")]

In 0.52.0, Explainer(..., algorithm="permutation", output_names=...) may discard those names during subclass dispatch. Set explanation.output_names from the verified model mapping after checking output count. Avoid ellipsis plus a string index, which can raise IndexError; resolve the name to an integer as above.

For ranked deep outputs, use the returned indexes; they can differ by sample.

Do not:

  • use explanation[output_index] to select a class (that selects a row);
  • average signed values across outputs;
  • compare output magnitudes in different units;
  • pass a 3-D multi-output tabular explanation directly to a plot requiring (samples, features).
Raw lines 378 to 401
Starts an agent dispatch :391
402## Sources
404- Explainer API: https://shap.readthedocs.io/en/latest/generated/shap.Explainer.html
405- TreeExplainer: https://shap.readthedocs.io/en/latest/generated/shap.TreeExplainer.html
406- PermutationExplainer: https://shap.readthedocs.io/en/latest/generated/shap.PermutationExplainer.html
407- PartitionExplainer: https://shap.readthedocs.io/en/latest/generated/shap.PartitionExplainer.html
408- DeepExplainer: https://shap.readthedocs.io/en/latest/generated/shap.DeepExplainer.html
409- API reference: https://shap.readthedocs.io/en/latest/api.html
411- Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/explainers/_explainer.py
412- Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/explainers/_kernel.py
413- Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/explainers/_tree.py

Sources

  • Explainer API: https://shap.readthedocs.io/en/latest/generated/shap.Explainer.html
  • TreeExplainer: https://shap.readthedocs.io/en/latest/generated/shap.TreeExplainer.html
  • PermutationExplainer: https://shap.readthedocs.io/en/latest/generated/shap.PermutationExplainer.html
  • PartitionExplainer: https://shap.readthedocs.io/en/latest/generated/shap.PartitionExplainer.html
  • DeepExplainer: https://shap.readthedocs.io/en/latest/generated/shap.DeepExplainer.html
  • API reference: https://shap.readthedocs.io/en/latest/api.html
  • Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/explainers/_explainer.py
  • Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/explainers/_kernel.py
  • Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/explainers/_tree.py
Raw lines 402 to 413