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

modalities.md

365 lines · skills/shap/references/modalities.md at 5f2bc03

Open on GitHub
1# Text, Images, and Deep Models
2
3Framework/model integration fragments below are illustrative: they were checked against SHAP 0.52.0 source but not run with pretrained weights or a TensorFlow/PyTorch/Transformers installation during this review. Tiny local text and constant-image masking games are tested separately.
4
5Structured inputs require structured maskers. Token deletion, image inpainting, and neural-network reference activations define different explanation games; do not reduce them to ordinary independent tabular columns without justification.
6

Text, Images, and Deep Models

Framework/model integration fragments below are illustrative: they were checked against SHAP 0.52.0 source but not run with pretrained weights or a TensorFlow/PyTorch/Transformers installation during this review. Tiny local text and constant-image masking games are tested separately.

Structured inputs require structured maskers. Token deletion, image inpainting, and neural-network reference activations define different explanation games; do not reduce them to ordinary independent tabular columns without justification.

Raw lines 1 to 6
7## General Pattern
8
91. Define a batched model callable with named outputs.
102. Choose a masker that produces valid model inputs.
113. Restrict outputs and evaluation rows before expensive computation.
124. Inspect result shapes.
135. Validate output reconstruction when the explainer supports it.
146. Run masking and baseline sensitivity checks.
16The `max_evals`/`outputs` pattern below applies to supported permutation/partition paths; it is not a universal call signature for tree, linear, or deep explainers.
18```python
19explainer = shap.Explainer(
20 model_fn,
21 masker,
22 output_names=output_names,
23 seed=7,
25explanation = explainer(
26 inputs,
27 max_evals=evaluation_budget,
28 outputs=selected_outputs,
30```

General Pattern

  1. Define a batched model callable with named outputs.
  2. Choose a masker that produces valid model inputs.
  3. Restrict outputs and evaluation rows before expensive computation.
  4. Inspect result shapes.
  5. Validate output reconstruction when the explainer supports it.
  6. Run masking and baseline sensitivity checks.

The max_evals/outputs pattern below applies to supported permutation/partition paths; it is not a universal call signature for tree, linear, or deep explainers.

explainer = shap.Explainer(
    model_fn,
    masker,
    output_names=output_names,
    seed=7,
)
explanation = explainer(
    inputs,
    max_evals=evaluation_budget,
    outputs=selected_outputs,
)
Raw lines 7 to 31
32## Text Classification
34Use the model's tokenizer:
36```python
37masker = shap.maskers.Text(tokenizer)
38explainer = shap.Explainer(
39 model_fn,
40 masker,
41 algorithm="partition",
42 output_names=class_names,
43 seed=7,
46all_outputs = explainer(texts)
47class_exp = all_outputs[..., class_index]
48shap.plots.text(class_exp)
49```
51The model callable should accept a batch of strings and return a 2-D numeric array `(batch, outputs)`.
53```python
54def model_fn(text_batch):
55 encoded = tokenizer(
56 list(text_batch),
57 padding=True,
58 truncation=True,
59 return_tensors="pt",
60 ).to(device)
62 with torch.inference_mode():
63 logits = model(**encoded).logits
65 return logits.detach().cpu().numpy()
66```
68Decide whether to explain:
70- raw class logits (multiclass softmax logits are not per-class log-odds);
71- explicit binary or one-versus-rest log-odds, when that is the intended output;
72- probabilities, which stakeholders may understand but couple classes through normalization;
73- another scalar score.
75State the choice in every plot.

Text Classification

Use the model's tokenizer:

masker = shap.maskers.Text(tokenizer)
explainer = shap.Explainer(
    model_fn,
    masker,
    algorithm="partition",
    output_names=class_names,
    seed=7,
)

all_outputs = explainer(texts)
class_exp = all_outputs[..., class_index]
shap.plots.text(class_exp)

The model callable should accept a batch of strings and return a 2-D numeric array (batch, outputs).

def model_fn(text_batch):
    encoded = tokenizer(
        list(text_batch),
        padding=True,
        truncation=True,
        return_tensors="pt",
    ).to(device)

    with torch.inference_mode():
        logits = model(**encoded).logits

    return logits.detach().cpu().numpy()

Decide whether to explain:

  • raw class logits (multiclass softmax logits are not per-class log-odds);
  • explicit binary or one-versus-rest log-odds, when that is the intended output;
  • probabilities, which stakeholders may understand but couple classes through normalization;
  • another scalar score.

State the choice in every plot.

Raw lines 32 to 76
77### Transformers pipelines
79SHAP provides `shap.models.TransformersPipeline`. Configure the existing text-classification pipeline with `top_k=None` so every class score is returned; a top-one pipeline leaves other columns at zero in this wrapper. Validate the complete label mapping and finite output values on a tiny batch before explaining:
81```python
82wrapped = shap.models.TransformersPipeline(
83 classifier_pipeline,
84 rescale_to_logits=True,
86masker = shap.maskers.Text(classifier_pipeline.tokenizer)
87explainer = shap.Explainer(wrapped, masker, algorithm="partition")
88explanation = explainer(texts)
89```
91`rescale_to_logits=True` applies `log(p / (1-p))` independently to each returned class probability. These are one-versus-rest log-odds, not recovered multiclass model logits; scores at 0 or 1 produce infinities. Prefer an explicit model callable when original logits are required. Do not compare these values directly with probability-space explanations.
93SHAP 0.52.0's upstream test extras pin `transformers<4.54.0`; this is a compatibility warning, not proof of current Transformers 5 support. Test a separately locked integration rather than promising compatibility from the wrapper's existence. Generation wrappers below have the same framework-validation requirement.

Transformers pipelines

SHAP provides shap.models.TransformersPipeline. Configure the existing text-classification pipeline with top_k=None so every class score is returned; a top-one pipeline leaves other columns at zero in this wrapper. Validate the complete label mapping and finite output values on a tiny batch before explaining:

wrapped = shap.models.TransformersPipeline(
    classifier_pipeline,
    rescale_to_logits=True,
)
masker = shap.maskers.Text(classifier_pipeline.tokenizer)
explainer = shap.Explainer(wrapped, masker, algorithm="partition")
explanation = explainer(texts)

rescale_to_logits=True applies log(p / (1-p)) independently to each returned class probability. These are one-versus-rest log-odds, not recovered multiclass model logits; scores at 0 or 1 produce infinities. Prefer an explicit model callable when original logits are required. Do not compare these values directly with probability-space explanations.

SHAP 0.52.0's upstream test extras pin transformers<4.54.0; this is a compatibility warning, not proof of current Transformers 5 support. Test a separately locked integration rather than promising compatibility from the wrapper's existence. Generation wrappers below have the same framework-validation requirement.

Raw lines 77 to 94
95### Text masking choices
97Check:
99- tokenizer special tokens;
100- subword splitting;
101- mask token;
102- whether consecutive masked tokens are collapsed;
103- maximum sequence length and truncation;
104- normalization and whitespace behavior;
105- language-specific token boundaries.
107SHAP can merge tokens hierarchically for display. A displayed phrase attribution may be a grouped coalition, not the sum from an independent-token game.

Text masking choices

Check:

  • tokenizer special tokens;
  • subword splitting;
  • mask token;
  • whether consecutive masked tokens are collapsed;
  • maximum sequence length and truncation;
  • normalization and whitespace behavior;
  • language-specific token boundaries.

SHAP can merge tokens hierarchically for display. A displayed phrase attribution may be a grouped coalition, not the sum from an independent-token game.

Raw lines 95 to 108
109### Generative and sequence-to-sequence models
111SHAP includes model wrappers such as:
113- `TeacherForcing`;
114- `TextGeneration`;
115- `TopKLM`.
117Generation explanations are target- and decoding-dependent. Record:
119- generated or fixed target sequence;
120- teacher-forcing setup;
121- decoding parameters;
122- top-k output selection;
123- tokenizer/model revision.
125Do not describe one generation explanation as a general explanation of the language model.

