What is Grad-CAM and how does it explain CNN predictions?
Grad-CAM (Gradient-weighted Class Activation Mapping) is a post-hoc technique that creates a class-specific spatial heatmap showing which regions of a convolutional network's feature representation contributed positive evidence to a selected target class score. It combines the feature maps of a chosen convolutional layer with gradients of that specific class score, then keeps positive contributions with ReLU.
For example, if a CNN predicts "dog" for a photograph, a Grad-CAM heatmap can show whether the score is associated mostly with the dog's body, surrounding grass, or an irrelevant watermark. It can help investigate *what the trained model is using*, but it does not establish causal reasoning, prove object recognition, or certify that a prediction is correct.
The foundational method is Selvaraju et al., *Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization* (ICCV 2017).
1. What does Grad-CAM explain?
- Model: A trained convolutional neural network (CNN) with spatial feature maps and a differentiable target score.
- Target concept: One selected class, e.g., dog. It can be the top-predicted class or a deliberately chosen alternative.
- Target layer: Usually the last useful convolutional feature layer or convolutional block, before spatial information is collapsed by global pooling or a classifier.
- Output: A coarse grid of nonnegative values, commonly normalized and interpolated back to input-image size as a visualization.
- Interpretation: Locations with higher heatmap intensity show stronger positive contributions in Grad-CAM's gradient-weighted linear approximation, for that class and layer on this input.
- Important boundary: A high intensity is neither a calibrated pixel probability nor a causal statement that removing that pixel would necessarily change the label.
A single image can produce different Grad-CAM maps for different classes because each class has a different score and gradient.
2. Formula: From feature maps and gradients to a heatmap
Let A^k be channel k of a chosen convolutional feature tensor, with spatial shape H×W. Let y^c be the pre-softmax target class score (logit) for class c.
Step A — Calculate a gradient for each spatial position.
G^k_(i,j) = ∂y^c / ∂A^k_(i,j).
This tells us how sensitive the target score is locally to the selected layer's feature at that position, holding the rest of the computation fixed for the derivative.
Step B — Average those gradients spatially.
α^c_k = (1/Z) × Σ_i Σ_j G^k_(i,j), where Z=H×W.
This produces one importance weight per channel, not one weight per pixel. Spatial averaging is why a channel's gradient may have mixed positive and negative locations but one net channel weight.
Step C — Weight and sum the feature maps.
M^c_(i,j) = Σ_k α^c_k × A^k_(i,j).
Step D — Retain positive evidence.
GradCAM^c_(i,j) = ReLU(M^c_(i,j)) = max(0,M^c_(i,j)).
Negative entries are set to zero by design; this does not mean negative evidence does not exist. It means the standard Grad-CAM visualization highlights positive contributions to class c.
Step E — Visualize.
Interpolate the coarse heatmap to the original image height and width, normalize a nonconstant map for display, apply a color palette and blend with the original displayable RGB image.
Why logits rather than post-softmax probabilities? Softmax couples all class scores and may saturate; using the target logit normally gives a more direct class-specific gradient. Grad-CAM can be adapted to other differentiable scores when the interpretation is made explicit.
3. Beginner-friendly numerical example: A 2×2 Grad-CAM calculation
Suppose a toy CNN produces a target-class logit y^dog = 2.4 and we examine a convolutional layer with two feature channels, each a 2×2 map.
The feature activations are:
Channel A¹
[[2, 0], [1, 3]]
Channel A²
[[0, 2], [2, 1]]
For the same input and the chosen dog score, backpropagation returns gradients with respect to these four activations per channel.
Gradients with respect to A¹
G¹ = [[0.8, 0.4], [0.4, 0.4]]
Gradients with respect to A²
G² = [[−0.4, −0.8], [−0.4, −0.4]]
These are hypothetical values chosen for clear arithmetic. They can arise from a simple affine score: y^dog = 2.0 + Σ(G¹×A¹) + Σ(G²×A²). For these values, the first channel contributes 3.2 and the second −2.8, giving 2.0+3.2−2.8 = 2.4. This makes the example's class score and feature gradients mutually consistent.
Step 1 — Count spatial locations
Each map has H=2, W=2, so Z=H×W=4.
Step 2 — Find the channel importance weights
For channel 1:
α¹ = (0.8+0.4+0.4+0.4)/4 = 2.0/4 = +0.5.
For channel 2:
α² = (−0.4−0.8−0.4−0.4)/4 = −2.0/4 = −0.5.
Interpretation: The first channel has positive average sensitivity to the dog score; the second has negative average sensitivity. These weights depend on the chosen class and input.
Step 3 — Multiply each activation map by its weight
0.5×A¹ = [[1, 0], [0.5, 1.5]].
−0.5×A² = [[0, −1], [−1, −0.5]].
Step 4 — Sum corresponding positions
M^dog = 0.5×A¹ − 0.5×A²
M^dog = [[1+0, 0−1], [0.5−1, 1.5−0.5]]
M^dog = [[1, −1], [−0.5, 1]].
Notice how different spatial positions combine positive and negative contributions.
Step 5 — Apply ReLU
Standard Grad-CAM retains only positive entries:
GradCAM^dog = ReLU(M^dog) = [[1, 0], [0, 1]].
The final unnormalized Grad-CAM heatmap already has maximum value 1, so dividing by that maximum leaves the same normalized map:
Normalized = [[1, 0], [0, 1]].
Beginner interpretation: In this toy 2×2 representation, the top-left and bottom-right locations carry positive gradient-weighted evidence for dog under this selected layer and score; top-right and bottom-left contribute zero after ReLU. Those positions are coarse feature-map locations, not exact pixel boundaries, and the model could be using context rather than the animal itself.
Step 6 — Upsample and overlay on the image
In a real classifier, a last convolutional tensor might have shape [1,512,7,7] for one image. Grad-CAM yields a 7×7 spatial map. If the input was 224×224, bilinear interpolation converts it to a 224×224 visualization for overlay.
**Upsampling adds pixels to the *display*, not new localization information.** A coarse 7×7 map does not become a faithful 224×224 segmentation mask after interpolation.
For a heatmap h normalized to [0,1], a basic overlay blends the original RGB image with an appropriately colorized heatmap. A frequently used mixing rule is overlay = (1−λ)×RGB + λ×colorized_heatmap, with a display transparency such as λ=0.4. This is for visualization only; it does not alter the network's prediction.
4. How should we choose the target convolutional layer?
- Prefer the last spatially informative convolutional layer or block for class-level semantic localization. Its channels tend to represent higher-level concepts.
- Earlier convolutional layers have larger maps with more edge/texture detail, but often less class-specific semantics.
- Later layers after global pooling or flattening may no longer have useful H×W spatial dimensions, making them unsuitable for the standard Grad-CAM formula.
- Architecture matters: ResNet, VGG, EfficientNet and other CNNs organize convolutional blocks differently. Choose the layer by its runtime output shape and graph role, not an arbitrary module index.
- Post-activation vs pre-activation matters: A target layer after ReLU can give different feature maps from the preceding convolution. State exactly what was hooked.
- Residual and in-place operations: Hooking tensors that are later modified in-place can create gradient errors or change which value is actually being explained. Prefer a stable layer output and avoid in-place modifications in hooked paths.
Practical diagnostic: Confirm the hooked activation tensor has shape [batch, channels, feature_height, feature_width] and that the selected class score has a gradient path to it.
5. Correct PyTorch implementation using a forward hook and a tensor gradient hook
The implementation below uses one model input image and produces a target-class heatmap. It deliberately uses a forward module hook to capture activations, then attaches a Tensor.register_hook callback to the output to capture the gradient flowing into that feature tensor. PyTorch's current gradient-visualization documentation describes this as an appropriate pattern.
PYTHONimport torch import torch.nn.functional as F def grad_cam_heatmap(model, image, target_layer, class_idx=None): """ model: trained classifier, in eval() mode image: [1, C, H, W] preprocessed input target_layer: module producing [1, K, h, w] class_idx: target class index; default uses predicted class """ if image.ndim != 4 or image.shape[0] != 1: raise ValueError("Provide exactly one image: [1,C,H,W].") captured = {} def save_features(_module, _inputs, output): if not isinstance(output, torch.Tensor) or output.ndim != 4: raise ValueError("Target layer must yield a 4D feature tensor.") if not output.requires_grad: raise RuntimeError( "Target activations must support autograd. " "Avoid inference_mode/no_grad; if all model " "weights are frozen, allow input gradients." ) captured["activations"] = output.detach() # Attach backward callback to this exact forward output. def save_gradient(grad): captured["gradients"] = grad.detach() output.register_hook(save_gradient) handle = target_layer.register_forward_hook(save_features) try: # Grad-CAM needs differentiation, even during evaluation. with torch.enable_grad(): logits = model(image) if logits.ndim != 2 or logits.shape[0] != 1: raise ValueError("Expected class logits [1, classes].") index = (int(logits[0].argmax().item()) if class_idx is None else int(class_idx)) model.zero_grad(set_to_none=True) # Use a class LOGIT, not the softmax probability. score = logits[0, index] score.backward() a = captured["activations"][0] # [K,h,w] g = captured["gradients"][0] # [K,h,w] # Channel weights: spatial average of target gradients. alpha = g.mean(dim=(1, 2), keepdim=True) # [K,1,1] low_res = torch.relu((alpha * a).sum(dim=0)) # [h,w] high_res = F.interpolate( low_res[None, None], size=image.shape[-2:], mode="bilinear", align_corners=False )[0, 0] # Normalize positive heatmap for display; all-zero stays zero. heatmap = high_res / high_res.amax().clamp_min(1e-8) return heatmap.detach(), index finally: # Prevent hooks from leaking into later evaluations. handle.remove() # Example usage for a compatible pretrained CNN: # model.eval() # target_layer = model.layer4[-1] # e.g., ResNet final spatial block # heatmap, selected_class = grad_cam_heatmap( # model, preprocessed_image, target_layer, class_idx=None # )
Implementation notes:
- Use a trained model: Grad-CAM on a randomly initialized CNN will create a numerical map, but a visually appealing pattern would not be a trustworthy explanation of learned behavior.
- Call `model.eval()`: Disable training-time dropout randomness and prevent BatchNorm running-statistic updates. Evaluation mode does *not* disable gradients.
- Do not wrap the forward pass in `torch.no_grad()` or `torch.inference_mode()`: Grad-CAM requires a gradient graph. The example's
torch.enable_grad()restores ordinary grad mode, but an outer inference-mode context must also be avoided. - Tensor hooks rather than deprecated backward hooks: The code binds a gradient callback to the exact feature tensor.
register_full_backward_hookon the module is another option but can interact badly with in-place operations; avoid deprecatedregister_backward_hook. - If the entire model is frozen: Set
image = image.detach().requires_grad_(True)as appropriate before the forward pass to preserve an autograd path to the feature tensor. - Hook lifecycle: Always remove the forward hook, including on failure. In notebooks and services, stale hooks can accumulate, retain memory or overwrite captured values.
- One target class per explanation: The selected logit controls the gradient. To explain a different class, perform a separate gradient pass for that class (or handle graph retention carefully).
- Normalized heatmap is not a calibrated attribution: Normalization to a maximum of 1 is a visualization convention; a bright 1 does not mean 100% responsibility.
6. Overlay the heatmap correctly
The network usually receives a preprocessed tensor, which may have been standardized by channel-wise mean and standard deviation. That tensor is not necessarily suitable for direct display.
To make a simple red positive-evidence overlay:
PYTHON# original_rgb: the same image, unnormalized [3,H,W], range [0,1] # heatmap: returned [H,W] value range [0,1] strength = 0.4 red = torch.zeros_like(original_rgb) red[0] = heatmap.to(red.device) # red channel overlay = ((1 - strength) * original_rgb + strength * red).clamp(0.0, 1.0) # Render overlay with your preferred plotting/image library. # Do not feed overlay back into the classifier as the original input.
Requirements: The original display image and preprocessed input must describe the same cropped/resized frame. Account for center crops, padding, aspect-ratio changes or image rotations; otherwise the heatmap will appear over the wrong pixels. A simple red overlay is merely a visualization convention: gradient information itself does not have an intrinsic color.
7. What do positive and negative values mean?
- Positive channel importance `α_k`: Increasing a channel's features tends, on average over spatial positions and locally around the current input, to increase the chosen score in the gradient approximation.
- Negative channel importance `α_k`: Its average local gradient points in the opposite direction; the channel can suppress the selected score.
- Weighted local sum `M`: Combining weighted activations can give positive or negative values at specific locations.
- ReLU in standard Grad-CAM: Discards the negative part to emphasize evidence that increases the selected class score.
- A zero in the heatmap is ambiguous: It may mean little positive evidence, canceled contributions or negative evidence suppressed by ReLU. It does not prove the location is irrelevant to the network.
- A positive highlight does not identify an object automatically: The model may be using background texture, camera watermark, lighting or other spurious correlations.
Avoid the causal leap: Grad-CAM uses local derivatives and a weighted aggregation. These explain associations *in this model's computation* at the selected representation; they are not controlled interventions showing that particular pixels caused a decision.
8. Grad-CAM versus raw saliency maps
Raw gradient saliency
- Computes derivatives of the class score with respect to input pixels, e.g.,
∂y^c/∂x. - Has the original input resolution but can be noisy, unstable, sign-sensitive or dominated by fine pixel variations.
- Shows a local sensitivity measure, not necessarily object boundaries or globally important features.
Grad-CAM
- Computes gradients with respect to a selected convolutional feature tensor, averages them spatially per channel, and combines the feature maps.
- Usually has lower spatial resolution but is often more semantically class-focused at later convolutional layers.
- Produces a coarse class-specific localization signal rather than a pixel-perfect segmentation.
- Interpolation to input resolution does not regain the precise localization detail that was lost at the convolutional grid.
Related methods:
- CAM (Class Activation Mapping): Original CAM uses architectural assumptions such as global average pooling and class-specific classifier weights; Grad-CAM uses target gradients and is applicable to a wider range of differentiable CNN architectures.
- Guided Grad-CAM: Combines coarse Grad-CAM with fine-grained guided backpropagation for visually sharper outputs. A sharper map does not automatically mean a more faithful explanation.
- Integrated gradients/occlusion tests: Answer different attribution questions and can provide useful comparison checks. No single explanation method works perfectly in all circumstances.
9. Practical applications in classification and debugging
- Dataset shortcut discovery: If a dog classifier consistently highlights a watermark or grass rather than the dog, investigate background confounding and data collection bias.
- Failure investigation: On misclassified images, compare heatmaps for the predicted class and true class; the difference can reveal which features each score responds to.
- Localization sanity checking: Highlighted regions may overlap a labeled object, but such overlap is not proof the prediction is correct or the region is necessary.
- Medical-image and safety-sensitive research: Can help generate hypotheses about spurious cues, while requiring stronger validation and never being treated as clinical proof.
- Model regression checks: Compare heatmaps for selected reference images across model versions, preprocessing changes and training runs.
- Class-specific visual education: Explain to engineers why two visually similar classes may elicit different network attention patterns.
Production example: A defect classifier claims a manufactured part is defective, but its Grad-CAM frequently highlights the corner containing a factory camera timestamp. This is a debugging lead, not the diagnosis. Test by collecting counterfactual examples, covering/removing the timestamp, retraining with varied backgrounds, and checking task performance. If the predictions change when the shortcut changes while the defect does not, that is stronger evidence of spurious reliance.
10. How faithful and robust is a Grad-CAM explanation?
Faithfulness asks whether the heatmap meaningfully reflects the model's actual behavior, not whether it looks intuitive.
Useful checks include:
- Target-class specificity: Request separate maps for dog and cat logits on the same image. Confirm the maps can meaningfully change with the requested target.
- Parameter randomization: Randomize trained model weights in a controlled sequence and examine whether the explanations respond appropriately.
- Data-label randomization: Where feasible, compare against a model trained on scrambled labels to test whether the map reflects learned task structure.
- Deletion/insertion tests: Perturb or progressively reveal highlighted regions and measure changes in the target score. Take care that masking creates unnatural out-of-distribution images.
- Input perturbation stability: Compare maps under small, label-preserving changes, such as slight resize, compression or illumination adjustments.
- Alternative baselines: Compare with raw gradient saliency, occlusion sensitivity, CAM-style methods or another appropriate attribution family.
- Layer sensitivity: Assess whether chosen layers create sensible maps and whether coarse spatial resolution hides important distinctions.
- Failure-case evaluation: Do not select only visually impressive examples; assess difficult classes, rare inputs, model mistakes and low-confidence cases.
Adebayo et al., *Sanity Checks for Saliency Maps* (NeurIPS 2018), showed why aesthetically plausible explanation maps may not adequately depend on learned parameters or training data. Grad-CAM does not automatically pass every faithfulness/robustness criterion just because it uses gradients.
Caution about perturbation metrics: Removing the pixels with highest heatmap values may change the data distribution or remove correlated context, so score changes support a particular experiment—not a proof of a universal causal explanation.
11. Limitations and frequent mistakes
- Treating heatmap pixels as a segmentation mask: A 7×7 feature map upsampled to 224×224 is still fundamentally coarse.
- Using softmax probability instead of the chosen logit unintentionally: Softmax coupling and saturation can change gradients and interpretations.
- Using `no_grad` or inference mode: Grad-CAM needs autograd during a backward pass, even for an evaluation model.
- Hooking a non-spatial layer: Fully connected outputs or pooled [N,C] tensors lack the H×W grid required by standard Grad-CAM.
- Misidentifying the target class: The predicted class is not always the class an engineer wants to explain; accept an explicit class index.
- Using unnormalized/preprocessed inputs inconsistently: Align the heatmap with the correct original display image and preprocessing crop.
- Assuming brighter means more certain: Heatmaps are normalized relative attributions, not output probabilities.
- Interpreting all zeros as absence of relevance: ReLU can suppress negative evidence and cancellations.
- Confusing Grad-CAM with attention weights: Grad-CAM comes from gradients and convolutional features; its values are not intrinsic Transformer attention probabilities.
- Explaining random or untrained weights: A map can be numerically generated even when the network has learned nothing useful.
- Ignoring in-place operations and hook lifetime: Hooks can conflict with in-place activation updates; leaked hooks may corrupt later results.
- Assuming every spatial area is independently causal: Neighboring convolutional receptive fields overlap; a highlighted region may depend on distant context.
- Overinterpreting color: A colormap and transparency can alter visual impressions without changing model attribution.
- Claiming explanation validates correctness or fairness: Grad-CAM can suggest hypotheses but cannot alone establish fairness, robustness, causality or medical reliability.
12. Curriculum boundaries and key takeaway
- Question 297 covered quantization-aware training, preparing a model for integer inference.
- Question 298 covered pruning, removing individual weights versus structural units.
- Question 299 covered knowledge distillation, learning a student from a teacher's outputs and features.
- Question 300 covers post-hoc CNN explanation through gradient-weighted convolutional feature maps. It neither changes network architecture nor compresses or retrains the model.
This is Question 300, the last item in the established MachinoAI Advanced Deep Learning questions 201–300 proposal. Any future supplemental lessons should be separately verified and semantically deduplicated rather than assumed to be Question 301 in that original curriculum.
Key takeaway: Grad-CAM calculates gradients of a target class score at a spatial convolutional layer, globally averages those gradients to obtain channel weights, sums the weighted feature maps, and applies ReLU to form a class-specific coarse heatmap. It is valuable for debugging model associations, but should be checked against perturbations and baselines and never treated as proof of causality.
Research and technical references: Selvaraju et al., *Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization* (ICCV 2017); Selvaraju et al., *Grad-CAM* arXiv; PyTorch, *Visualizing Gradients*; PyTorch, *Module Hook API*; Adebayo et al., *Sanity Checks for Saliency Maps* (NeurIPS 2018).
Sources & Research References
Learning Sequence
Deep Learning Curriculum
What does the backpropagation algorithm do in neural networks? What are its drawbacks?
Explore Related Questions
Deepen your understanding across related Deep Learning topics.