spacr.attribution¶
Attribution — what a trained classifier attends to, and whether that means anything.
spaCR already drew Grad-CAM and saliency maps (spacr.utils.GradCAMGenerator,
spacr.utils.SaliencyMapGenerator, spacr.utils.IntegratedGradients). This
module is the library those two were the first entries in: the CAM family
(Grad-CAM, Grad-CAM++, Score-CAM, XGrad-CAM, Layer-CAM, Eigen-CAM, HiRes-CAM,
Ablation-CAM), the gradient family (saliency, integrated gradients, guided
backprop, input×gradient, DeepLIFT, and SmoothGrad wrapped around any of them),
the SHAP family (GradientSHAP, DeepSHAP), the perturbation family (occlusion,
feature ablation), and for Vision Transformers attention rollout plus Chefer et
al.’s class-specific relevance propagation.
Not every method applies to every backbone. method_applicability() says
which do for a model or a model_type name, and why the others do not, so a
method selector can grey an entry with its reason instead of failing mid-run.
Almost none of it is written here. The CAM variants come from the optional torchcam attribution extra, while the gradient and perturbation methods come from the core captum dependency. What is written here is the part no library can supply: the adapters that make every method agree on one output shape, the handling of spaCR’s two classifier head shapes, and — the reason this module exists — the analyses in the second half.
An attribution map is not an explanation. It is a number per pixel produced by a procedure. It does not show what the model “looked at”, it does not establish that the highlighted pixels caused the prediction, and it will render a confident, beautiful, plausible picture for a model with random weights. Four checks stand between a map and wishful thinking, and they are the point of this module:
deletion_curve()/insertion_curve()— remove (or add) the pixels the map ranks highest and watch the score. A map whose deletion curve is flat is not describing what the model uses, however good it looks.pointing_game()— does the map’s peak land inside the object at all? spaCR has the object masks already (merged/*.npy), so this costs nothing.randomization_sanity_check()— Adebayo et al. 2018. Randomise the model’s weights layer by layer and attribute again. Several popular methods return a nearly identical map for a randomised model, which means they are edge detectors that happen to be plotted over a classifier. This is the single most informative check here and the one most often skipped.method_agreement()— rank correlation between methods on the same image. Agreement is weak evidence. Disagreement is strong evidence that no single map should be trusted.
Every criterion measures a different property and they routinely disagree. None of them is ground truth, because for attribution there is none.
Two head shapes, one contract. A spaCR classifier’s head emits either one
logit (binary; class 1 when the logit is positive) or C logits. Code that
assumes one shape is wrong for the other, and silently so: attributing the raw
logit of a single-logit head always explains class 1, so for an image the model
called class 0 the map you get is the map for the class it rejected — the
negation of what you asked for. Every method here goes through
ClassScoreModel, which presents a single logit z as the two-column
view [-z, +z]. Both classes then have a real gradient, target means the
same thing for both head shapes, and no caller has to know which head it has.
- author:
spaCR
Exceptions¶
Base class for the failures this module reports instead of guessing. |
|
Raised when a CAM is asked of a model that has no spatial layer to hook. |
|
Raised for a method name that is not registered. |
Classes¶
Pairwise rank correlation between several methods on the same image. |
|
One attribution map plus everything needed to judge it. |
|
Batch adapter with the interface |
|
Present any spaCR classifier head as |
|
A deletion or insertion curve and its area. |
|
One registered attribution method. |
|
Result of randomising the model's weights and attributing again. |
Functions¶
|
|
|
Classify a backbone into what the attribution families can use. |
|
Attention rollout (Abnar & Zuidema 2020) for transformer backbones. |
|
Attribute one image with one method. |
|
|
|
Every |
|
Class-specific transformer relevance (Chefer, Gur & Wolf 2021). |
|
Per-class scores for |
|
Attribute one image with several methods, for side-by-side reading. |
|
Every |
|
Remove the highest-ranked pixels first and track the class probability. |
|
Every faithfulness number for one map, with the caveats attached. |
|
Start from a blanked image and add the highest-ranked pixels first. |
|
Registered method names, optionally restricted to one family. |
|
Rank correlation between several attribution maps of the same image. |
|
Whether a registered method can give a meaningful map for this backbone. |
|
Method names grouped by family, families in a stable order. |
|
Does the map's brightest pixel land inside the object? |
|
Pointing-game hit rate over a set of images. |
|
Adebayo et al. 2018: does the map change when the weights are destroyed? |
|
The last convolutional layer — the usual CAM target — or None. |
|
The registry method a |
|
Resolve a dotted layer name against |
|
SmoothGrad: average |
Module Contents¶
- exception spacr.attribution.AttributionError[source]¶
Bases:
RuntimeErrorBase class for the failures this module reports instead of guessing.
Initialize self. See help(type(self)) for accurate signature.
- exception spacr.attribution.NoSpatialLayerError[source]¶
Bases:
AttributionErrorRaised when a CAM is asked of a model that has no spatial layer to hook.
A CAM is a weighted sum of one convolutional layer’s feature maps. A pure transformer has no such layer, and hooking its patch embedding produces a picture that is not a CAM of anything. Rather than return that picture, the CAM adapters raise this and name the model so the caller can switch to
attention_rollout()or to a gradient / perturbation method, which work on any architecture.Initialize self. See help(type(self)) for accurate signature.
- exception spacr.attribution.UnknownMethodError[source]¶
Bases:
AttributionErrorRaised for a method name that is not registered.
Initialize self. See help(type(self)) for accurate signature.
- class spacr.attribution.Agreement[source]¶
Pairwise rank correlation between several methods on the same image.
- Parameters:
methods – attribution-method names in matrix row and column order.
matrix – symmetric Spearman rank-correlation matrix for those methods.
mean – mean of the finite off-diagonal correlations.
minimum – smallest finite off-diagonal correlation.
pairs –
(method_a, method_b, rho)comparisons ordered from greatest disagreement upward.notes – verdict and interpretive caveats accompanying the agreement result.
- class spacr.attribution.Attribution[source]¶
One attribution map plus everything needed to judge it.
- Parameters:
method – Requested attribution-method name; normally a key of
ATTRIBUTION_METHODS, and retained verbatim on a skipped-failure placeholder.map – Finite 2-D float32 map at input spatial resolution; larger values rank pixels higher, while a skipped failure carries an all-zero placeholder.
target – Class index this map was requested to explain.
n_classes – Number of classes exposed by the normalized head, including two for a single-logit binary head.
single_logit – Whether the underlying model head emitted one binary logit.
predicted – Class predicted by the model for the attributed input.
raw – Signed per-channel attribution retained by methods that expose it, or
Nonewhen no such representation exists.layer – Resolved CAM target-layer name, the caller’s requested layer on a skipped failure, or
Nonewhen no layer applies.family – Registered family (
"cam","gradient","perturbation", or"attention"), or an empty string for an unregistered skipped failure.backend – Registered implementation provider (
"torchcam","captum", or"spacr"), or an empty string for an unregistered skipped failure.params – Recorded call options, including the resolved layer and SmoothGrad flag for registry-dispatched methods; this is not a complete expansion of every effective default.
notes – User-facing caveats, flat-map or single-logit context, or the reason a placeholder method failed.
- normalized() numpy.ndarray[source]¶
The map rescaled to
[0, 1]; all-zero when the map is flat.A flat map is exactly what a fully suppressed CAM produces, and the unguarded min-max rescale of one is
0/0.
- class spacr.attribution.AttributionMapGenerator(model, method: str = 'gradcam', target_layer: str | None = None, model_type: str | None = None, smoothgrad_samples: int = 0, smoothgrad_sigma: float = 0.15, **kw)[source]¶
Batch adapter with the interface
generate_activation_mapalready uses.spacr.utils.GradCAMGeneratorandspacr.utils.SaliencyMapGeneratorexposecompute_*_and_predictions(X)plusplot_activation_grid. This offers the same two calls for every method inATTRIBUTION_METHODS, so the existing batch loop gains twelve methods without changing shape.- Parameters:
model – the trained classifier.
method – a key of
ATTRIBUTION_METHODS.target_layer – CAM target layer, or None for the last convolution.
model_type – architecture name, used in the error messages.
smoothgrad_samples – when above 1, each map is SmoothGrad-averaged.
smoothgrad_sigma – SmoothGrad noise as a fraction of the input range.
kw – forwarded to the method.
- Raises:
UnknownMethodError – if
methodis not registered inATTRIBUTION_METHODS.
Validate the method name up front rather than mid-batch.
- compute_maps_and_predictions(X)[source]¶
Attribute every image in a batch.
- Parameters:
X – batch tensor
(N, C, H, W).- Returns:
(maps, predictions)— maps is(N, H, W)float32, predictions is(N,)long, correct for either head shape.
- plot_activation_grid(X, maps, predictions, overlay=True, normalize=False)[source]¶
Render the batch grid, reusing spaCR’s existing layout.
- Parameters:
X – the input batch.
maps – the attribution maps.
predictions – predicted class per image.
overlay – draw the map over the image.
normalize – percentile-stretch the image under the overlay.
- Returns:
the matplotlib Figure.
- class spacr.attribution.ClassScoreModel(model: torch.nn.Module, n_out: int | None = None)[source]¶
Bases:
torch.nn.ModulePresent any spaCR classifier head as
C >= 2per-class scores.A head emitting one logit
zis presented as[-z, +z]: column 1 is the evidence for class 1, column 0 the evidence for class 0, andargmaxreproduces thez > 0rule spaCR’s binary models use. The obvious alternative,[0, z], is exactly equivalent under softmax but has zero gradient for class 0, so every attribution for class 0 would be an all-zero map — a silent, plausible-looking wrong answer.A head emitting
C > 1logits is passed through untouched.- Parameters:
model – the classifier to wrap.
n_out – optional raw output width. If omitted, the first forward pass infers it from the wrapped model’s output.
- Variables:
n_out – the wrapped model’s raw output width (1 or C).
n_classes – the number of classes the wrapper exposes (2 or C).
single_logit – True when the wrapped head emits one logit.
Wrap
model, recording whether its head is single-logit.- forward(x: torch.Tensor) torch.Tensor[source]¶
Return
(B, n_classes)scores forx.- Parameters:
x – input batch passed to the wrapped classifier.
- class spacr.attribution.Curve[source]¶
A deletion or insertion curve and its area.
- Variables:
kind –
'deletion'or'insertion'.fractions – fraction of pixels removed / inserted at each step.
scores – the target class’s probability at each step.
auc – area under the curve, trapezoidal over
fractions. Bounded in[0, 1]because the scores are probabilities.baseline – what removed pixels were replaced with.
target – the class whose probability was tracked.
notes – caveats.
- class spacr.attribution.MethodSpec[source]¶
One registered attribution method.
- Parameters:
name – registry key callers pass as
method=.family – method family—
"cam","gradient","shap","perturbation", or"attention".backend – implementation provider—
"torchcam","captum", or"spacr".fn – adapter callable that computes this method’s attribution.
needs_layer – whether the method requires a spatial target layer.
smoothed – whether the Captum adapter wraps the base attributor in a SmoothGrad noise tunnel.
description – concise user-facing explanation suitable for method selectors.
- smoothgrad_variant() MethodSpec[source]¶
This method with SmoothGrad averaging turned on.
- class spacr.attribution.SanityCheck[source]¶
Result of randomising the model’s weights and attributing again.
- Variables:
method – the method under test.
mode –
'cascading'(randomise layers from the output backwards, accumulating) or'independent'(one layer at a time, from a fresh copy).stages –
(layer_name, similarity)after each randomisation step, in the order applied.final_similarity – similarity to the trained model’s map once every parameterised layer has been randomised. This is the number that matters: at that point the model is noise.
max_similarity – the largest similarity over all stages.
threshold – the value
final_similaritymust fall below to pass.passed – whether the method’s map changed when the weights did.
metric – name of the similarity measure.
notes – the verdict in words.
- spacr.attribution.applicable_methods(model: torch.nn.Module | None = None, model_type: str | None = None) Dict[str, Tuple[bool, str]][source]¶
method_applicability()for every registered method, by name.
- spacr.attribution.architecture_kind(model: torch.nn.Module | None = None, model_type: str | None = None) str[source]¶
Classify a backbone into what the attribution families can use.
- Parameters:
model – the model itself, when it is loaded.
model_type – the architecture name spaCR stores in settings (
'resnet50','maxvit_t','vit_b_16'…).
- Returns:
'vit'(global self-attention over a patch grid),'swin'(shifted-window attention),'hybrid'(MaxViT: convolutions after attention),'cnn','other'(a loaded model with neither convolution nor attention) or'unknown'(nothing to go on).
- spacr.attribution.attention_rollout(model: torch.nn.Module, image: Any, *, target: int | None = None, head_fusion: str = 'mean', discard_ratio: float = 0.0, model_type: str | None = None) Attribution[source]¶
Attention rollout (Abnar & Zuidema 2020) for transformer backbones.
A CAM needs a convolutional feature map. A pure transformer has none, so this is the substitute: the per-layer attention matrices are averaged over heads, mixed with the identity to account for the residual stream, row- normalised and multiplied together, giving how much each input token contributes to the class token.
It reads spaCR’s
torch.nn.MultiheadAttentionblocks, which return their attention weights fromforward. Backbones whose attention is a fused kernel (timm’s ViT viascaled_dot_product_attention) expose no weights, and this raises rather than inventing a map.Rollout is not class-conditional. The result is the same for every
target: it describes where information flowed, not what the model concluded. It cannot show the model separated your classes; a gradient or perturbation method can.- Parameters:
model – the transformer classifier.
image – one image,
(C, H, W)or(1, C, H, W).target – recorded on the result; does not change the map.
head_fusion –
'mean','max'or'min'over attention heads.discard_ratio – fraction of the lowest attention weights zeroed per layer before rollout, which sharpens the map and is pure cosmetics.
model_type – architecture name for the error messages.
- Returns:
the
Attribution.- Raises:
NoSpatialLayerError – when the model exposes no attention weights.
- spacr.attribution.attribute(model: torch.nn.Module, image: Any, method: str = 'gradcam', *, target: int | None = None, layer: str | None = None, model_type: str | None = None, **kw) Attribution[source]¶
Attribute one image with one method.
Every registered method returns the same thing: a finite
(H, W)map at the input’s resolution, for the classtargetnames, for either head shape. What differs is what the number means, which is whyAttributioncarries the family and the notes.- Parameters:
model – the trained classifier. Left untouched — the wrapper and the hooks are removed before this returns.
image – one image,
(H, W),(C, H, W)or(1, C, H, W).method – a key of
ATTRIBUTION_METHODS.target – class index to explain; defaults to the model’s prediction. For a single-logit head, 0 and 1 are both valid and give opposite maps.
layer – dotted target-layer name for the CAM family; defaults to the last convolution.
model_type – architecture name, used only to make errors readable.
kw – method-specific options —
n_steps/baseline(integrated gradients, DeepLIFT),window/stride(occlusion),block(feature ablation),head_fusion/discard_ratio(rollout),n_samples/sigmawhen called throughsmoothgrad().
- Returns:
the
Attribution.- Raises:
UnknownMethodError – for an unregistered method name.
NoSpatialLayerError – when a CAM is asked of a model with no convolutional feature map, or rollout of a model with no attention.
AttributionError – for a bad target, layer or baseline.
- spacr.attribution.cam_type_applicability(cam_type: str, *, model: torch.nn.Module | None = None, model_type: str | None = None) Tuple[bool, str][source]¶
method_applicability()for acam_typesetting value.The legacy Grad-CAM generators need a spatial layer like any CAM; the legacy saliency maps apply to every backbone.
- Parameters:
cam_type – the
cam_typesetting value, asresolve_cam_type()accepts it.model – the loaded model, when there is one.
model_type – the architecture name, when there is no model.
- Returns:
(applies, reason); the reason is empty when it applies.- Raises:
UnknownMethodError – for a name
resolve_cam_type()refuses.
- spacr.attribution.cam_type_choices() Tuple[str, ...][source]¶
Every
cam_typethe Activation Maps settings can name, in menu order.
- spacr.attribution.chefer_relevance(model: torch.nn.Module, image: Any, *, target: int | None = None, model_type: str | None = None) Attribution[source]¶
Class-specific transformer relevance (Chefer, Gur & Wolf 2021).
Rollout multiplies raw attention and so gives one map whatever class is asked about. This weights every head’s attention by the class score’s gradient on it, keeps the positive part, averages the heads and accumulates the result through the residual stream,
R <- R + A_bar Rfrom the identity. The class token’s row ofRis the relevance of each patch for the target class, so asking for the other class gives a different map.It reads
torch.nn.MultiheadAttentionblocks (torchvision’s ViT and spaCR’s own), asking each for per-head weights the wayattention_rollout()does.- Parameters:
model – the transformer classifier.
image – one image,
(C, H, W)or(1, C, H, W).target – class to explain; defaults to the prediction.
model_type – architecture name for the error messages.
- Returns:
the
Attribution.- Raises:
NoSpatialLayerError – when the model has no attention blocks whose weights sit on the gradient path, or its tokens do not form a grid.
- spacr.attribution.class_scores(model: torch.nn.Module, x: torch.Tensor, *, probability: bool = True) torch.Tensor[source]¶
Per-class scores for
x, for either head shape.- Parameters:
model – the classifier (raw or already wrapped).
x – input batch
(B, C, H, W).probability – return softmax probabilities rather than raw scores. Probabilities are what the deletion / insertion curves track, because a bounded quantity makes their areas comparable across images.
- Returns:
(B, n_classes)tensor.
- spacr.attribution.compare_methods(model: torch.nn.Module, image: Any, methods: Sequence[str] = (), *, target: int | None = None, layer: str | None = None, model_type: str | None = None, skip_failures: bool = True, **kw) List[Attribution][source]¶
Attribute one image with several methods, for side-by-side reading.
The deliverable is the panel plus
method_agreement()over it, not any single map. Methods that cannot run on this architecture (a CAM on a pure transformer) are skipped with their reason recorded rather than aborting the comparison, unlessskip_failuresis off.- Parameters:
model – the trained classifier.
image – one image.
methods – method names; defaults to one representative of each family that works on any architecture, plus Grad-CAM.
target – class to explain; resolved once so every method explains the same class.
layer – CAM target layer.
model_type – architecture name for the error messages.
skip_failures – record and skip a failing method instead of raising.
kw – forwarded to every method.
- Returns:
the attributions, in the order requested. Failures appear as
Attributionobjects with a flat map and the error innotesonly whenskip_failuresis True.
- spacr.attribution.conv_layer_names(model: torch.nn.Module) List[str][source]¶
Every
Conv2dlayer name inmodel, in definition order.- Parameters:
model – the model to scan.
- Returns:
dotted layer names; empty for a model with no convolutions.
- spacr.attribution.deletion_curve(model: torch.nn.Module, image: Any, amap: Any, *, target: int | None = None, n_steps: int = 20, baseline: Any = 'blur') Curve[source]¶
Remove the highest-ranked pixels first and track the class probability.
A faithful map removes the pixels the model actually uses, so the probability collapses early and the area under the curve is small. A flat deletion curve is the finding: the map ranked pixels the model does not use, whatever the picture looked like.
- Parameters:
model – the trained classifier.
image – the image the map explains.
amap – an
Attributionor a raw(H, W)map.target – class whose probability is tracked; defaults to the prediction on the unperturbed image.
n_steps – perturbation steps between 0 % and 100 % removed.
baseline – what removed pixels become —
'blur'(default, the least out-of-distribution),'zero','mean','uniform', a number or a tensor.
- Returns:
the
Curve; loweraucis better.
- spacr.attribution.faithfulness(model: torch.nn.Module, image: Any, amap: Any, *, target: int | None = None, n_steps: int = 20, baseline: Any = 'blur', mask: Any | None = None) Dict[str, Any][source]¶
Every faithfulness number for one map, with the caveats attached.
- Parameters:
model – the trained classifier.
image – the image the map explains.
amap – an
Attributionor a raw(H, W)map.target – class to score.
n_steps – steps for both curves.
baseline – removal baseline for both curves.
mask – optional boolean object mask enabling the pointing game.
- Returns:
dict with
deletion_auc,insertion_auc,deletionandinsertionCurveobjects,pointing_game(or None),flatandnotes.
- spacr.attribution.insertion_curve(model: torch.nn.Module, image: Any, amap: Any, *, target: int | None = None, n_steps: int = 20, baseline: Any = 'blur') Curve[source]¶
Start from a blanked image and add the highest-ranked pixels first.
The mirror of
deletion_curve(), and it answers a different question: deletion asks whether the map found pixels that are necessary, insertion whether it found pixels that are sufficient. The two routinely rank methods differently, and that disagreement is information, not an error.- Parameters:
model – the trained classifier.
image – the image the map explains.
amap – an
Attributionor a raw(H, W)map.target – class whose probability is tracked.
n_steps – insertion steps between 0 % and 100 % inserted.
baseline – what the not-yet-inserted pixels are.
- Returns:
the
Curve; higheraucis better.
- spacr.attribution.list_methods(family: str | None = None) List[str][source]¶
Registered method names, optionally restricted to one family.
- spacr.attribution.method_agreement(attributions: Sequence[Any]) Agreement[source]¶
Rank correlation between several attribution maps of the same image.
Agreement and disagreement are not symmetric evidence. Methods agreeing is weak: the gradient family shares failure modes, so its members agree with each other whether or not any of them is faithful. Methods disagreeing is strong: at most one of them can be right, so none should be quoted alone.
- Parameters:
attributions –
Attributionobjects or raw(H, W)maps; at least two, all the same shape.- Returns:
the
Agreement.- Raises:
AttributionError – for fewer than two maps or a shape mismatch.
- spacr.attribution.method_applicability(method: str, *, model: torch.nn.Module | None = None, model_type: str | None = None) Tuple[bool, str][source]¶
Whether a registered method can give a meaningful map for this backbone.
Decided from the architecture and from which optional backends are installed, without running the model, so a settings form can grey the methods that do not apply and show the reason.
- Parameters:
method – a key of
ATTRIBUTION_METHODS.model – the loaded model, when there is one.
model_type – the architecture name, when there is no model.
- Returns:
(applies, reason); the reason is empty when it applies.- Raises:
UnknownMethodError – for an unregistered method name.
- spacr.attribution.methods_by_family() Dict[str, List[str]][source]¶
Method names grouped by family, families in a stable order.
- spacr.attribution.pointing_game(amap: Any, mask: Any, *, tolerance: int = 0) float[source]¶
Does the map’s brightest pixel land inside the object?
spaCR already has the answer key:
merged/*.npystores the label-mask planes next to the image channels, so a boolean object mask is free. The game is deliberately crude — one pixel, hit or miss — because that is all it claims to measure.- Parameters:
amap – an
Attributionor a(H, W)map.mask – object mask, same spatial shape. Any non-zero value is inside the object, so a spaCR integer label plane can be passed directly.
tolerance – dilate the mask by this many pixels before testing, the allowance the original pointing-game protocol uses for maps computed at a coarser resolution than the image.
- Returns:
1.0 for a hit, 0.0 for a miss.
- Raises:
AttributionError – on a shape mismatch or an empty mask — an empty mask would score 0.0 and look like a method failure rather than a missing annotation.
- spacr.attribution.pointing_game_rate(maps: Sequence[Any], masks: Sequence[Any], *, tolerance: int = 0) Dict[str, Any][source]¶
Pointing-game hit rate over a set of images.
- Parameters:
maps – attributions or raw maps.
masks – the matching object masks.
tolerance – passed to
pointing_game().
- Returns:
dict with
rate,hits,n,skipped(images whose mask was empty or mismatched, which are excluded rather than counted as misses) andnotes.- Raises:
AttributionError – when the two sequences differ in length.
- spacr.attribution.randomization_sanity_check(model: torch.nn.Module, image: Any, method: str | Callable = 'gradcam', *, target: int | None = None, layer: str | None = None, model_type: str | None = None, mode: str = 'cascading', threshold: float = 0.5, seed: int = 0, max_stages: int | None = None, attribute_fn: Callable[..., Any] | None = None, **kw) SanityCheck[source]¶
Adebayo et al. 2018: does the map change when the weights are destroyed?
Randomise the model’s parameters layer by layer, from the output backwards, re-attribute at every stage, and correlate each map with the map from the trained model. A method that depends on what the model learned produces an uncorrelated map once the weights are noise. Several widely used methods do not: guided backprop and guided Grad-CAM are the canonical failures, and a method that fails this is an edge detector being read as an explanation.
This is the most informative check in the module. A map that passes deletion and insertion but fails this one is describing the image; a method that fails here cannot be rescued by smoothing, a better colormap or a different target layer.
- Parameters:
model – the trained classifier. Deep-copied — the original is never modified.
image – one image.
method – a registered method name, or any callable when
attribute_fnis not given.target – class to explain, resolved once against the trained model and held fixed, so a stage’s map is not silently for a different class.
layer – CAM target layer.
model_type – architecture name for the error messages.
mode –
'cascading'(default, the paper’s) or'independent'.threshold – rank correlation below which the method passes.
seed – RNG seed for the randomisation, so the check reproduces.
max_stages – cap on the number of layers randomised, from the output backwards. The final stage always randomises everything regardless.
attribute_fn –
fn(model, image, target=...) -> map or Attribution, for testing a method that is not in the registry.kw – forwarded to the attribution call.
- Returns:
the
SanityCheck.- Raises:
AttributionError – for an unknown mode, or a model with no parameters to randomise.
- spacr.attribution.recommended_layer(model: torch.nn.Module) str | None[source]¶
The last convolutional layer — the usual CAM target — or None.
- Parameters:
model – model whose convolutional layers are scanned.
Mirrors
spacr.utils.recommend_target_layers(), but returns None for a model with no convolutions instead of raising, so the CAM adapters can raiseNoSpatialLayerErrorwith the architecture named.
- spacr.attribution.resolve_cam_type(cam_type: str) str | None[source]¶
The registry method a
cam_typenames, or None for a legacy one.- Parameters:
cam_type – a
cam_typesetting value: a legacy generator, aCAM_TYPE_ALIASESspelling or a key ofATTRIBUTION_METHODS.- Returns:
the registry method name, or None for a legacy generator.
- Raises:
UnknownMethodError – for a name that is neither.
- spacr.attribution.resolve_layer(model: torch.nn.Module, name: str) torch.nn.Module[source]¶
Resolve a dotted layer name against
model.- Parameters:
model – the model to look in.
name – dotted module path, e.g.
'features.2'.
- Returns:
the submodule.
- Raises:
AttributionError – naming the closest available layers. A wrong target layer is the most common way a CAM run dies, and a bare
AttributeError: 'Sequential' object has no attribute 'conv_b'does not tell the user what to type instead.
- spacr.attribution.smoothgrad(model: torch.nn.Module, image: Any, base_method: str = 'saliency', *, n_samples: int = 25, sigma: float = 0.15, target: int | None = None, layer: str | None = None, model_type: str | None = None, seed: int | None = None, **kw) Attribution[source]¶
SmoothGrad: average
base_methodovern_samplesnoisy copies.Gradient maps are visually noisy because the gradient of a ReLU network fluctuates sharply between neighbouring inputs. Averaging over Gaussian perturbations of the input suppresses that fluctuation as
1/sqrt(n)while keeping the structure that survives perturbation.For the captum-backed methods this is captum’s own
NoiseTunnel. The CAM family and rollout are not captum attributors, so for those the averaging is done here over re-runs of the adapter — same definition, applied to the map.Smoothing makes a map look better. It does not make it more faithful, and a smoothed map that still fails
randomization_sanity_check()fails it just as badly.- Parameters:
model – the trained classifier.
image – one image.
base_method – any key of
ATTRIBUTION_METHODS.n_samples – number of noisy copies to average.
1is a single noisy sample, not the clean map — callattribute()for that.sigma – noise standard deviation as a fraction of the input’s dynamic range (the SmoothGrad paper’s
stdev_spread).target – class to explain; resolved once on the clean image so the noise cannot flip which class is being explained sample to sample.
layer – CAM target layer.
model_type – architecture name for the error messages.
seed – torch seed, so a repeated call reproduces.
kw – forwarded to the base method.
- Returns:
the averaged
Attribution.- Raises:
AttributionError – for
n_samplesbelow 1.
Nested helpers¶
- _ablation_cam._ablate(_m, _inp, out)¶
Record the clean feature maps, or zero one channel per batch row.
spacr/attribution.py:1125
- _ask_for_attention_weights._wrap(block)¶
Install the attention-weight adapter and return the original call.
spacr/attribution.py:868
- _ask_for_attention_weights._wrap.forward(*args, **kwargs)¶
Request per-head weights unless a positional request owns them.
spacr/attribution.py:872
- _ask_for_attention_weights.restore()¶
Restore every block’s exact original bound forward method.
spacr/attribution.py:890
- _check_spatial_activation._attn_hook(_m, _inp, _out)¶
Record that an attention block ran.
spacr/attribution.py:430
- _check_spatial_activation._target_hook(_m, _inp, out)¶
Capture the target layer’s output and its position in the pass.
spacr/attribution.py:425
- _eigen_cam._hook(_m, _inp, out)¶
Capture the target layer’s feature maps.
spacr/attribution.py:637
- _layer_activation_and_gradient._hook(_m, _inp, out)¶
Copy the feature maps and ask for their gradient.
spacr/attribution.py:1062
- _layer_activation_and_gradient._keep_gradient(grad)¶
Store the gradient that reaches the hooked feature map.
spacr/attribution.py:1058
- attention_rollout._hook(_m, _inp, out)¶
Capture the (B, L, S) attention weights an MHA block returns.
spacr/attribution.py:954
- chefer_relevance._hook(_m, _inp, out)¶
Keep the attention weights an MHA block returns, graph attached.
spacr/attribution.py:1422
- randomization_sanity_check._run(m: nn.Module) np.ndarray¶
Attribute
imagewith the method under test on modelm.spacr/attribution.py:2280