Generative and sequence-to-sequence models

SHAP includes model wrappers such as:

  • TeacherForcing;
  • TextGeneration;
  • TopKLM.

Generation explanations are target- and decoding-dependent. Record:

  • generated or fixed target sequence;
  • teacher-forcing setup;
  • decoding parameters;
  • top-k output selection;
  • tokenizer/model revision.

Do not describe one generation explanation as a general explanation of the language model.

Raw lines 109 to 126
127## Image Classification
129`shap.maskers.Image` needs OpenCV (`cv2`) for string-based blur/inpainting, not for a numeric constant/array baseline. OpenCV is not installed by the `plots` extra. Add a compatible OpenCV build only when those methods are required. Inpainting converts pixels to `uint8`; use a suitable 0–255 image representation and put the model's normalization inside the callable. Applying it directly to normalized floats can destroy image information.
131Wrap preprocessing inside the model callable so masked images receive the same transformations:
133```python
134def image_model_fn(image_batch):
135 prepared = preprocess(image_batch.copy())
136 return model(prepared)
137```
139Choose an image masker:
141```python
142masker = shap.maskers.Image(
143 "inpaint_telea",
144 shape=image_shape,
147explainer = shap.Explainer(
148 image_model_fn,
149 masker,
150 output_names=class_names,
151 seed=7,
154explanation = explainer(
155 images,
156 max_evals=500,
157 batch_size=50,
158 outputs=shap.Explanation.argsort.flip[:3],
161shap.plots.image(explanation)
162```
164The current constructor also accepts blur specifications or constant mask values. Compare plausible alternatives:
166```python
167inpaint = shap.maskers.Image("inpaint_telea", image_shape)
168blur = shap.maskers.Image("blur(32,32)", image_shape)
169zero = shap.maskers.Image(0, image_shape)
170```
172These answer different questions:
174- inpainting replaces a region using nearby pixels;
175- blur removes high-frequency detail while retaining coarse structure;
176- a constant value creates a fixed visual baseline.
178None guarantees an in-distribution counterfactual.

Image Classification

shap.maskers.Image needs OpenCV (cv2) for string-based blur/inpainting, not for a numeric constant/array baseline. OpenCV is not installed by the plots extra. Add a compatible OpenCV build only when those methods are required. Inpainting converts pixels to uint8; use a suitable 0–255 image representation and put the model's normalization inside the callable. Applying it directly to normalized floats can destroy image information.

Wrap preprocessing inside the model callable so masked images receive the same transformations:

def image_model_fn(image_batch):
    prepared = preprocess(image_batch.copy())
    return model(prepared)

Choose an image masker:

masker = shap.maskers.Image(
    "inpaint_telea",
    shape=image_shape,
)

explainer = shap.Explainer(
    image_model_fn,
    masker,
    output_names=class_names,
    seed=7,
)

explanation = explainer(
    images,
    max_evals=500,
    batch_size=50,
    outputs=shap.Explanation.argsort.flip[:3],
)

shap.plots.image(explanation)

The current constructor also accepts blur specifications or constant mask values. Compare plausible alternatives:

inpaint = shap.maskers.Image("inpaint_telea", image_shape)
blur = shap.maskers.Image("blur(32,32)", image_shape)
zero = shap.maskers.Image(0, image_shape)

These answer different questions:

  • inpainting replaces a region using nearby pixels;
  • blur removes high-frequency detail while retaining coarse structure;
  • a constant value creates a fixed visual baseline.

None guarantees an in-distribution counterfactual.

Raw lines 127 to 179
180### Output selection
182Image classifiers may have thousands of outputs. Use:
184```python
185outputs=shap.Explanation.argsort.flip[:k]
186```
188The selected outputs can vary by row. Preserve `output_indexes`/`output_names` and never assume position zero refers to the same class for every image when ranked outputs are used.

