Model or dataset
frgfm/torch-cam avatar
frgfm/torch-cam

TorchCAM: one wrapper, twelve class activation methods for PyTorch

Class activation maps for your PyTorch models (CAM, Grad-CAM, Grad-CAM++, Smooth Grad-CAM++, Score-CAM, SS-CAM, IS-CAM, XGrad-CAM, Layer-CAM, Finer-CAM, LeGrad, RefineCAM)

2,305 stars227 forksPythonApache-2.0

At a glance

What is it?
TorchCAM attaches PyTorch forward and backward hooks to a model you already trained and returns class activation maps from a chosen layer. It is a debugging library, not a training library, and the documentation is explicit about where the hooks stop working.
Who is it for?
Adopt TorchCAM if you already have a trained PyTorch classifier and need per-class heatmaps for a handful of surprising predictions, and if you are willing to read the advanced usage and troubleshooting pages before filing an issue about a blank map or a hook registration error.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem TorchCAM addresses: reading a classifier's mind one prediction at a time

A trained image classifier returns logits. It does not tell you which pixels pushed a logit up. TorchCAM exists to close that gap without asking you to modify the model definition, retrain, or write your own backward hooks. The README frames the library as a "simple way to leverage the class-specific activation of convolutional and transformer layers in PyTorch", and the primary use case it names is concrete: "Debugging one surprising classifier result?" The target reader is someone who already has a model in hand and a prediction that looks wrong, not someone building a general interpretability research platform. The package ships twelve named methods in the description (CAM, Grad-CAM, Grad-CAM++, Smooth Grad-CAM++, Score-CAM, SS-CAM, IS-CAM, XGrad-CAM, Layer-CAM, Finer-CAM, LeGrad, RefineCAM), and the README points to an exhaustive list under the documentation's methods reference. That breadth matters because the methods disagree with each other. A Grad-CAM map and a Score-CAM map of the same image and the same layer can highlight different regions, and having them behind one interface is the practical value here.

How the hook wrapper works, and why the layer choice is the real decision

Each CAM object is a wrapper around your model. The README states that TorchCAM "leverages PyTorch hooking mechanisms to seamlessly retrieve all required information to produce the class activation without additional efforts from the user". In practice that means you construct the extractor with a model, then run inference as you normally would. The extractor intercepts the forward activations and, for gradient-based methods, the backward pass, and it returns the map when you call it with a class index and the model output. The default target layer is documented as "the last non-reduced convolutional layer", which is a sensible default for a ResNet-style backbone and a poor one for anything else. The constructor accepts a target_layer argument when you want a different layer, and the advanced usage guide is where the README sends you for choosing it. This is the design's honest limitation: the library automates the plumbing, not the judgement. Picking the wrong layer produces a map that is technically valid and analytically useless. The README's own advanced usage tip groups target_layer selection together with Vision Transformers, 3D and video data, and batched inputs, which suggests these are the cases where the default assumption breaks first.

Getting a heatmap out of a torchvision ResNet-18

The README gives a complete path. Install the package, then wrap the model. The example uses torchvision's newer get_model and get_model_weights API with LayerCAM:

model = get_model("resnet18", weights=get_model_weights("resnet18").DEFAULT).eval() cam_extractor = LayerCAM(model)

Inference stays unchanged. The extractor is used as a context manager, and the map is retrieved by passing the class index and the output:

with LayerCAM(model) as cam_extractor: out = model(input_tensor.unsqueeze(0)) activation_map = cam_extractor(out.squeeze(0).argmax().item(), out)

The README notes that the first argument is the index in the model's output logits of the class you want to explain, and that argmax is only a convenience for the top prediction. The extractor "returns one activation map per target layer", so the calling code indexes activation_map[0]. Visualization is left to matplotlib and torchcam.utils.overlay_mask, with the README's example passing alpha=0.5 and converting the map with to_pil_image(..., mode='F'). Note the unsqueeze(0) on the input tensor: the example feeds a batch of one, and the advanced usage guide is flagged as the place to look for batched inputs. That detail is easy to miss and is a common source of shape confusion.

Where TorchCAM stops being the right tool

The README's troubleshooting link names the failure modes directly: a "cannot register a hook ..." error, a "requires grad" error, a NaN, or a blank heatmap. Those are not exotic edge cases. A hook registration failure typically means the module you named is not in the forward path you are running, or that something else already owns a hook on it. The requires-grad error points at the gradient-based methods needing a backward pass that your inference code may have disabled under torch.no_grad() or on a frozen or quantized model. A blank heatmap can come from a layer whose activations were reduced to nothing useful, which loops back to target_layer selection. The v0.4.1 release note mentions "Cleaner hooks control for CAM extractors", which implies the hook lifecycle was reworked; if your own code registers hooks on the same modules, that is worth checking against the release notes. The broader limitation is scope: TorchCAM produces maps. It does not tell you whether a map is correct, and the evaluation metrics that arrived in v0.4.0 are a starting point rather than a settled answer to that question. If you need to compare methods quantitatively across a dataset, you are building that harness yourself.

How TorchCAM differs from Captum and from hand-rolled hooks

Captum is the obvious alternative, and the difference is in the abstraction. Captum exposes attribution algorithms as functions over a model and an input, with its own notions of baselines, internal batch sizes, and layer attribution variants; you call it per input and it manages the forward and backward passes. TorchCAM inverts that: the extractor is constructed once around the model and persists, the model's own forward call drives everything, and the map is fetched afterward by class index. That makes TorchCAM fit naturally into existing inference code, including code you did not write, because you are not restructuring the forward pass. The cost is that TorchCAM's correctness depends on your model's call pattern matching its hook expectations, which is exactly where the troubleshooting page says things go wrong. Hand-rolled hooks give you total control and zero dependency, but you reimplement the per-method math for each of the twelve methods, and the README's example image was produced with a pretrained ResNet-18, which is the well-trodden path where any of these approaches works.

Maintenance, versioning and the Apache-2.0 terms

The release cadence visible here is uneven. v0.3.2 landed in August 2022, v0.4.0 in October 2023 with evaluation metrics and PyTorch 2.0 support, and v0.4.1 in October 2025 with the hook control changes. The repository's last push date is later than the last release, so work is happening between releases. That pattern means you should pin a version rather than track main, and read the release notes before moving between minor versions, because the v0.4.1 hook changes are the kind that can interact with code outside the library. The project is Apache-2.0 licensed, which permits commercial and closed-source use and includes an explicit patent grant, with the usual requirements around preserving notices and stating changes. That is a description of the licence text, not legal advice; if you are shipping TorchCAM inside a product, have your own counsel read the NOTICE and attribution requirements. The README also links a Hugging Face Space and a Colab notebook, which are useful for a first look before you install anything locally.

Editorial conclusion

Adopt TorchCAM if you already have a trained PyTorch classifier and need per-class heatmaps for a handful of surprising predictions, and if you are willing to read the advanced usage and troubleshooting pages before filing an issue about a blank map or a hook registration error. Do not adopt it if you need a maintained evaluation harness for comparing explanation methods at scale, or if your model's forward pass does not expose a convolutional or transformer layer you can name. Before writing it into a pipeline, verify three things: that your chosen target_layer actually receives gradients for the class index you pass, that your inputs are either single or properly batched for the method you picked, and that the 0.4.x hook control changes in v0.4.1 do not conflict with any hooks your own code already registers on the same module.

Official sources

  1. frgfm/torch-cam on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes