Computes Gradient-weighted Class Activation Mapping (Grad-CAM). This implementation is based on: Selvaraju et al., Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization, https://arxiv.org/abs/1610.02391 Examples .. code-block:: python
| 317 | |
| 318 | |
| 319 | class GradCAM(CAMBase): |
| 320 | """ |
| 321 | Computes Gradient-weighted Class Activation Mapping (Grad-CAM). |
| 322 | This implementation is based on: |
| 323 | |
| 324 | Selvaraju et al., Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization, |
| 325 | https://arxiv.org/abs/1610.02391 |
| 326 | |
| 327 | Examples |
| 328 | |
| 329 | .. code-block:: python |
| 330 | |
| 331 | import torch |
| 332 | |
| 333 | # densenet 2d |
| 334 | from monai.networks.nets import DenseNet121 |
| 335 | from monai.visualize import GradCAM |
| 336 | |
| 337 | model_2d = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3) |
| 338 | cam = GradCAM(nn_module=model_2d, target_layers="class_layers.relu") |
| 339 | result = cam(x=torch.rand((1, 1, 48, 64))) |
| 340 | |
| 341 | # resnet 2d |
| 342 | from monai.networks.nets import seresnet50 |
| 343 | from monai.visualize import GradCAM |
| 344 | |
| 345 | model_2d = seresnet50(spatial_dims=2, in_channels=3, num_classes=4) |
| 346 | cam = GradCAM(nn_module=model_2d, target_layers="layer4") |
| 347 | result = cam(x=torch.rand((2, 3, 48, 64))) |
| 348 | |
| 349 | N.B.: To help select the target layer, it may be useful to list all layers: |
| 350 | |
| 351 | .. code-block:: python |
| 352 | |
| 353 | for name, _ in model.named_modules(): print(name) |
| 354 | |
| 355 | See Also: |
| 356 | |
| 357 | - :py:class:`monai.visualize.class_activation_maps.CAM` |
| 358 | |
| 359 | """ |
| 360 | |
| 361 | def compute_map(self, x, class_idx=None, retain_graph=False, layer_idx=-1, **kwargs): # type: ignore[override] |
| 362 | _, acti, grad = self.nn_module(x, class_idx=class_idx, retain_graph=retain_graph, **kwargs) |
| 363 | acti, grad = acti[layer_idx], grad[layer_idx] |
| 364 | b, c, *spatial = grad.shape |
| 365 | weights = grad.view(b, c, -1).mean(2).view(b, c, *[1] * len(spatial)) |
| 366 | acti_map = (weights * acti).sum(1, keepdim=True) |
| 367 | return F.relu(acti_map) |
| 368 | |
| 369 | def __call__(self, x, class_idx=None, layer_idx=-1, retain_graph=False, **kwargs): # type: ignore[override] |
| 370 | """ |
| 371 | Compute the activation map with upsampling and postprocessing. |
| 372 | |
| 373 | Args: |
| 374 | x: input tensor, shape must be compatible with `nn_module`. |
| 375 | class_idx: index of the class to be visualized. Default to argmax(logits) |
| 376 | layer_idx: index of the target layer if there are multiple target layers. Defaults to -1. |
no outgoing calls
no test coverage detected
searching dependent graphs…