import numpy as np from pytorch_grad_cam.base_cam import BaseCAM # https://arxiv.org/abs/1710.11063 class GradCAMPlusPlus(BaseCAM): def __init__(self, model, target_layers, use_cuda=False, reshape_transform=None): super(GradCAMPlusPlus, self).__init__(model, target_layers, use_cuda, reshape_transform) def get_cam_weights(self, input_tensor, target_layers, target_category, activations, grads): grads_power_2 = grads**2 grads_power_3 = grads_power_2 * grads # Equation 19 in https://arxiv.org/abs/1710.11063 sum_activations = np.sum(activations, axis=(2, 3)) eps = 0.000001 aij = grads_power_2 / (2 * grads_power_2 + sum_activations[:, :, None, None] * grads_power_3 + eps) # Now bring back the ReLU from eq.7 in the paper, # And zero out aijs where the activations are 0 aij = np.where(grads != 0, aij, 0) weights = np.maximum(grads, 0) * aij weights = np.sum(weights, axis=(2, 3)) return weights