-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
118 lines (94 loc) · 3.37 KB
/
utils.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
113
114
115
116
117
118
import numpy as np
import datetime
import sklearn.metrics
import torch
import torchvision
class LoopLoader():
def __init__(self,
dset_path,
which, # '['train', 'test', 'val']'
batch_size,
cuda_device
):
self.dset_path = dset_path
self.which = which
self.batch_size = batch_size
self.cuda_device = cuda_device
# For a list of which, we concatenate
self.ds_folder = torch.utils.data.ConcatDataset([torchvision.datasets.DatasetFolder(
root=f"{dset_path}/{split}",
extensions="npy",
loader=gen_loader(self.cuda_device))
for split in which])
self.data_loader = torch.utils.data.DataLoader(
dataset=self.ds_folder,
batch_size=self.batch_size,
drop_last=False,
shuffle=True)
self.reload_iter()
def reload_iter(self):
self.data_loader = torch.utils.data.DataLoader(
dataset=self.ds_folder,
batch_size=self.batch_size,
drop_last=False,
shuffle=True)
self.loader_iter = iter(self.data_loader)
def get_batch(self):
try:
return next(self.loader_iter)
except StopIteration:
self.reload_iter()
return next(self.loader_iter)
def print_time(str):
print(str, '--', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
# Just putting the cuda_device in a closure for the DatasetFolder loader
def gen_loader(cuda_device):
# Load an image, convert it to a tensor with one single channel,
# and send it to the cuda device (GPU/CPU)
def the_loader(path):
# Load the data: a 2D numpy array
ary = np.load(path)
# We need a 3rd dimension for "channels"
ary.shape = (1, *ary.shape) # same as `reshape()` but "inplace"
# Send the tensor to the GPU/CPU depending on what device is available
tensor = torch.from_numpy(ary).to(cuda_device)
return tensor
return the_loader
# Returns a big dictionary with all the metrics
def get_metrics(loss_function, confusion_matrix_dict, predictions_per_batch):
# Get totals
tp = sum(confusion_matrix_dict['TP'])
fp = sum(confusion_matrix_dict['FP'])
tn = sum(confusion_matrix_dict['TN'])
fn = sum(confusion_matrix_dict['FN'])
if tp + fp + tn + fn:
accuracy = (tp + tn) / (tp + fp + tn + fn)
else:
accuracy = 0.0
if tp + fp:
precision = tp / (tp + fp)
else:
precision = 0.0
if tp + fn:
recall = tp / (tp + fn)
else:
recall = 0.0
if precision + recall:
f1score = 2 * ((precision * recall) / (precision + recall))
else:
f1score = 0.0
if tn + fp:
specificity = tn / (tn + fp)
else:
specificity = 0.0
y_true = predictions_per_batch['labels']
y_score = predictions_per_batch['predictions_positive_class']
auc = sklearn.metrics.roc_auc_score(y_true, y_score)
# we use torch.nn.CrossEntropyLoss (`cel` below)
cel_input = predictions_per_batch['raw_predictions']
cel_target = predictions_per_batch['labels_tensor']
loss = loss_function(cel_input, cel_target).item()
return {
'loss': loss, 'accuracy': accuracy,
'precision': precision, 'recall': recall,
'f1score': f1score, 'specificity': specificity, 'auc': auc}