AI_MRI / scripts /validation /generate_heatmaps.py
deboraJ23's picture
upload job examples and scripts
011f070 verified
Raw History Blame Contribute Delete
2.96 kB
from pathlib import Path
import torch
import torch.nn as nn
import torchio as tio
import matplotlib.pyplot as plt
import numpy as np
from auto_detect_breast_mri.config import resolve_path
from auto_detect_breast_mri.models.resnets import model_names
from auto_detect_breast_mri.data.breast_mri_dataset import BreastMRISubjects
# Paths come from the site config (see config.example.yaml).
path_base = resolve_path(None, "data_root", "root folder of the NIfTI data")
split_root = resolve_path(None, "split_root", "folder holding the split files")
model_root = resolve_path(None, "model_root", "folder holding the checkpoints", required=False) \
or resolve_path(None, "output_root", "folder holding the checkpoints")
batch_size = 1
pre_image_shape = (32, 512, 512)
heatmap_size = (32, 256, 256)
# Get Model
model_name = 'resnet18_abrv'
protocol = ['Dyn_0', 'Sub_1']
model_path = str(Path(model_root) / "malignity_{}.pth".format(model_name))
model = model_names.get(model_name)
checkpoint = torch.load(model_path)
model.load_state_dict(checkpoint)
model.eval()
# Register forward hook
target_layer = model.layer4[-1] # Choose the target layer
activation = {}
def get_activation(name):
def hook(model, input, output):
activation[name] = output.detach()
return hook
target_layer.register_forward_hook(get_activation('target_layer'))
# forward pass
data_set = BreastMRISubjects(path_base, str(Path(split_root) / "fold0" / "stratified_evaluation_set-f0-0.csv"),
protocol=protocol)
data_loader = tio.SubjectsLoader(data_set, batch_size=batch_size, shuffle=False, num_workers=16)
for batch_id, batch in enumerate(data_loader):
data = batch['image']['data']
ground_truth = batch['label']
path = batch['path']
output = model(data)
# Calculate gradients
model.zero_grad()
one_hot = torch.zeros_like(output)
one_hot[0, output.argmax()] = 1.0
output.backward(gradient=one_hot, retain_graph=True)
# Weighted sum of feature maps
grads = activation['target_layer'].grad.mean(dim=(2, 3), keepdim=True)
heatmap = torch.sum(grads * activation['target_layer'], dim=1, keepdim=True)
heatmap = nn.functional.relu(heatmap)
# Resize the heatmap to match the original image size
heatmap = nn.functional.interpolate(heatmap, size=heatmap_size, mode="bilinear", align_corners=False)
heatmap = heatmap / heatmap.max() # Normalize
heatmap = heatmap.squeeze().numpy() # transform to numpy array
# Display the original image and Grad-CAM heatmap
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(np.transpose(data[0, 0, 16].squeeze().numpy(), (1, 2, 0)))
plt.title('Original Image')
plt.subplot(1, 2, 2)
plt.imshow(heatmap[0, 0, 16], cmap='viridis') # TODO maybe only 0, 16 ?
plt.title('Grad-CAM Heatmap')
plt.show()