-
Notifications
You must be signed in to change notification settings - Fork 0
/
eval_model.py
102 lines (88 loc) · 4.05 KB
/
eval_model.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
import torch
import pandas as pd
import cxr_dataset as CXR
from torchvision import transforms, utils
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms, utils
import sklearn
import sklearn.metrics as sklm
from torch.autograd import Variable
import numpy as np
import os
import torch.nn as nn
import torch.backends.cudnn as cudnn
import torchvision
from sklearn.metrics import roc_auc_score
from readData import ChestXrayDataSet
###########################################################
# EXTERNAL FUNCTION
###########################################################
def make_pred_multilabel(data_transforms, model, PATH_TO_IMAGES):
"""
Gives predictions for test fold and calculates AUCs using previously trained model
Args:
data_transforms: torchvision transforms to preprocess raw images; same as validation transforms
model: densenet-121 from torchvision previously fine tuned to training data
PATH_TO_IMAGES: path at which NIH images can be found
Returns:
pred_df: dataframe containing individual predictions and ground truth for each test image
auc_df: dataframe containing aggregate AUCs by train/test tuples
"""
N_CLASSES = 14
CLASS_NAMES = [ 'Atelectasis', 'Cardiomegaly', 'Effusion', 'Infiltration', 'Mass', 'Nodule', 'Pneumonia',
'Pneumothorax', 'Consolidation', 'Edema', 'Emphysema', 'Fibrosis', 'Pleural_Thickening', 'Hernia']
BATCH_SIZE = 64
# calc preds in batches of 16, can reduce if your GPU has less RAM
BATCH_SIZE = 8
# set model to eval mode; required for proper predictions given use of batchnorm
model.eval()
cudnn.benchmark = True
normalize = transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
test_dataset = ChestXrayDataSet(data_dir=PATH_TO_IMAGES, image_list_file="./labels/test_list.txt",
transform=transforms.Compose([
transforms.Resize(340),
transforms.TenCrop(299),
transforms.Lambda
(lambda crops: torch.stack([transforms.ToTensor()(crop) for crop in crops])),
transforms.Lambda
(lambda crops: torch.stack([normalize(crop) for crop in crops]))
]))
test_loader = DataLoader(dataset=test_dataset, batch_size=BATCH_SIZE,
shuffle=False, num_workers=8, pin_memory=True)
# initialize the ground truth and output tensor
gt = torch.FloatTensor()
gt = gt.cuda()
pred = torch.FloatTensor()
pred = pred.cuda()
for i, (inp, target) in enumerate(test_loader):
with torch.no_grad():
target = target.cuda()
gt = torch.cat((gt, target), 0)
bs, n_crops, c, h, w = inp.size()
input_var = torch.autograd.Variable(inp.view(-1, c, h, w).cuda())
output = model(input_var)
output_mean = output.view(bs, n_crops, -1).mean(1)
pred = torch.cat((pred, output_mean.data), 0)
AUROCs = compute_AUCs(gt, pred)
AUROC_avg = np.array(AUROCs).mean()
print('The average AUROC is {AUROC_avg:.3f}'.format(AUROC_avg=AUROC_avg))
for i in range(N_CLASSES):
print('The AUROC of {} is {}'.format(CLASS_NAMES[i], AUROCs[i]))
def compute_AUCs(gt, pred):
"""Computes Area Under the Curve (AUC) from prediction scores.
Args:
gt: Pytorch tensor on GPU, shape = [n_samples, n_classes]
true binary labels.
pred: Pytorch tensor on GPU, shape = [n_samples, n_classes]
can either be probability estimates of the positive class,
confidence values, or binary decisions.
Returns:
List of AUROCs of all classes.
"""
AUROCs = []
gt_np = gt.cpu().numpy()
pred_np = pred.cpu().numpy()
for i in range(14):
AUROCs.append(roc_auc_score(gt_np[:, i], pred_np[:, i]))
return AUROCs