Output selection

Image classifiers may have thousands of outputs. Use:

outputs=shap.Explanation.argsort.flip[:k]

The selected outputs can vary by row. Preserve output_indexes/output_names and never assume position zero refers to the same class for every image when ranked outputs are used.

Raw lines 180 to 189
190### Interpreting image overlays
192Attribution overlays:
194- explain a model score under a region-masking game;
195- do not identify objects with segmentation accuracy;
196- do not prove the model "looked at" a region causally;
197- can change with resize, crop, normalization, and masker.
199Test:
201- multiple maskers;
202- nearby images/augmentations;
203- different evaluation budgets;
204- class-output selection;
205- consistency with predictive errors.

Interpreting image overlays

Attribution overlays:

  • explain a model score under a region-masking game;
  • do not identify objects with segmentation accuracy;
  • do not prove the model "looked at" a region causally;
  • can change with resize, crop, normalization, and masker.

Test:

  • multiple maskers;
  • nearby images/augmentations;
  • different evaluation budgets;
  • class-output selection;
  • consistency with predictive errors.
Raw lines 190 to 206
207## PyTorch Deep Models
209Before constructing the explainer, switch the PyTorch `nn.Module` to evaluation mode with its standard `eval` method. This disables training behavior such as dropout; it is not Python's built-in code-evaluation function.
211```python
212background = training_tensor[background_indices].to(device)
213to_explain = test_tensor[:batch_size].to(device)
215explainer = shap.DeepExplainer(model, background)
216values = explainer.shap_values(to_explain, check_additivity=True)
217```
219For layer-input attribution:
221```python
222explainer = shap.DeepExplainer(
223 (model, model.feature_extractor.target_layer),
224 background,
226```
228Requirements:
230- model inputs match background tensor structure;
231- PyTorch output has shape `(batch, outputs)`, including `(batch, 1)` for one output, rather than a squeezed `(batch,)`;
232- all relevant operations have supported attribution rules;
233- dropout/batch normalization are in inference mode.
235Do not disable `check_additivity` merely to suppress unsupported-operation failures.

PyTorch Deep Models

Before constructing the explainer, switch the PyTorch nn.Module to evaluation mode with its standard eval method. This disables training behavior such as dropout; it is not Python's built-in code-evaluation function.

background = training_tensor[background_indices].to(device)
to_explain = test_tensor[:batch_size].to(device)

explainer = shap.DeepExplainer(model, background)
values = explainer.shap_values(to_explain, check_additivity=True)

For layer-input attribution:

explainer = shap.DeepExplainer(
    (model, model.feature_extractor.target_layer),
    background,
)

Requirements:

  • model inputs match background tensor structure;
  • PyTorch output has shape (batch, outputs), including (batch, 1) for one output, rather than a squeezed (batch,);
  • all relevant operations have supported attribution rules;
  • dropout/batch normalization are in inference mode.

Do not disable check_additivity merely to suppress unsupported-operation failures.

Raw lines 207 to 236
237## TensorFlow/Keras Deep Models
239```python
240background = X_train[background_indices]
241to_explain = X_test[:batch_size]
243explainer = shap.DeepExplainer(model, background)
244values = explainer.shap_values(to_explain, check_additivity=True)
245```
247SHAP 0.46 added NumPy 2, Keras 3, and TensorFlow 2.16 compatibility. Later versions may still have architecture-specific limitations. Verify installed TensorFlow/Keras versions against SHAP release notes and test a minimal batch.
249For graph-specific use, TensorFlow may accept an `(input_tensors, output_tensor)` pair. The selected output tensor should be one-dimensional per sample.

TensorFlow/Keras Deep Models

background = X_train[background_indices]
to_explain = X_test[:batch_size]

explainer = shap.DeepExplainer(model, background)
values = explainer.shap_values(to_explain, check_additivity=True)

