|
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 |
|
|