-
Notifications
You must be signed in to change notification settings - Fork 10
/
test_models.py
245 lines (169 loc) · 6.76 KB
/
test_models.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#!/usr/bin/env python
# coding: utf-8
"""
This module tests the "experts" that have been generated by the generate_models.py file. If the wrong autoencoder were to be
selected, the performance would obviously suffer. A metric to determine how many times this occurs has been designed. Since in
these tasks.
"""
import torch
torch.backends.cudnn.benchmark=True
import torch.nn as nn
from torch.autograd import Variable
import torch.optim as optim
import torch.nn.functional as F
import torchvision.datasets as datasets
import torchvision.models as models
import torchvision.transforms as transforms
import argparse
import numpy as np
from random import shuffle
import os
import copy
from autoencoder import *
import sys
sys.path.append(os.path.join(os.getcwd(), 'utils'))
from encoder_train import *
from encoder_utils import *
from model_train import *
from model_utils import *
parser = argparse.ArgumentParser(description='Test file')
#parser.add_argument('--task_number', default=1, type=int, help='Select the task you want to test out the architecture; choose from 1-4')
parser.add_argument('--use_gpu', default=False, type=bool, help = 'Set the flag if you wish to use the GPU')
parser.add_argument('--batch_size', default=16, type=int, help='Batch size you want to use whilst testing the model')
#get the arguments passed in
args = parser.parse_args()
use_gpu = args.use_gpu
batch_size = args.batch_size
#randomly shuffle the tasks in the sequence
task_number_list = [x for x in range(1,10)]
#shuffle(task_number_list)
classes = []
#transformations for the test data
data_transforms_tin = {
'test': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
}
#transforms for the mnist dataset. Applicable for the tasks 5-9
data_transforms_mnist = {
'test': transforms.Compose([
transforms.ToTensor(),
transforms.Normalize([0.1307,], [0.3081,])
])
}
#get the paths to the data and model
data_path = os.path.join(os.getcwd(), "Data")
encoder_path = os.path.join(os.getcwd(), "models", "autoencoders")
model_path = os.path.join(os.getcwd(), "models", "trained_models")
#Get the number of classes in each of the given task folders
for task_number in task_number_list:
path_task = os.path.join(data_path, "Task_" + str(task_number))
if(task_number >=1 and task_number <=4):
#get the image folder
image_folder = datasets.ImageFolder(os.path.join(path_task, 'test'), transform = data_transforms_tin['test'])
classes.append(len(image_folder.classes))
else:
image_folder = datasets.ImageFolder(os.path.join(path_task, 'test'), transform = data_transforms_mnist['test'])
classes.append(len(image_folder.classes))
#shuffle the sequence of the tasks
shuffle(task_number_list)
#set the device to be used and initialize the feature extractor to feed the data into the autoencoder
device = torch.device("cuda:0" if use_gpu else "cpu")
feature_extractor = Alexnet_FE(models.alexnet(pretrained=True))
feature_extractor.to(device)
for task_number in task_number_list:
#get the paths to the data and model
path_task = os.path.join(data_path, "Task_" + str(task_number))
if(task_number >=1 and task_number <=4):
#get the image folder
image_folder = datasets.ImageFolder(os.path.join(path_task, 'test'), transform = data_transforms_tin['test'])
dset_size = len(image_folder)
else:
#get the image folder
image_folder = datasets.ImageFolder(os.path.join(path_task, 'test'), transform = data_transforms_mnist['test'])
dset_size = len(image_folder)
dset_loaders = torch.utils.data.DataLoader(image_folder, batch_size = batch_size,
shuffle=True, num_workers=4)
best_loss = 99999999999
model_number = 0
#Load autoencoder models for tasks 1-10; need to select the best performing autoencoder model
for ae_number in range(1, 10):
ae_path = os.path.join(encoder_path, "autoencoder_" + str(ae_number))
#Load a trained autoencoder model
model = Autoencoder()
model.load_state_dict(torch.load(os.path.join(ae_path, 'best_performing_model.pth')))
running_loss = 0
model.to(device)
#Test out the different auto encoder models and check their reconstruction error
for data in dset_loaders:
input_data, labels = data
del labels
del data
if (use_gpu):
input_data = input_data.to(device)
else:
input_data = Variable(input_data)
#get the input to the autoencoder from the conv backbone of the Alexnet
input_to_ae = feature_extractor(input_data)
input_to_ae = input_to_ae.view(input_to_ae.size(0), -1)
#get the outputs from the model
preds = model(input_to_ae)
loss = encoder_criterion(preds, input_to_ae)
del preds
del input_data
del input_to_ae
running_loss = running_loss + loss.item()
model_loss = running_loss/dset_size
if(model_loss < best_loss):
best_loss = model_loss
model_number = ae_number
del model
if(model_number == task_number):
print ("The correct autoencoder has been found")
else:
print ("Incorrect routing, wrong model has been selected")
#Load the expert that has been found by this procedure into memory
trained_model_path = os.path.join(model_path, "model_" + str(model_number))
#Get the number of classes that this expert was exposed to
file_name = os.path.join(trained_model_path, "classes.txt")
file_object = open(file_name, 'r')
num_of_classes = file_object.read()
file_object.close()
num_of_classes = int(num_of_classes)
model = GeneralModelClass(num_of_classes)
model.load_state_dict(torch.load(os.path.join(trained_model_path, 'best_performing_model.pth')))
#initialize the results statistics
running_loss = 0
running_corrects = 0
#run the test loop over the model
for data in dset_loaders:
input_data, labels = data
del data
if (use_gpu):
input_data = Variable(input_data.to(device))
labels = Variable(labels.to(device))
else:
input_data = Variable(input_data)
labels = Variable(labels)
model.to(device)
outputs = model(input_data)
loss = model_criterion(outputs, labels, 'CE')
#for a more robust analysis check over the entire output layer (similar to multi head setting)
_, preds = torch.max(outputs, 1)
#check over only the specific layer identified by the AE (similar to single head setting)
#uncomment this line if you wish to evalute this setting
#_, preds = torch.max(outputs[:, -classes[model_number]:], 1)
running_corrects += torch.sum(preds==labels.data)
running_loss = running_loss + loss.item()
del preds
del input_data
del labels
model_loss = running_loss/dset_size
model_accuracy = running_corrects.double()/dset_size
#Store the results into a file
with open("results.txt", "a") as myfile:
myfile.write("\n{}: {}".format(task_number, model_accuracy*100))
myfile.close()