|
a |
|
b/utils.py |
|
|
1 |
import pandas as pd |
|
|
2 |
import numpy as np |
|
|
3 |
from sklearn import metrics |
|
|
4 |
from sklearn.metrics import confusion_matrix, classification_report, average_precision_score, precision_recall_curve, accuracy_score, confusion_matrix, average_precision_score |
|
|
5 |
|
|
|
6 |
|
|
|
7 |
|
|
|
8 |
def episode_metrics(model, x, parameters, rhythm, out_message=False): |
|
|
9 |
""" arg |
|
|
10 |
|
|
|
11 |
""" |
|
|
12 |
# Rhythmn predictions |
|
|
13 |
predictions_qa, predictions_r = model.predict(x) |
|
|
14 |
# If the estimated prob of AF(column 1) is higher than the estimated prob of non-AF(column 0) |
|
|
15 |
# than consider the window as an AF window. |
|
|
16 |
y_predictions = np.argmax(predictions_r, axis=1) |
|
|
17 |
y_truth = np.argmax(rhythm, axis=1) |
|
|
18 |
# Confusion_matrix |
|
|
19 |
cf = confusion_matrix(y_truth, y_predictions, labels=[0, 1]) |
|
|
20 |
TN, FP, FN, TP = cf.ravel() |
|
|
21 |
support = TN+FP+FN+TP |
|
|
22 |
# Sensitivity, recall, or true positive rate |
|
|
23 |
TPR = TP/(TP+FN) |
|
|
24 |
# Specificity or true negative rate |
|
|
25 |
TNR = TN/(TN+FP) |
|
|
26 |
# Precision or positive predictive value |
|
|
27 |
PPV = TP/(TP+FP) |
|
|
28 |
# Negative predictive value |
|
|
29 |
NPV = TN/(TN+FN) |
|
|
30 |
# Fall out or false positive rate |
|
|
31 |
FPR = FP/(FP+TN) |
|
|
32 |
# False negative rate |
|
|
33 |
FNR = FN/(TP+FN) |
|
|
34 |
# F1 score |
|
|
35 |
f1 = metrics.f1_score(y_truth, y_predictions, average=None) |
|
|
36 |
# selecting f1score for positive case if present |
|
|
37 |
f1_pos = f1[1] if len(f1) > 1 else f1[0] |
|
|
38 |
# Area under precision recall curve |
|
|
39 |
#auprc = metrics.average_precision_score(y_truth, rhythm[:,1]) |
|
|
40 |
if out_message: |
|
|
41 |
print(pd.DataFrame(cf).rename(columns={0: "Predicted Non-AF", 1:" Predicted AF"}, index={0: "True Non-AF", 1:"True AF"})) |
|
|
42 |
print("Sensitivity/Recall: %0.4f" % TPR) |
|
|
43 |
print("Specificity: %0.4f" % TNR) |
|
|
44 |
print("Precision/PPV: %0.4f" % PPV) |
|
|
45 |
print("Negative predictive value/NPV: %0.2f" % NPV) |
|
|
46 |
print("False positive rate: %0.4f" % FPR) |
|
|
47 |
print("False negative rate: %0.4f" % FNR) |
|
|
48 |
print("F1 score: %0.4f" % f1_pos) |
|
|
49 |
print('support: ', support) |
|
|
50 |
print('\n\n\n') |
|
|
51 |
episode_metrics = [TPR, TNR, PPV, NPV, FPR, FNR, f1_pos, support] |
|
|
52 |
return episode_metrics |
|
|
53 |
|
|
|
54 |
|
|
|
55 |
def episode_metrics_singletask(model, x, parameters, rhythm, out_message=False): |
|
|
56 |
""" arg |
|
|
57 |
|
|
|
58 |
""" |
|
|
59 |
# Rhythmn predictions |
|
|
60 |
predictions_r = model.predict(x) |
|
|
61 |
# If the estimated prob of AF(column 1) is higher than the estimated prob of non-AF(column 0) |
|
|
62 |
# than consider the window as an AF window. |
|
|
63 |
y_predictions = np.argmax(predictions_r, axis=1) |
|
|
64 |
y_truth = np.argmax(rhythm, axis=1) |
|
|
65 |
# Confusion_matrix |
|
|
66 |
cf = confusion_matrix(y_truth, y_predictions, labels=[0, 1]) |
|
|
67 |
TN, FP, FN, TP = cf.ravel() |
|
|
68 |
support = TN+FP+FN+TP |
|
|
69 |
# Sensitivity, recall, or true positive rate |
|
|
70 |
TPR = TP/(TP+FN) |
|
|
71 |
# Specificity or true negative rate |
|
|
72 |
TNR = TN/(TN+FP) |
|
|
73 |
# Precision or positive predictive value |
|
|
74 |
PPV = TP/(TP+FP) |
|
|
75 |
# Negative predictive value |
|
|
76 |
NPV = TN/(TN+FN) |
|
|
77 |
# Fall out or false positive rate |
|
|
78 |
FPR = FP/(FP+TN) |
|
|
79 |
# False negative rate |
|
|
80 |
FNR = FN/(TP+FN) |
|
|
81 |
# F1 score |
|
|
82 |
f1 = metrics.f1_score(y_truth, y_predictions, average=None) |
|
|
83 |
# selecting f1score for positive case if present |
|
|
84 |
f1_pos = f1[1] if len(f1) > 1 else f1[0] |
|
|
85 |
# Area under precision recall curve |
|
|
86 |
#auprc = metrics.average_precision_score(y_truth, rhythm[:,1]) |
|
|
87 |
if out_message: |
|
|
88 |
print(pd.DataFrame(cf).rename(columns={0: "Predicted Non-AF", 1:" Predicted AF"}, index={0: "True Non-AF", 1:"True AF"})) |
|
|
89 |
print("Sensitivity/Recall: %0.4f" % TPR) |
|
|
90 |
print("Specificity: %0.4f" % TNR) |
|
|
91 |
print("Precision/PPV: %0.4f" % PPV) |
|
|
92 |
print("Negative predictive value/NPV: %0.2f" % NPV) |
|
|
93 |
print("False positive rate: %0.4f" % FPR) |
|
|
94 |
print("False negative rate: %0.4f" % FNR) |
|
|
95 |
print("F1 score: %0.4f" % f1_pos) |
|
|
96 |
print('support: ', support) |
|
|
97 |
print('\n\n\n') |
|
|
98 |
episode_metrics = [TPR, TNR, PPV, NPV, FPR, FNR, f1_pos, support] |
|
|
99 |
return episode_metrics |
|
|
100 |
|
|
|
101 |
|
|
|
102 |
def collecting_individual_metrics(model, x, parameters, rhythm, out_message=False): |
|
|
103 |
""" |
|
|
104 |
""" |
|
|
105 |
individual_metrics = {} |
|
|
106 |
for i in np.unique(parameters['ID']): |
|
|
107 |
# Sub-selecting individuals |
|
|
108 |
p_indx = np.where(parameters['ID'] == i)[0] |
|
|
109 |
x_pID = x[p_indx] |
|
|
110 |
parameters_pID = parameters.iloc[p_indx] |
|
|
111 |
rhythm_pID = rhythm[p_indx] |
|
|
112 |
# Rhythmn predictions |
|
|
113 |
predictions_qa, predictions_r = model.predict(x_pID) |
|
|
114 |
# If the estimated prob of AF(column 1) is higher than the estimated prob of non-AF(column 0) |
|
|
115 |
# than consider the window as an AF window. |
|
|
116 |
y_predictions = np.argmax(predictions_r, axis=1) |
|
|
117 |
y_truth = np.argmax(rhythm_pID, axis=1) |
|
|
118 |
# Confusion_matrix |
|
|
119 |
cf = confusion_matrix(y_truth, y_predictions, labels=[0, 1]) |
|
|
120 |
TN, FP, FN, TP = cf.ravel() |
|
|
121 |
support = TN+FP+FN+TP |
|
|
122 |
# Sensitivity, recall, or true positive rate |
|
|
123 |
TPR = TP/(TP+FN) |
|
|
124 |
# Specificity or true negative rate |
|
|
125 |
TNR = TN/(TN+FP) |
|
|
126 |
# Fall out or false positive rate |
|
|
127 |
FPR = FP/(FP+TN) |
|
|
128 |
# False negative rate |
|
|
129 |
FNR = FN/(TP+FN) |
|
|
130 |
# F1 score |
|
|
131 |
f1 = metrics.f1_score(y_truth, y_predictions, average=None) |
|
|
132 |
# selecting f1score for positive case if present |
|
|
133 |
f1_pos = f1[1] if len(f1) > 1 else f1[0] |
|
|
134 |
# Area under precision recall curve |
|
|
135 |
#auprc = metrics.average_precision_score(y_test_truth, rhythm_pID[:,1]) |
|
|
136 |
if (TP + FN) > 0: |
|
|
137 |
individual_metrics[i] = [TPR, np.NaN, np.NaN, FNR, f1_pos, support] |
|
|
138 |
if (FP + TN) > 0: |
|
|
139 |
individual_metrics[i] = [np.NaN, TNR, FPR, np.NaN, np.NaN, support] |
|
|
140 |
if out_message: |
|
|
141 |
print("PATIENT :", i , '\n') |
|
|
142 |
print(pd.DataFrame(cf).rename(columns={0: "Predicted Non-AF", 1:" Predicted AF"}, index={0: "True Non-AF", 1:"True AF"})) |
|
|
143 |
if (TP + FN) > 0: |
|
|
144 |
print("Sensitivity/Recall: %0.4f" % TPR) |
|
|
145 |
print("False negative rate: %0.4f" % FNR) |
|
|
146 |
print("F1 score: %0.4f" % f1_pos) |
|
|
147 |
print('support: ' , support) |
|
|
148 |
if (FP + TN) > 0: |
|
|
149 |
print("Specificity: %0.4f" % TNR) |
|
|
150 |
print("False positive rate: %0.4f" % FPR) |
|
|
151 |
print('support: ' , support) |
|
|
152 |
return individual_metrics |
|
|
153 |
|
|
|
154 |
def collecting_individual_metrics_singletask(model, x, parameters, rhythm, out_message=False): |
|
|
155 |
""" |
|
|
156 |
""" |
|
|
157 |
individual_metrics = {} |
|
|
158 |
for i in np.unique(parameters['ID']): |
|
|
159 |
# Sub-selecting individuals |
|
|
160 |
p_indx = np.where(parameters['ID'] == i)[0] |
|
|
161 |
x_pID = x[p_indx] |
|
|
162 |
parameters_pID = parameters.iloc[p_indx] |
|
|
163 |
rhythm_pID = rhythm[p_indx] |
|
|
164 |
# Rhythmn predictions |
|
|
165 |
predictions_r = model.predict(x_pID) |
|
|
166 |
# If the estimated prob of AF(column 1) is higher than the estimated prob of non-AF(column 0) |
|
|
167 |
# than consider the window as an AF window. |
|
|
168 |
y_predictions = np.argmax(predictions_r, axis=1) |
|
|
169 |
y_truth = np.argmax(rhythm_pID, axis=1) |
|
|
170 |
# Confusion_matrix |
|
|
171 |
cf = confusion_matrix(y_truth, y_predictions, labels=[0, 1]) |
|
|
172 |
TN, FP, FN, TP = cf.ravel() |
|
|
173 |
support = TN+FP+FN+TP |
|
|
174 |
# Sensitivity, recall, or true positive rate |
|
|
175 |
TPR = TP/(TP+FN) |
|
|
176 |
# Specificity or true negative rate |
|
|
177 |
TNR = TN/(TN+FP) |
|
|
178 |
# Fall out or false positive rate |
|
|
179 |
FPR = FP/(FP+TN) |
|
|
180 |
# False negative rate |
|
|
181 |
FNR = FN/(TP+FN) |
|
|
182 |
# F1 score |
|
|
183 |
f1 = metrics.f1_score(y_truth, y_predictions, average=None) |
|
|
184 |
# selecting f1score for positive case if present |
|
|
185 |
f1_pos = f1[1] if len(f1) > 1 else f1[0] |
|
|
186 |
# Area under precision recall curve |
|
|
187 |
#auprc = metrics.average_precision_score(y_test_truth, rhythm_pID[:,1]) |
|
|
188 |
if (TP + FN) > 0: |
|
|
189 |
individual_metrics[i] = [TPR, np.NaN, np.NaN, FNR, f1_pos, support] |
|
|
190 |
if (FP + TN) > 0: |
|
|
191 |
individual_metrics[i] = [np.NaN, TNR, FPR, np.NaN, np.NaN, support] |
|
|
192 |
if out_message: |
|
|
193 |
print("PATIENT :", i , '\n') |
|
|
194 |
print(pd.DataFrame(cf).rename(columns={0: "Predicted Non-AF", 1:" Predicted AF"}, index={0: "True Non-AF", 1:"True AF"})) |
|
|
195 |
if (TP + FN) > 0: |
|
|
196 |
print("Sensitivity/Recall: %0.4f" % TPR) |
|
|
197 |
print("False negative rate: %0.4f" % FNR) |
|
|
198 |
print("F1 score: %0.4f" % f1_pos) |
|
|
199 |
print('support: ' , support) |
|
|
200 |
if (FP + TN) > 0: |
|
|
201 |
print("Specificity: %0.4f" % TNR) |
|
|
202 |
print("False positive rate: %0.4f" % FPR) |
|
|
203 |
print('support: ' , support) |
|
|
204 |
return individual_metrics |