|
a |
|
b/PathCNN_GradCAM.py |
|
|
1 |
import os |
|
|
2 |
import pandas as pd |
|
|
3 |
import numpy as np |
|
|
4 |
import keras.backend as K |
|
|
5 |
import keras |
|
|
6 |
import cv2 |
|
|
7 |
|
|
|
8 |
from keras.models import load_model |
|
|
9 |
|
|
|
10 |
def grad_cam(model, category_index, layer_name): |
|
|
11 |
print(layer_name) |
|
|
12 |
|
|
|
13 |
inp = model.input |
|
|
14 |
y_c = model.output.op.inputs[0][0, category_index] |
|
|
15 |
A_k = model.get_layer(layer_name).output |
|
|
16 |
print(y_c, A_k) |
|
|
17 |
|
|
|
18 |
get_output = K.function( |
|
|
19 |
[inp], [A_k, K.gradients(y_c, A_k)[0], model.output]) |
|
|
20 |
|
|
|
21 |
return get_output |
|
|
22 |
|
|
|
23 |
|
|
|
24 |
def apply_grad_cam(get_output, input): |
|
|
25 |
input_image = input[0] |
|
|
26 |
|
|
|
27 |
[conv_output, grad_val, model_output] = get_output(input) |
|
|
28 |
|
|
|
29 |
conv_output = conv_output[0] |
|
|
30 |
grad_val = grad_val[0] |
|
|
31 |
|
|
|
32 |
weights = np.mean(grad_val, axis=(0, 1)) |
|
|
33 |
|
|
|
34 |
grad_cam = np.zeros(dtype=np.float32, shape=conv_output.shape[0:2]) |
|
|
35 |
for k, w in enumerate(weights): |
|
|
36 |
grad_cam += w * conv_output[:, :, k] |
|
|
37 |
|
|
|
38 |
grad_cam = np.maximum(grad_cam, 0) |
|
|
39 |
heatmap = grad_cam/np.max(grad_cam) |
|
|
40 |
|
|
|
41 |
image = input_image.squeeze() |
|
|
42 |
image -= np.min(image) |
|
|
43 |
image = 255 * image / np.max(image) |
|
|
44 |
image1 = cv2.resize(cv2.cvtColor(image.astype(np.uint8), cv2.COLOR_GRAY2RGB), (240, 1460), |
|
|
45 |
interpolation=cv2.INTER_NEAREST) |
|
|
46 |
|
|
|
47 |
print(np.percentile(heatmap/np.max(heatmap), [0, 25, 50, 75, 100])) |
|
|
48 |
heatmap1 = cv2.resize(heatmap/np.max(heatmap), |
|
|
49 |
(240, 1460), interpolation=cv2.INTER_LINEAR) |
|
|
50 |
|
|
|
51 |
grad_cam = cv2.applyColorMap(np.uint8(255*heatmap1), cv2.COLORMAP_JET) |
|
|
52 |
grad_cam = np.float32(grad_cam) + np.float32(image1) |
|
|
53 |
grad_cam = 255 * grad_cam / np.max(grad_cam) |
|
|
54 |
|
|
|
55 |
return np.uint8(grad_cam), heatmap |
|
|
56 |
|
|
|
57 |
|
|
|
58 |
pca_exp = pd.read_excel("data/PCA_EXP.xlsx", header=None) |
|
|
59 |
pca_cnv = pd.read_excel("data/PCA_CNV.xlsx", header=None) |
|
|
60 |
pca_mt = pd.read_excel("data/PCA_MT.xlsx", header=None) |
|
|
61 |
clinical = pd.read_excel("data/Clinical.xlsx") |
|
|
62 |
|
|
|
63 |
# data size: 146 pathways, 5 PCs |
|
|
64 |
n = len(pca_exp) # sample size: number of Pts |
|
|
65 |
path_n = 146 # number of pathways |
|
|
66 |
pc = 5 # number of PCs |
|
|
67 |
|
|
|
68 |
# data creation-EXP |
|
|
69 |
pca_exp = pca_exp.to_numpy() |
|
|
70 |
print(pca_exp.shape) |
|
|
71 |
exp_data = np.zeros((n, path_n, pc)) |
|
|
72 |
for i in range(n): |
|
|
73 |
for j in range(path_n): |
|
|
74 |
exp_data[i, j, :] = pca_exp[i, j * pc:(j + 1) * pc] |
|
|
75 |
|
|
|
76 |
# data creation-CNV |
|
|
77 |
pca_cnv = pca_cnv.to_numpy() |
|
|
78 |
cnv_data = np.zeros((n, path_n, pc)) |
|
|
79 |
for i in range(n): |
|
|
80 |
for j in range(path_n): |
|
|
81 |
cnv_data[i, j, :] = pca_cnv[i, j * pc:(j + 1) * pc] |
|
|
82 |
|
|
|
83 |
# data creation-MT |
|
|
84 |
pca_mt = pca_mt.to_numpy() |
|
|
85 |
mt_data = np.zeros((n, path_n, pc)) |
|
|
86 |
for i in range(n): |
|
|
87 |
for j in range(path_n): |
|
|
88 |
mt_data[i, j, :] = pca_mt[i, j * pc:(j + 1) * pc] |
|
|
89 |
|
|
|
90 |
# data merge: mRNA expression, CNV, and MT with a specific number of PCs |
|
|
91 |
no_pc = 2 # use the first 2 PCs among 5 PCs |
|
|
92 |
all_data = np.zeros((n, path_n, no_pc * 3)) |
|
|
93 |
for i in range(n): |
|
|
94 |
all_data[i, :, :] = np.concatenate((exp_data[i, :, 0:no_pc], cnv_data[i, :, 0:no_pc], mt_data[i, :, 0:no_pc]), |
|
|
95 |
axis=1) |
|
|
96 |
|
|
|
97 |
index = np.arange(0, pca_exp.shape[1], pc) |
|
|
98 |
|
|
|
99 |
clinical = clinical.to_numpy() |
|
|
100 |
survival = clinical[:, 5] |
|
|
101 |
os_months = clinical[:, 6] |
|
|
102 |
idx0 = np.where((survival == 1) & (os_months <= 24)) # class0 |
|
|
103 |
idx1 = np.where(os_months > 24) # class1 |
|
|
104 |
|
|
|
105 |
all_data = all_data[:, :, :] |
|
|
106 |
|
|
|
107 |
data_0 = all_data[idx0, :, :] |
|
|
108 |
data_0 = data_0[0, :, :, :] |
|
|
109 |
data_1 = all_data[idx1, :, :] |
|
|
110 |
data_1 = data_1[0, :, :, :] |
|
|
111 |
|
|
|
112 |
outcomes_0 = np.zeros(len(idx0[0])) |
|
|
113 |
outcomes_1 = np.ones(len(idx1[0])) |
|
|
114 |
|
|
|
115 |
# data merge |
|
|
116 |
data = np.concatenate((data_0, data_1)) |
|
|
117 |
outcomes = np.concatenate((outcomes_0, outcomes_1)) |
|
|
118 |
|
|
|
119 |
print('test') |
|
|
120 |
event_rate = np.array( |
|
|
121 |
[outcomes_0.shape[0], outcomes_1.shape[0]])/outcomes_0.shape[0] |
|
|
122 |
print(event_rate) |
|
|
123 |
|
|
|
124 |
vmin = -10 |
|
|
125 |
vmax = 10 |
|
|
126 |
m = 1 |
|
|
127 |
|
|
|
128 |
model_file = 'PathCNN_model.h5' |
|
|
129 |
|
|
|
130 |
model = load_model(model_file) |
|
|
131 |
layers = model.layers |
|
|
132 |
print(model.summary()) |
|
|
133 |
|
|
|
134 |
orig_weights = model.get_weights().copy() |
|
|
135 |
|
|
|
136 |
output_layer = model.get_layer('dense_2') |
|
|
137 |
output_weights = output_layer.get_weights() |
|
|
138 |
print(output_weights[1]) |
|
|
139 |
|
|
|
140 |
col = ['outcome', 'prediction', 'target_class', |
|
|
141 |
'probability']+list(range(1, no_pc*path_n*3+1)) |
|
|
142 |
print(col) |
|
|
143 |
|
|
|
144 |
layer = layers[4] # the last layer before flatten |
|
|
145 |
print(layer.name) |
|
|
146 |
weights = layer.get_weights() |
|
|
147 |
|
|
|
148 |
get_output = [None, None] |
|
|
149 |
for target_class in range(2): |
|
|
150 |
get_output[target_class] = grad_cam(model, target_class, layer.name) |
|
|
151 |
|
|
|
152 |
os.makedirs('output/'+layer.name, exist_ok=True) |
|
|
153 |
for i in range(0, data.shape[0], 1): |
|
|
154 |
oimg = data[i, :, :] |
|
|
155 |
|
|
|
156 |
print(f'\ncase {i:03d}_{outcomes[i]:.0f}') |
|
|
157 |
print(oimg.shape) |
|
|
158 |
|
|
|
159 |
img = ((np.clip(oimg, vmin, vmax) - vmin) / |
|
|
160 |
(vmax - vmin) * 255).astype('uint8') |
|
|
161 |
|
|
|
162 |
timg = oimg.reshape(1, oimg.shape[0], oimg.shape[1], 1) |
|
|
163 |
|
|
|
164 |
preprocessed_input = [timg] |
|
|
165 |
|
|
|
166 |
model.set_weights(orig_weights) |
|
|
167 |
predictions = model.predict(preprocessed_input) |
|
|
168 |
print('Predicted class:') |
|
|
169 |
print(predictions) |
|
|
170 |
predicted_class = np.argmax(predictions) |
|
|
171 |
print(predicted_class) |
|
|
172 |
|
|
|
173 |
for target_class in range(2): |
|
|
174 |
gradcam, heatmap = apply_grad_cam(get_output[target_class], preprocessed_input) |
|
|
175 |
filename = f'output/{layer.name}/gradcam{i:03d}_{outcomes[i]:.0f}_{predicted_class:d}_{target_class:d}_{predictions[0][target_class]:0.2f}.png' |
|
|
176 |
cv2.imwrite(filename, gradcam) |
|
|
177 |
|
|
|
178 |
heatmap1 = cv2.resize(heatmap, (no_pc*3, path_n)) |
|
|
179 |
#print(heatmap.shape) |
|
|
180 |
data_row = [[outcomes[i], predicted_class, target_class, |
|
|
181 |
predictions[0][target_class]]+heatmap1.flatten().tolist()] |
|
|
182 |
gradcam_pd = pd.DataFrame(data_row, columns=col, index=[i]) |
|
|
183 |
if i == 0 and target_class == 0: |
|
|
184 |
gradcam_pd.to_csv( |
|
|
185 |
f'output/{layer.name}/pathcnn_gradcam.csv', mode='w') |
|
|
186 |
else: |
|
|
187 |
gradcam_pd.to_csv(f'output/{layer.name}/pathcnn_gradcam.csv', |
|
|
188 |
mode='a', header=False) |