Skip to content
Snippets Groups Projects
Commit 08b20c1f authored by Max Ramsay King's avatar Max Ramsay King
Browse files
parents e75c71a4 8bdeaf68
No related branches found
No related tags found
No related merge requests found
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
**/__pycache__/
**/datasets/
*.py[cod] *.py[cod]
*$py.class *$py.class
*.pyc *.pyc
......
...@@ -14,6 +14,8 @@ import pygad.torchga as torchga ...@@ -14,6 +14,8 @@ import pygad.torchga as torchga
import random import random
import copy import copy
from MetaAugment.main import *
# import MetaAugment.child_networks as child_networks # import MetaAugment.child_networks as child_networks
# from MetaAugment.main import * # from MetaAugment.main import *
...@@ -53,8 +55,10 @@ class Learner(nn.Module): ...@@ -53,8 +55,10 @@ class Learner(nn.Module):
self.relu3 = nn.ReLU() self.relu3 = nn.ReLU()
self.fc2 = nn.Linear(120, 84) self.fc2 = nn.Linear(120, 84)
self.relu4 = nn.ReLU() self.relu4 = nn.ReLU()
self.fc3 = nn.Linear(84, 13) self.fc3 = nn.Linear(84, num_transforms + 21)
# self.sig = nn.Sigmoid() # self.sig = nn.Sigmoid()
# Currently using discrete outputs for the probabilities
def forward(self, x): def forward(self, x):
...@@ -157,90 +161,13 @@ def train_model(transform_idx, p, child_network): ...@@ -157,90 +161,13 @@ def train_model(transform_idx, p, child_network):
epoch = 20 epoch = 20
best_acc = train_child_network(child_network, train_loader, test_loader, sgd, cost, max_epochs=100) best_acc = train_child_network(child_network, train_loader, test_loader,
sgd, cost, max_epochs=100, print_every_epoch=False)
return best_acc
def train_child_network(child_network, train_loader, test_loader, sgd,
cost, max_epochs=100, early_stop_num = 10, logging=False):
best_acc=0
early_stop_cnt = 0
# logging accuracy for plotting
acc_log = []
# train child_network and check validation accuracy each epoch
for _epoch in range(max_epochs):
# train child_network
child_network.train()
for idx, (train_x, train_label) in enumerate(train_loader):
label_np = np.zeros((train_label.shape[0], 10))
sgd.zero_grad()
predict_y = child_network(train_x.float())
loss = cost(predict_y, train_label.long())
loss.backward()
sgd.step()
# check validation accuracy on validation set
correct = 0
_sum = 0
child_network.eval()
with torch.no_grad():
for idx, (test_x, test_label) in enumerate(test_loader):
predict_y = child_network(test_x.float()).detach()
predict_ys = np.argmax(predict_y, axis=-1)
label_np = test_label.numpy()
_ = predict_ys == test_label
correct += np.sum(_.numpy(), axis=-1)
_sum += _.shape[0]
# update best validation accuracy if it was higher, otherwise increase early stop count
acc = correct / _sum
if acc > best_acc :
best_acc = acc
early_stop_cnt = 0
else:
early_stop_cnt += 1
# exit if validation gets worse over 10 runs
if early_stop_cnt >= early_stop_num:
break
# print('main.train_child_network best accuracy: ', best_acc)
acc_log.append(acc)
if logging:
return best_acc, acc_log
return best_acc return best_acc
def create_toy(train_dataset, test_dataset, batch_size, n_samples, seed=100):
# shuffle and take first n_samples %age of training dataset
shuffle_order_train = np.random.RandomState(seed=seed).permutation(len(train_dataset))
shuffled_train_dataset = torch.utils.data.Subset(train_dataset, shuffle_order_train)
indices_train = torch.arange(int(n_samples*len(train_dataset)))
reduced_train_dataset = torch.utils.data.Subset(shuffled_train_dataset, indices_train)
# shuffle and take first n_samples %age of test dataset
shuffle_order_test = np.random.RandomState(seed=seed).permutation(len(test_dataset))
shuffled_test_dataset = torch.utils.data.Subset(test_dataset, shuffle_order_test)
indices_test = torch.arange(int(n_samples*len(test_dataset)))
reduced_test_dataset = torch.utils.data.Subset(shuffled_test_dataset, indices_test)
# push into DataLoader
train_loader = torch.utils.data.DataLoader(reduced_train_dataset, batch_size=batch_size)
test_loader = torch.utils.data.DataLoader(reduced_test_dataset, batch_size=batch_size)
return train_loader, test_loader
# ORGANISING DATA # ORGANISING DATA
......
No preview for this file type
...@@ -53,109 +53,114 @@ class aa_learner: ...@@ -53,109 +53,114 @@ class aa_learner:
# TODO: We should probably use a different way to store results than self.history # TODO: We should probably use a different way to store results than self.history
self.history = [] self.history = []
def generate_new_policy(self): def generate_new_discrete_operation(self, fun_num=14, p_bins=10, m_bins=10):
''' '''
Generate a new random policy in the form of generate a new random operation in the form of a tensor of dimension:
[ (fun_num + 11 + 10)
(("Invert", 0.8, None), ("Contrast", 0.2, 6)),
(("Rotate", 0.7, 2), ("Invert", 0.8, None)), The first fun_num dimensions is a 1-hot encoding to specify which function to use.
(("Sharpness", 0.8, 1), ("Sharpness", 0.9, 3)), The next 11 dimensions specify which 'probability' to choose.
(("ShearY", 0.5, 8), ("Invert", 0.7, None)), (0.0, 0.1, ..., 1.0)
] The next 10 dimensions specify which 'magnitude' to choose.
(0, 1, ..., 9)
''' '''
fun = np.random.randint(0, fun_num)
prob = np.random.randint(p_bins+1, fun_num)
mag = np.random.randint(m_bins, fun_num)
fun_t= torch.zeros(fun_num)
fun_t[fun] = 1
prob_t = torch.zeros(p_bins+1)
prob_t[prob] = 1
mag_t = torch.zeros(m_bins)
mag_t[mag] = 1
def generate_new_discrete_operation(fun_num=14, p_bins=10, m_bins=10): return torch.cat([fun_t, prob_t, mag_t])
'''
generate a new random operation in the form of a tensor of dimension:
(fun_num + 11 + 10) def generate_new_continuous_operation(self, fun_num=14, p_bins=10, m_bins=10):
'''
The first fun_num dimensions is a 1-hot encoding to specify which function to use. Returns operation_tensor, which is a tensor representation of a random operation with
The next 11 dimensions specify which 'probability' to choose. dimension:
(0.0, 0.1, ..., 1.0) (fun_num + 1 + 1)
The next 10 dimensions specify which 'magnitude' to choose.
(0, 1, ..., 9) The first fun_num dimensions is a 1-hot encoding to specify which function to use.
''' The next 1 dimensions specify which 'probability' to choose.
fun = np.random.randint(0, fun_num) 0 < x < 1
prob = np.random.randint(p_bins+1, fun_num) The next 1 dimensions specify which 'magnitude' to choose.
mag = np.random.randint(m_bins, fun_num) 0 < x < 9
'''
fun_t= torch.zeros(fun_num) fun = np.random.randint(0, fun_num)
fun_t[fun] = 1
prob_t = torch.zeros(p_bins+1) fun_p_m = torch.zeros(fun_num + 2)
prob_t[prob] = 1 fun_p_m[fun] = 1
mag_t = torch.zeros(m_bins) fun_p_m[-2] = np.random.uniform() # 0<prob<1
mag_t[mag] = 1 fun_p_m[-1] = np.random.uniform() * (m_bins-1) # 0<mag<9
return torch.cat([fun_t, prob_t, mag_t])
return fun_p_m
def generate_new_continuous_operation(fun_num=14, p_bins=10, m_bins=10):
''' def translate_operation_tensor(self, operation_tensor, fun_num=14,
Returns operation_tensor, which is a tensor representation of a random operation with
dimension:
(fun_num + 1 + 1)
The first fun_num dimensions is a 1-hot encoding to specify which function to use.
The next 1 dimensions specify which 'probability' to choose.
0 < x < 1
The next 1 dimensions specify which 'magnitude' to choose.
0 < x < 9
'''
fun = np.random.randint(0, fun_num)
fun_p_m = torch.zeros(fun_num + 2)
fun_p_m[fun] = 1
fun_p_m[-2] = np.random.uniform() # 0<prob<1
fun_p_m[-1] = np.random.uniform() * (m_bins-1) # 0<mag<9
return fun_p_m
def translate_operation_tensor(operation_tensor, fun_num=14,
p_bins=10, m_bins=10, p_bins=10, m_bins=10,
discrete_p_m=False): discrete_p_m=False):
''' '''
takes in a tensor representing a operation and returns an actual operation which takes in a tensor representing a operation and returns an actual operation which
is in the form of: is in the form of:
("Invert", 0.8, None) ("Invert", 0.8, None)
or or
("Contrast", 0.2, 6) ("Contrast", 0.2, 6)
Args: Args:
operation_tensor operation_tensor
continuous_p_m (boolean): whether the operation_tensor has continuous representations continuous_p_m (boolean): whether the operation_tensor has continuous representations
of probability and magnitude of probability and magnitude
''' '''
# if input operation_tensor is discrete # if input operation_tensor is discrete
if discrete_p_m: if discrete_p_m:
fun_t = operation_tensor[:fun_num]
prob_t = operation_tensor[fun_num:fun_num+p_bins+1]
mag_t = operation_tensor[-m_bins:]
fun = torch.argmax(fun_t)
prob = torch.argmax(prob_t)
mag = torch.argmax(mag_t)
raise NotImplementedError("U can implement this if u want")
# process continuous operation_tensor
fun_t = operation_tensor[:fun_num] fun_t = operation_tensor[:fun_num]
p = operation_tensor[-2].item() # 0 < p < 1 prob_t = operation_tensor[fun_num:fun_num+p_bins+1]
m = operation_tensor[-1].item() # 0 < m < 9 mag_t = operation_tensor[-m_bins:]
fun = torch.argmax(fun_t)
prob = torch.argmax(prob_t) # 0 <= p <= 10
mag = torch.argmax(mag_t) # 0 <= m <= 9
fun = augmentation_space[fun][0]
prob = prob/10
fun_num = torch.argmax(fun_t) return (fun, prob, mag)
function = augmentation_space[fun_num][0]
p = round(p, 1) # round to nearest first decimal digit
m = round(m) # round to nearest integer # process continuous operation_tensor
return (function, p, m) fun_t = operation_tensor[:fun_num]
p = operation_tensor[-2].item() # 0 < p < 1
m = operation_tensor[-1].item() # 0 < m < 9
fun_num = torch.argmax(fun_t)
function = augmentation_space[fun_num][0]
p = round(p, 1) # round to nearest first decimal digit
m = round(m) # round to nearest integer
return (function, p, m)
def generate_new_policy(self):
'''
Generate a new random policy in the form of
[
(("Invert", 0.8, None), ("Contrast", 0.2, 6)),
(("Rotate", 0.7, 2), ("Invert", 0.8, None)),
(("Sharpness", 0.8, 1), ("Sharpness", 0.9, 3)),
(("ShearY", 0.5, 8), ("Invert", 0.7, None)),
]
'''
new_policy = [] new_policy = []
for _ in range(self.sp_num): for _ in range(self.sp_num):
# generate 2 operations for each subpolicy # generate 2 operations for each subpolicy
ops = [] ops = []
for i in range(2): for i in range(2):
new_op = generate_new_continuous_operation(self.fun_num) new_op = self.generate_new_continuous_operation(self.fun_num)
new_op = translate_operation_tensor(new_op) new_op = self.translate_operation_tensor(new_op)
ops.append(new_op) ops.append(new_op)
new_subpolicy = tuple(ops) new_subpolicy = tuple(ops)
......
...@@ -57,109 +57,113 @@ class randomsearch_learner: ...@@ -57,109 +57,113 @@ class randomsearch_learner:
# TODO: We should probably use a different way to store results than self.history # TODO: We should probably use a different way to store results than self.history
self.history = [] self.history = []
def generate_new_policy(self): def generate_new_discrete_operation(self, fun_num=14, p_bins=10, m_bins=10):
''' '''
Generate a new random policy in the form of generate a new random operation in the form of a tensor of dimension:
[ (fun_num + 11 + 10)
(("Invert", 0.8, None), ("Contrast", 0.2, 6)),
(("Rotate", 0.7, 2), ("Invert", 0.8, None)), The first fun_num dimensions is a 1-hot encoding to specify which function to use.
(("Sharpness", 0.8, 1), ("Sharpness", 0.9, 3)), The next 11 dimensions specify which 'probability' to choose.
(("ShearY", 0.5, 8), ("Invert", 0.7, None)), (0.0, 0.1, ..., 1.0)
] The next 10 dimensions specify which 'magnitude' to choose.
(0, 1, ..., 9)
''' '''
fun = np.random.randint(0, fun_num)
prob = np.random.randint(p_bins+1, fun_num)
mag = np.random.randint(m_bins, fun_num)
fun_t= torch.zeros(fun_num)
fun_t[fun] = 1
prob_t = torch.zeros(p_bins+1)
prob_t[prob] = 1
mag_t = torch.zeros(m_bins)
mag_t[mag] = 1
def generate_new_discrete_operation(fun_num=14, p_bins=10, m_bins=10): return torch.cat([fun_t, prob_t, mag_t])
'''
generate a new random operation in the form of a tensor of dimension:
(fun_num + 11 + 10) def generate_new_continuous_operation(self, fun_num=14, p_bins=10, m_bins=10):
'''
The first fun_num dimensions is a 1-hot encoding to specify which function to use. Returns operation_tensor, which is a tensor representation of a random operation with
The next 11 dimensions specify which 'probability' to choose. dimension:
(0.0, 0.1, ..., 1.0) (fun_num + 1 + 1)
The next 10 dimensions specify which 'magnitude' to choose.
(0, 1, ..., 9) The first fun_num dimensions is a 1-hot encoding to specify which function to use.
''' The next 1 dimensions specify which 'probability' to choose.
fun = np.random.randint(0, fun_num) 0 < x < 1
prob = np.random.randint(p_bins+1, fun_num) The next 1 dimensions specify which 'magnitude' to choose.
mag = np.random.randint(m_bins, fun_num) 0 < x < 9
'''
fun_t= torch.zeros(fun_num) fun = np.random.randint(0, fun_num)
fun_t[fun] = 1
prob_t = torch.zeros(p_bins+1)
prob_t[prob] = 1
mag_t = torch.zeros(m_bins)
mag_t[mag] = 1
return torch.cat([fun_t, prob_t, mag_t])
fun_p_m = torch.zeros(fun_num + 2)
fun_p_m[fun] = 1
fun_p_m[-2] = np.random.uniform() # 0<prob<1
fun_p_m[-1] = np.random.uniform() * (m_bins-1) # 0<mag<9
return fun_p_m
def generate_new_continuous_operation(fun_num=14, p_bins=10, m_bins=10): def translate_operation_tensor(self, operation_tensor, fun_num=14,
'''
Returns operation_tensor, which is a tensor representation of a random operation with
dimension:
(fun_num + 1 + 1)
The first fun_num dimensions is a 1-hot encoding to specify which function to use.
The next 1 dimensions specify which 'probability' to choose.
0 < x < 1
The next 1 dimensions specify which 'magnitude' to choose.
0 < x < 9
'''
fun = np.random.randint(0, fun_num)
fun_p_m = torch.zeros(fun_num + 2)
fun_p_m[fun] = 1
fun_p_m[-2] = np.random.uniform() # 0<prob<1
fun_p_m[-1] = np.random.uniform() * (m_bins-1) # 0<mag<9
return fun_p_m
def translate_operation_tensor(operation_tensor, fun_num=14,
p_bins=10, m_bins=10, p_bins=10, m_bins=10,
discrete_p_m=False): discrete_p_m=False):
''' '''
takes in a tensor representing a operation and returns an actual operation which takes in a tensor representing a operation and returns an actual operation which
is in the form of: is in the form of:
("Invert", 0.8, None) ("Invert", 0.8, None)
or or
("Contrast", 0.2, 6) ("Contrast", 0.2, 6)
Args: Args:
operation_tensor operation_tensor
continuous_p_m (boolean): whether the operation_tensor has continuous representations continuous_p_m (boolean): whether the operation_tensor has continuous representations
of probability and magnitude of probability and magnitude
''' '''
# if input operation_tensor is discrete # if input operation_tensor is discrete
if discrete_p_m: if discrete_p_m:
fun_t = operation_tensor[:fun_num]
prob_t = operation_tensor[fun_num:fun_num+p_bins+1]
mag_t = operation_tensor[-m_bins:]
fun = torch.argmax(fun_t)
prob = torch.argmax(prob_t)
mag = torch.argmax(mag_t)
raise NotImplementedError("U can implement this if u want")
# process continuous operation_tensor
fun_t = operation_tensor[:fun_num] fun_t = operation_tensor[:fun_num]
p = operation_tensor[-2].item() # 0 < p < 1 prob_t = operation_tensor[fun_num:fun_num+p_bins+1]
m = operation_tensor[-1].item() # 0 < m < 9 mag_t = operation_tensor[-m_bins:]
fun = torch.argmax(fun_t)
prob = torch.argmax(prob_t) # 0 <= p <= 10
mag = torch.argmax(mag_t) # 0 <= m <= 9
fun_num = torch.argmax(fun_t) fun = augmentation_space[fun][0]
function = augmentation_space[fun_num][0] prob = prob/10
p = round(p, 1) # round to nearest first decimal digit
m = round(m) # round to nearest integer
return (function, p, m)
return (fun, prob, mag)
# process continuous operation_tensor
fun_t = operation_tensor[:fun_num]
p = operation_tensor[-2].item() # 0 < p < 1
m = operation_tensor[-1].item() # 0 < m < 9
fun_num = torch.argmax(fun_t)
function = augmentation_space[fun_num][0]
p = round(p, 1) # round to nearest first decimal digit
m = round(m) # round to nearest integer
return (function, p, m)
def generate_new_policy(self):
'''
Generate a new random policy in the form of
[
(("Invert", 0.8, None), ("Contrast", 0.2, 6)),
(("Rotate", 0.7, 2), ("Invert", 0.8, None)),
(("Sharpness", 0.8, 1), ("Sharpness", 0.9, 3)),
(("ShearY", 0.5, 8), ("Invert", 0.7, None)),
]
'''
new_policy = [] new_policy = []
for _ in range(self.sp_num): for _ in range(self.sp_num):
# generate 2 operations for each subpolicy # generate 2 operations for each subpolicy
ops = [] ops = []
for i in range(2): for i in range(2):
new_op = generate_new_continuous_operation(self.fun_num) new_op = self.generate_new_continuous_operation(self.fun_num)
new_op = translate_operation_tensor(new_op) new_op = self.translate_operation_tensor(new_op)
ops.append(new_op) ops.append(new_op)
new_subpolicy = tuple(ops) new_subpolicy = tuple(ops)
......
...@@ -38,7 +38,8 @@ def create_toy(train_dataset, test_dataset, batch_size, n_samples, seed=100): ...@@ -38,7 +38,8 @@ def create_toy(train_dataset, test_dataset, batch_size, n_samples, seed=100):
def train_child_network(child_network, train_loader, test_loader, sgd, def train_child_network(child_network, train_loader, test_loader, sgd,
cost, max_epochs=2000, early_stop_num = 10, logging=False): cost, max_epochs=2000, early_stop_num = 10, logging=False,
print_every_epoch=True):
if torch.cuda.is_available(): if torch.cuda.is_available():
device = torch.device('cuda') device = torch.device('cuda')
else: else:
...@@ -102,12 +103,13 @@ def train_child_network(child_network, train_loader, test_loader, sgd, ...@@ -102,12 +103,13 @@ def train_child_network(child_network, train_loader, test_loader, sgd,
if early_stop_cnt >= early_stop_num: if early_stop_cnt >= early_stop_num:
break break
print('main.train_child_network best accuracy: ', best_acc) if print_every_epoch:
print('main.train_child_network best accuracy: ', best_acc)
acc_log.append(acc) acc_log.append(acc)
if logging: if logging:
return best_acc, acc_log return best_acc.item(), acc_log
return best_acc return best_acc.item()
if __name__=='__main__': if __name__=='__main__':
import MetaAugment.child_networks as cn import MetaAugment.child_networks as cn
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment