Repository navigation
Expand file tree
/
Copy pathmain.py
More file actions
213 lines (154 loc) · 7.35 KB
/
Copy pathmain.py
File metadata and controls
213 lines (154 loc) · 7.35 KB
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
import torch
import utils
import setup
from EWCCNN import EWCCNN
from EWCMLP import EWCMLP
from VanillaMLP import VanillaMLP
from VanillaCNN import VanillaCNN
import numpy as np
import scipy as sp
import h5py
import random
from Continuum import Continuum
# import matplotlib
# matplotlib.use('Agg')
import matplotlib.pyplot as plt
def show_mnist_img(batch, task):
fig = plt.figure()
for i, img in enumerate(batch, 1):
plt.subplot(len(batch) // 10, 10, i)
npimg = img.numpy()
npimg = np.resize(npimg, (28,28))
plt.imshow(npimg)
plt.show()
def main():
args = setup.parse_arguments()
kwargs, device = setup.set_gpu_options(args)
print(device)
setup.seed_rngs(args)
# test seeding...
print(np.random.randint(low=1, high=10000))
print(sp.stats.randint.rvs(1, 10000, size=1))
print(torch.randint(1, 10000, (1,), device=torch.device('cpu')))
print(torch.randint(1, 10000, (1,), device=torch.device('cuda')))
print(random.randint(1, 10000))
# print 8 digits of precision when displaying floating point output from tensors
torch.set_printoptions(precision=8)
models = setup.build_models(args, device)
for model in models:
for parameter in model.parameters():
print(parameter.size())
# The number of the task on which we are CURRENTLY training in the loop below-
# e.g. when training on task 3 this value will be 3
task_count = 1
#utils.output_tensorboard_graph(args, device, models, task_count) # TODO change this to model.device in utils/ model constructor
# todo fix kwargs (**kwargs)
# todo fix num_workers in utils
#cifar_classes = utils.define_cifar100_labels()
# for task in range(args.tasks):
# # get some random training images
# images, labels = next(iter(test_loaders[task]))
#
# # show images
# utils.imshow(torchvision.utils.make_grid(images))
#
# # print labels
# print(' '.join('%5s' % cifar_classes[labels[j]] for j in range(len(labels))))
# A list of the different DataLoader objects that hold various permutations of the mnist testing dataset-
# used for testing models on all previously encountered tasks
prev_test_loaders = []
retrain_task = False
files, expansions, avg_acc, task_acc, h5file = setup.setup_h5_file(args, models)
# metrics for measuring network strain- saved to h5 dataset later
### ALL OF THESE ARE EVALUATED BASED ON THE RUNNING SUMS OF THE FISHER INFO ###
failure = [0] # task at which network fails without expansion
fisher_total = [0] # sum of all calculated FIM diagonals for each task
post_training_loss = [0] # training loss after final training iteration on each task
fisher_average = [0] # avg of FIM diags
fisher_st_dev = [0] # standard deviation of FIM diags
fisher_max = [0] # maximum Fisher Info of any parameter in the network
fisher_information = [[0]] # actual FIM diagonals
ewc_pen = [0, 0] # ewc penalty (loss on previous tasks only) is 0 for task 1 and 0 (filler)
if args.dataset == "cifar":
train_loaders, validation_loaders, test_loaders = utils.generate_cifar_tasks(args, kwargs)
while task_count < (args.tasks + 1) :
torch.cuda.empty_cache() # free any available gpu memory
if not retrain_task:
if args.dataset == "cifar":
train_loader = train_loaders[task_count - 1]
validation_loader = validation_loaders[task_count - 1]
test_loader = test_loaders[task_count - 1]
# todo remove- just for testing CNNs
#train_loader, test_loader = utils.generate_1_cifar10_task(args)
else:# todo add this to the arg parser
# get the DataLoaders for the training, validation, and testing data
train_loader, validation_loader, test_loader = utils.generate_new_mnist_task(args, kwargs,
first_task=(task_count == 1)
)
# add the new test_loader for this task to the list of testing dataset DataLoaders for later re-use
# to evaluate how well the models retain accuracy on old tasks after learning new ones
#
# NOTE: this list also includes the current test_loader, which we are appending here, because we also
# need to test each network on the current task after training
prev_test_loaders.append(test_loader)
# verify percent permuation of images
# train_batch, labels = next(iter(train_loader))
# show_mnist_img(train_batch, task_count)
#
# test_batch, labels = next(iter(test_loader))
# show_mnist_img(test_batch, task_count)
retrain_task = False
for model_num, model in enumerate(models):
train_args = {'validation_loader': validation_loader,
'failure': failure,
'fisher_total': fisher_total,
'post_training_loss': post_training_loss,
'fisher_average': fisher_average,
'fisher_st_dev': fisher_st_dev,
'fisher_max': fisher_max,
'fisher_information': fisher_information,
'h5file': h5file,
'ewc_pen': ewc_pen
} \
if isinstance(model, (EWCMLP, EWCCNN)) else {}
# for each desired epoch, train the model on the latest task
model.train_model(args, train_loader, task_count, **train_args)
threshold = 0 if isinstance(model, (VanillaMLP, VanillaCNN)) else args.accuracy_threshold
# test the model on ALL tasks trained thus far (including current task)
test_results = model.test(prev_test_loaders, threshold, args)
if test_results == -1:
print(len(ewc_pen))
if len(ewc_pen) > 2:
del ewc_pen[-1] # if expanding, we want to rewrite this or it will be inaccurate
print(len(ewc_pen))
retrain_task = True
break
else:
task_acc[model_num][:len(test_results)] = np.array(test_results)[...]
if retrain_task:
for model in models:
model.reset(task_count - 1)
models = utils.expand(models, args)
for model_num in range(len(models)):
expansions[model_num][task_count] += 1
#utils.output_tensorboard_graph(args, models, task_count + 1)
else:
for model_num in range(len(models)):
avg_acc[model_num][task_count] = sum(task_acc[model_num]) / task_count
# increment the number of the current task before re-entering while loop
task_count += 1
for f in files:
f.flush()
for f in files:
print("|-----[", f.filename, "]-----|", '\n')
print("METADATA:\n")
print([d for d in f['metadata']], '\n')
print("FINAL TASK ACCURACIES:\n")
print([d for d in f['task_acc']], '\n')
print("EXPANSIONS:\n")
print([d for d in f['expansions']], '\n')
print("AVERAGE ACCURACIES:\n")
print([d for d in f['avg_acc']], '\n')
f.close()
if __name__ == '__main__':
main()