SHAP 0.46 added NumPy 2, Keras 3, and TensorFlow 2.16 compatibility. Later versions may still have architecture-specific limitations. Verify installed TensorFlow/Keras versions against SHAP release notes and test a minimal batch.

For graph-specific use, TensorFlow may accept an (input_tensors, output_tensor) pair. The selected output tensor should be one-dimensional per sample.

Raw lines 237 to 250
251## `GradientExplainer`
253Expected gradients can be an alternative when DeepExplainer lacks an operator rule:
255```python
256explainer = shap.GradientExplainer(
257 model,
258 background,
259 batch_size=50,
260 local_smoothing=0,
262values = explainer.shap_values(
263 to_explain,
264 nsamples=200,
265 rseed=7,
267```
269Report:
271- background;
272- `nsamples`;
273- seed;
274- smoothing;
275- selected output;
276- whether values were stable at a larger sample count.

GradientExplainer

Expected gradients can be an alternative when DeepExplainer lacks an operator rule:

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

Report:

  • background;
  • nsamples;
  • seed;
  • smoothing;
  • selected output;
  • whether values were stable at a larger sample count.
Raw lines 251 to 277
278## Output Shapes
280Since SHAP 0.45:
282- one input, one output: `(samples, *input_shape)` or an additional final singleton output axis; the PyTorch Deep 0.52.0 backend stacks even one output;
283- one input, multiple outputs: `(samples, *input_shape, outputs)`;
284- multiple inputs: a list with one array per model input.
286For `deep_explainer.shap_values(X, ranked_outputs=k)`, the return is `(values, indexes)`; `ranked_outputs` is not a constructor argument. The indexes tell which outputs were selected for each row.
288Always inspect rather than branch on a remembered version:
290```python
291if isinstance(values, list):
292 print([value.shape for value in values])
293else:
294 print(values.shape)
295```

Output Shapes

Since SHAP 0.45:

  • one input, one output: (samples, *input_shape) or an additional final singleton output axis; the PyTorch Deep 0.52.0 backend stacks even one output;
  • one input, multiple outputs: (samples, *input_shape, outputs);
  • multiple inputs: a list with one array per model input.

For deep_explainer.shap_values(X, ranked_outputs=k), the return is (values, indexes); ranked_outputs is not a constructor argument. The indexes tell which outputs were selected for each row.

Always inspect rather than branch on a remembered version:

if isinstance(values, list):
    print([value.shape for value in values])
else:
    print(values.shape)
Raw lines 278 to 296
297## Genomics and Other Sequences
299Define the attribution unit:
301- nucleotide or amino acid;
302- one-hot channel;
303- k-mer;
304- motif;
305- position window;
306- assay channel.
308Independent one-hot channels can create invalid bases. Prefer a masker or grouping that preserves valid sequence states. For motif-level claims, aggregate or test motifs explicitly and validate across background sequences.
310For genomic models, background choice can represent:
312- genomic distribution;
313- dinucleotide-shuffled controls;
314- matched GC/content cohorts;
315- experimentally defined controls.
317Each implies a different baseline and scientific question.

Genomics and Other Sequences

Define the attribution unit:

  • nucleotide or amino acid;
  • one-hot channel;
  • k-mer;
  • motif;
  • position window;
  • assay channel.

Independent one-hot channels can create invalid bases. Prefer a masker or grouping that preserves valid sequence states. For motif-level claims, aggregate or test motifs explicitly and validate across background sequences.

For genomic models, background choice can represent:

  • genomic distribution;
  • dinucleotide-shuffled controls;
  • matched GC/content cohorts;
  • experimentally defined controls.

Each implies a different baseline and scientific question.

Raw lines 297 to 318
319## Multiple Inputs
321For models with multiple inputs, use a compatible list/composite masker or framework explainer:
323```python
324values = deep_explainer.shap_values([input_a, input_b])
325```
327Do not sum values across inputs unless they share the same additive output and the aggregation is documented. Keep names and shapes per input.

Multiple Inputs

For models with multiple inputs, use a compatible list/composite masker or framework explainer:

