-
Notifications
You must be signed in to change notification settings - Fork 2
/
integrated-gradient.py
112 lines (102 loc) · 5.2 KB
/
integrated-gradient.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import numpy as np
import torch
from torchvision import models
import cv2
import torch.nn.functional as F
from visualization import visualize
from models.DenseNet import initialize_model as DenseNet
from models.AttentionDenseNet import initialize_model as Attention_DenseNet
import argparse
import os
def calculate_outputs_and_gradients(inputs, model, target_label_idx, cuda=True):
# do the pre-processing
predict_idx = None
gradients = []
for input in inputs:
input = pre_processing(input, cuda)
output = model(input)
output = F.softmax(output, dim=1)
if target_label_idx is None:
target_label_idx = torch.argmax(output, 1).item()
index = np.ones((output.size()[0], 1)) * target_label_idx
index = torch.tensor(index, dtype=torch.int64)
if cuda:
index = index.cuda()
output = output.gather(1, index)
# clear grad
model.zero_grad()
output.backward()
gradient = input.grad.detach().cpu().numpy()[0]
gradients.append(gradient)
gradients = np.array(gradients)
return gradients, target_label_idx
def pre_processing(obs, cuda):
mean = np.array([0.485, 0.456, 0.406]).reshape([1, 1, 3])
std = np.array([0.229, 0.224, 0.225]).reshape([1, 1, 3])
obs = obs / 255
obs = (obs - mean) / std
obs = np.transpose(obs, (2, 0, 1))
obs = np.expand_dims(obs, 0)
obs = np.array(obs)
if cuda:
torch_device = torch.device('cuda:0')
else:
torch_device = torch.device('cpu')
obs_tensor = torch.tensor(obs, dtype=torch.float32, device=torch_device, requires_grad=True)
return obs_tensor
# generate the entire images
def generate_entrie_images(img_origin, img_grad, img_grad_overlay, img_integrad, img_integrad_overlay):
blank = np.ones((img_grad.shape[0], 10, 3), dtype=np.uint8) * 255
blank_hor = np.ones((10, 20 + img_grad.shape[0] * 3, 3), dtype=np.uint8) * 255
upper = np.concatenate([img_origin[:, :, (2, 1, 0)], blank, img_grad_overlay, blank, img_grad], 1)
down = np.concatenate([img_origin[:, :, (2, 1, 0)], blank, img_integrad_overlay, blank, img_integrad], 1)
total = np.concatenate([upper, blank_hor, down], 0)
total = cv2.resize(total, (550, 364))
return total
# integrated gradients
def integrated_gradients(inputs, model, target_label_idx, predict_and_gradients, baseline, steps=50, cuda=False):
if baseline is None:
baseline = 0 * inputs
# scale inputs and compute gradients
scaled_inputs = [baseline + (float(i) / steps) * (inputs - baseline) for i in range(0, steps + 1)]
grads, _ = predict_and_gradients(scaled_inputs, model, target_label_idx, cuda)
avg_grads = np.average(grads[:-1], axis=0)
avg_grads = np.transpose(avg_grads, (1, 2, 0))
delta_X = (pre_processing(inputs, cuda) - pre_processing(baseline, cuda)).detach().squeeze(0).cpu().numpy()
delta_X = np.transpose(delta_X, (1, 2, 0))
integrated_grad = delta_X * avg_grads
return integrated_grad
def random_baseline_integrated_gradients(inputs, model, target_label_idx, predict_and_gradients, steps, num_random_trials, cuda):
all_intgrads = []
for i in range(num_random_trials):
integrated_grad = integrated_gradients(inputs, model, target_label_idx, predict_and_gradients, \
baseline=255.0 *np.random.random(inputs.shape), steps=steps, cuda=cuda)
all_intgrads.append(integrated_grad)
print('the trial number is: {}'.format(i))
avg_intgrads = np.average(np.array(all_intgrads), axis=0)
return avg_intgrads
if __name__ == '__main__':
# start to create models...
num_classes = 5
model, input_size = DenseNet(num_classes = num_classes)
model.load_state_dict(torch.load('weights/model3', map_location=torch.device('cpu')))
model.eval()
# read the image
img = cv2.imread('separated-data/test/im_Dyskeratotic/001.bmp')
mg = cv2.resize(img, (224, 224))
img = img.astype(np.float32)
img = img[:, :, (2, 1, 0)]
# calculate the gradient and the label index
gradients, label_index = calculate_outputs_and_gradients([img], model, None)
gradients = np.transpose(gradients[0], (1, 2, 0))
img_gradient_overlay = visualize(gradients, img, clip_above_percentile=99, clip_below_percentile=0, overlay=True, mask_mode=True)
img_gradient = visualize(gradients, img, clip_above_percentile=99, clip_below_percentile=0, overlay=False)
# calculae the integrated gradients
attributions = random_baseline_integrated_gradients(img, model, label_index, calculate_outputs_and_gradients, \
steps=50, num_random_trials=10, cuda=True)
img_integrated_gradient_overlay = visualize(attributions, img, clip_above_percentile=99, clip_below_percentile=0, \
overlay=True, mask_mode=True)
img_integrated_gradient = visualize(attributions, img, clip_above_percentile=99, clip_below_percentile=0, overlay=False)
output_img = generate_entrie_images(img, img_gradient, img_gradient_overlay, img_integrated_gradient, \
img_integrated_gradient_overlay)
cv2.imwrite('vis_densenet', np.uint8(output_img))