| import torch | |
| import tqdm | |
| from pytorch_grad_cam.base_cam import BaseCAM | |
| class ScoreCAM(BaseCAM): | |
| def __init__( | |
| self, | |
| model, | |
| target_layers, | |
| use_cuda=False, | |
| reshape_transform=None): | |
| super(ScoreCAM, self).__init__(model, | |
| target_layers, | |
| use_cuda, | |
| reshape_transform=reshape_transform, | |
| uses_gradients=False) | |
| def get_cam_weights(self, | |
| input_tensor, | |
| target_layer, | |
| targets, | |
| activations, | |
| grads): | |
| with torch.no_grad(): | |
| upsample = torch.nn.UpsamplingBilinear2d( | |
| size=input_tensor.shape[-2:]) | |
| activation_tensor = torch.from_numpy(activations) | |
| if self.cuda: | |
| activation_tensor = activation_tensor.cuda() | |
| upsampled = upsample(activation_tensor) | |
| maxs = upsampled.view(upsampled.size(0), | |
| upsampled.size(1), -1).max(dim=-1)[0] | |
| mins = upsampled.view(upsampled.size(0), | |
| upsampled.size(1), -1).min(dim=-1)[0] | |
| maxs, mins = maxs[:, :, None, None], mins[:, :, None, None] | |
| upsampled = (upsampled - mins) / (maxs - mins) | |
| input_tensors = input_tensor[:, None, | |
| :, :] * upsampled[:, :, None, :, :] | |
| if hasattr(self, "batch_size"): | |
| BATCH_SIZE = self.batch_size | |
| else: | |
| BATCH_SIZE = 16 | |
| scores = [] | |
| for target, tensor in zip(targets, input_tensors): | |
| for i in tqdm.tqdm(range(0, tensor.size(0), BATCH_SIZE)): | |
| batch = tensor[i: i + BATCH_SIZE, :] | |
| outputs = [target(o).cpu().item() | |
| for o in self.model(batch)] | |
| scores.extend(outputs) | |
| scores = torch.Tensor(scores) | |
| scores = scores.view(activations.shape[0], activations.shape[1]) | |
| weights = torch.nn.Softmax(dim=-1)(scores).numpy() | |
| return weights | |