values = deep_explainer.shap_values([input_a, input_b])

Do not sum values across inputs unless they share the same additive output and the aggregation is documented. Keep names and shapes per input.

Raw lines 319 to 328
329## Performance
331- Explain a small, predeclared row subset first.
332- Restrict outputs.
333- Batch model calls.
334- Keep background modest and test convergence.
335- Increase `max_evals`/`nsamples` only after validating shape and semantics.
336- Measure peak accelerator memory.
337- Avoid silently falling back to CPU.
339Approximation variance and model stochasticity are different. Put the model in deterministic inference mode before estimating explainer variability.

Performance

  • Explain a small, predeclared row subset first.
  • Restrict outputs.
  • Batch model calls.
  • Keep background modest and test convergence.
  • Increase max_evals/nsamples only after validating shape and semantics.
  • Measure peak accelerator memory.
  • Avoid silently falling back to CPU.

Approximation variance and model stochasticity are different. Put the model in deterministic inference mode before estimating explainer variability.

Raw lines 329 to 340
341## Privacy
343Text and image plots can reproduce sensitive input content. Before export:
345- redact direct identifiers;
346- avoid embedding full clinical notes or faces when unnecessary;
347- separate row identifiers from plot artifacts;
348- restrict report access;
349- review HTML/JavaScript force or text outputs for embedded raw values.

Privacy

Text and image plots can reproduce sensitive input content. Before export:

  • redact direct identifiers;
  • avoid embedding full clinical notes or faces when unnecessary;
  • separate row identifiers from plot artifacts;
  • restrict report access;
  • review HTML/JavaScript force or text outputs for embedded raw values.
Raw lines 341 to 350
351## Sources
353- Text examples: https://shap.readthedocs.io/en/latest/text_examples.html
354- Image examples: https://shap.readthedocs.io/en/latest/image_examples.html
355- Genomic examples: https://shap.readthedocs.io/en/latest/genomic_examples.html
356- Text masker: https://shap.readthedocs.io/en/latest/generated/shap.maskers.Text.html
357- Image masker: https://shap.readthedocs.io/en/latest/generated/shap.maskers.Image.html
358- DeepExplainer: https://shap.readthedocs.io/en/latest/generated/shap.DeepExplainer.html
359- GradientExplainer: https://shap.readthedocs.io/en/latest/generated/shap.GradientExplainer.html
360- TransformersPipeline: https://shap.readthedocs.io/en/latest/generated/shap.models.TransformersPipeline.html
362- Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/pyproject.toml
363- Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/models/_transformers_pipeline.py
364- Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/explainers/_deep/deep_pytorch.py
365- Released source / upstream contract: https://huggingface.co/docs/transformers/main_classes/pipelines#transformers.TextClassificationPipeline

Sources

  • Text examples: https://shap.readthedocs.io/en/latest/text_examples.html
  • Image examples: https://shap.readthedocs.io/en/latest/image_examples.html
  • Genomic examples: https://shap.readthedocs.io/en/latest/genomic_examples.html
  • Text masker: https://shap.readthedocs.io/en/latest/generated/shap.maskers.Text.html
  • Image masker: https://shap.readthedocs.io/en/latest/generated/shap.maskers.Image.html
  • DeepExplainer: https://shap.readthedocs.io/en/latest/generated/shap.DeepExplainer.html
  • GradientExplainer: https://shap.readthedocs.io/en/latest/generated/shap.GradientExplainer.html
  • TransformersPipeline: https://shap.readthedocs.io/en/latest/generated/shap.models.TransformersPipeline.html
  • Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/pyproject.toml
  • Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/models/_transformers_pipeline.py
  • Released source / upstream contract: https://github.com/shap/shap/blob/v0.52.0/shap/explainers/_deep/deep_pytorch.py
  • Released source / upstream contract: https://huggingface.co/docs/transformers/main_classes/pipelines#transformers.TextClassificationPipeline
Raw lines 351 to 365