Run GradCAM
Step 1 — Load a trained model
import torch
from src.astrovision import build_model, load_galaxy10_splits
model = build_model('efficientnet')
model.load_state_dict(torch.load('checkpoints/efficientnet_galaxy10_finetune_best.pt', map_location='cuda'))
model = model.to('cuda').eval()
Step 2 — Create the explainer
Each CNN exposes its target layer as model.gradcam_target.
from src.astrovision import GradCAM
gcam = GradCAM(model, model.gradcam_target)
Step 3 — One image
_, _, test_loader = load_galaxy10_splits(batch_size=16, num_workers=0)
images, labels = next(iter(test_loader))
heatmap, pred = gcam.compute(images[:1].to('cuda')) # heat map (H, W) in [0, 1] and predicted class
heatmap_true, _ = gcam.compute(images[:1].to('cuda'), class_idx=int(labels[0])) # explain the true class instead
compute expects a normalised (1, 3, H, W) tensor on the model's device and returns the heat map resized to the input size.
Step 4 — A grid of examples
from src.astrovision import plot_gradcam_grid
fig = plot_gradcam_grid(model, gcam, images, labels, device='cuda',
n_samples=8, alpha=0.45, filename='gradcam_grid.png') # saved to figures/
The grid shows original · heat map · overlay, with ✓ / ✗ and the predicted class.
Expected output
A PNG in figures/ with n_samples rows. Compare with the exported EfficientNet figure.
Notes
- Grad-CAM needs gradients: do not wrap
computeintorch.no_grad(). - For the DINOv2 classifier, use the attention maps of Attention & Grad-CAM (
attention_morphometry.extract_attention_map); the README example hooksmodel.backbone.blocks[-1].norm1, which is not a convolutional layer.
Related pages