forked from cgnorthcutt/benchmarking-keras-pytorch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimagenet_pytorch_get_predictions.py
executable file
·171 lines (133 loc) · 5.46 KB
/
imagenet_pytorch_get_predictions.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python
# coding: utf-8
# In[1]:
# These imports enhance Python2/3 compatibility.
from __future__ import print_function, absolute_import, division, unicode_literals, with_statement
# In[13]:
from torchvision import models, datasets, transforms
import torch
import multiprocessing
import numpy as np
import os
import sys
import argparse
# This helps with dataloading for inference
torch.multiprocessing.set_sharing_strategy('file_system')
VAL_SIZE = 50000
# In[3]:
pytorch_models = [
"inception_v3",
"vgg11",
"vgg11_bn",
"vgg13",
"vgg13_bn",
"vgg16",
"vgg16_bn",
"vgg19",
"vgg19_bn",
"densenet121",
"densenet161",
"densenet169",
"densenet201",
"alexnet",
"squeezenet1_0",
"squeezenet1_1",
"resnet18",
"resnet34",
"resnet50",
"resnet101",
"resnet152",
]
# In[22]:
# Set up argument parser
parser = argparse.ArgumentParser(description='PyTorch ImageNet Inference')
parser.add_argument('val_dir', metavar='DIR',
help='path to imagenet val dataset folder')
parser.add_argument('-m', '--model', metavar='MODEL', default=None,
choices=pytorch_models,
help='model architecture: ' +
' | '.join(pytorch_models) +
' (example: resnet50)' +
' (default: Runs across all PyTorch models)')
parser.add_argument('-g', '--gpu', metavar='MODEL', default=0,
help='int of GPU to use. Only uses single GPU.')
parser.add_argument('-b', '--batch-size', metavar='BATCHSIZE', type=int, default=32,
help='Number of examples to run forward pass on at once.')
parser.add_argument('-o', '--output-dir', metavar='OUTPUTDIR', default="pytorch_imagenet/",
help='directory folder to store output results in.')
parser.add_argument('--save-all-probs', action='store_true', default = False,
help='Store entire softmax output for all examples (100 MB)')
# In[23]:
def main(args = parser.parse_args()):
'''Select GPU and set up data loader for ImageNet val set.'''
global device
os.environ["CUDA_VISIBLE_DEVICES"]=str(args.gpu)
# Detect if we have a GPU available
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Create output directory if it does not exist
if not os.path.exists(args.output_dir):
os.makedirs(args.output_dir)
dataloaders = {}
for img_size in [224, 299]:
val_transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(img_size),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])
val_dataset = datasets.ImageFolder(args.val_dir, val_transform)
dataloaders[img_size] = torch.utils.data.DataLoader(
val_dataset,
batch_size=args.batch_size,
shuffle=False,
num_workers=max(1, multiprocessing.cpu_count() - 2),
)
# Run forward pass inference on all models for all examples in val set.
models = pytorch_models if args.model is None else [args.model]
for model in models:
process_model(model, dataloaders, args.output_dir, args.save_all_probs)
# In[ ]:
def process_model(
model_name,
dataloaders,
out_dir = "pytorch_imagenet/",
save_all_probs = False,
):
'''Actual work is done here. This runs inference on a pyTorch model,
using the pyTorch batch loader.
Top5 predictions and probabilities for each example for the model
are stored in the pytorch_imagenet/ output directory.'''
# Load PyTorch model pre-trained on ImageNet
model = eval("models.{}(pretrained=True)".format(model_name))
# Send the model to GPU/CPU
model = model.to(device)
wfn_base = os.path.join(out_dir, model_name + "_pytorch_imagenet_")
probs, labels = [], []
loader = dataloaders[299] if model_name == "inception_v3" else dataloaders[224]
# Inference, with no gradient changing
model.eval() # set model to inference mode (not train mode)
with torch.set_grad_enabled(False):
for i, (x_val, y_val) in enumerate(loader):
print("\r{} completed: {:.2%}".format(model_name, i / len(loader)), end="")
sys.stdout.flush()
out = torch.nn.functional.softmax(model(x_val.to(device)), dim=1)
probs.append(out.numpy() if device == 'cpu' else out.cpu().numpy())
labels.append(y_val)
# Convert batches to single numpy arrays
probs = np.stack([p for l in probs for p in l])
labels = np.array([t for l in labels for t in l])
if save_all_probs:
np.save(wfn_base + "probs.npy", probs.astype(np.float16))
# Extract top 5 predictions for each example
n = 5
top = np.argpartition(-probs, n, axis = 1)[:,:n]
top_probs = probs[np.arange(probs.shape[0])[:, None], top]
acc1 = sum(top[range(len(top)), np.argmax(top_probs, axis = 1)] == labels) / float(len(labels))
acc5 = sum([labels[i] in row for i, row in enumerate(top)]) / float(len(labels))
print('\n{}: acc1: {:.2%}, acc5: {:.2%}'.format(model_name, acc1, acc5))
# Save top 5 predictions and associated probabilities
np.save(wfn_base + "top5preds.npy", top)
np.save(wfn_base + "top5probs.npy", top_probs.astype(np.float16))
# In[ ]:
if __name__ == '__main__':
main()