A saliency map scores every pixel independently — 36 separate numbers for a 6×6 image. Grad-CAM — short for Gradient-weighted Class Activation Mapping — asks a coarser, more targeted question instead: which regions did the convolution layer's own feature map actually rely on, for this specific class?
This is the same minimal CNN (short for Convolutional Neural Network)'s 4×4 feature map after ReLU (short for Rectified Linear Unit) — the exact tensor that gets pooled and fed to the dense layer. Grad-CAM reweights this map by how much each of its cells actually mattered to the predicted class, then clips anything left negative to zero.
Grad-CAM has two steps. First, weight each feature-map channel by how much it mattered to class 's logit — averaging that channel's gradient over every spatial location:
- — the weight for channel : how much that channel matters to class 's logit.
- — the feature map's height and width, i.e. its number of spatial locations.
- — class 's logit, the model's raw output score for that class.
- — the feature map's activation for channel at spatial location .
- — the index over feature-map channels.
- — the class being explained.
Then combine the channels using those weights, and clip to only the positive evidence:
- — the final heatmap for class : a weighted, positive-only combination of the feature-map channels.
- With one filter, one channel weight
With only one convolution filter, there's just one channel , so collapses to a single number.
- But that number still depends on the class
That single number still depends on which class you ask about, which is exactly what makes Grad-CAM class-discriminative instead of a fixed, class-blind map.
Switch classes. The weight flips from to — same feature map, opposite sign — because "Edge detected" and "No edge" read the identical evidence with opposite-signed dense weights. Watch what that does to the CAM itself once ReLU is applied.
The feature map is in every one of its 4 rows — the same tied activations from the saliency chapter, one level before pooling:
- The channel weight, for each class
Every 2×2 pooling window here is a 4-way tie (all s or all s), so nudging any one cell up by makes it that window's new unique max — the pooled output rises by — while nudging it down by leaves the other three tied cells still winning, so the pooled output doesn't move at all. That one-sided response is what the numerical gradient picks up:
- For "Edge detected" (dense weight on every flattened position), one cell's plus-side logit rises by while its minus-side logit is unchanged, giving gradient for every cell (the same tie-breaking happens in every window). Averaging 16 identical s over all 16 cells just gives back , so .
- For "No edge"'s dense weight, the same argument gives everywhere instead, so .
- Grad-CAM for 'Edge detected'
— the two right-hand columns, exactly where the edge evidence lives.
- Grad-CAM for 'No edge'
— completely zero. There's no region of this image that positively supports "no edge," so ReLU throws all of it away.
Pick the class whose Grad-CAM has no positive evidence anywhere — every cell exactly zero.
Grad-CAM trades saliency's pixel-level precision for something a real, many-channel CNN needs: a way to ask "where, and for which class." In a network with hundreds of filters, most channels are irrelevant to any one class — the weighting step is what picks out the handful that actually matter, before painting a coarse heatmap back onto the image. The next two chapters leave images behind entirely and explain a prediction the same way regardless of what kind of model produced it.