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
__pycache__/
**/__pycache__/
**/datasets/
*.py[cod]
*$py.class
*.pyc
......
......@@ -14,6 +14,8 @@ import pygad.torchga as torchga
import random
import copy
from MetaAugment.main import *
# import MetaAugment.child_networks as child_networks
# from MetaAugment.main import *
......@@ -53,8 +55,10 @@ class Learner(nn.Module):
self.relu3 = nn.ReLU()
self.fc2 = nn.Linear(120, 84)
self.relu4 = nn.ReLU()
self.fc3 = nn.Linear(84, 13)
self.fc3 = nn.Linear(84, num_transforms + 21)
# self.sig = nn.Sigmoid()
# Currently using discrete outputs for the probabilities
def forward(self, x):
......@@ -157,90 +161,13 @@ def train_model(transform_idx, p, child_network):
epoch = 20
best_acc = train_child_network(child_network, train_loader, test_loader, sgd, cost, max_epochs=100)
return best_acc
best_acc = train_child_network(child_network, train_loader, test_loader,
sgd, cost, max_epochs=100, print_every_epoch=False)
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
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
......
No preview for this file type
......@@ -53,109 +53,114 @@ class aa_learner:
# TODO: We should probably use a different way to store results than 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
[
(("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)),
]
generate a new random operation in the form of a tensor of dimension:
(fun_num + 11 + 10)
The first fun_num dimensions is a 1-hot encoding to specify which function to use.
The next 11 dimensions specify which 'probability' to choose.
(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):
'''
generate a new random operation in the form of a tensor of dimension:
(fun_num + 11 + 10)
The first fun_num dimensions is a 1-hot encoding to specify which function to use.
The next 11 dimensions specify which 'probability' to choose.
(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
return torch.cat([fun_t, prob_t, mag_t])
return torch.cat([fun_t, prob_t, mag_t])
def generate_new_continuous_operation(self, fun_num=14, p_bins=10, m_bins=10):
'''
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 generate_new_continuous_operation(fun_num=14, p_bins=10, m_bins=10):
'''
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,
def translate_operation_tensor(self, operation_tensor, fun_num=14,
p_bins=10, m_bins=10,
discrete_p_m=False):
'''
takes in a tensor representing a operation and returns an actual operation which
is in the form of:
("Invert", 0.8, None)
or
("Contrast", 0.2, 6)
Args:
operation_tensor
continuous_p_m (boolean): whether the operation_tensor has continuous representations
of probability and magnitude
'''
# if input operation_tensor is discrete
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
'''
takes in a tensor representing a operation and returns an actual operation which
is in the form of:
("Invert", 0.8, None)
or
("Contrast", 0.2, 6)
Args:
operation_tensor
continuous_p_m (boolean): whether the operation_tensor has continuous representations
of probability and magnitude
'''
# if input operation_tensor is discrete
if discrete_p_m:
fun_t = operation_tensor[:fun_num]
p = operation_tensor[-2].item() # 0 < p < 1
m = operation_tensor[-1].item() # 0 < m < 9
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) # 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)
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)
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 = []
for _ in range(self.sp_num):
# generate 2 operations for each subpolicy
ops = []
for i in range(2):
new_op = generate_new_continuous_operation(self.fun_num)
new_op = translate_operation_tensor(new_op)
new_op = self.generate_new_continuous_operation(self.fun_num)
new_op = self.translate_operation_tensor(new_op)
ops.append(new_op)
new_subpolicy = tuple(ops)
......
......@@ -57,109 +57,113 @@ class randomsearch_learner:
# TODO: We should probably use a different way to store results than 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
[
(("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)),
]
generate a new random operation in the form of a tensor of dimension:
(fun_num + 11 + 10)
The first fun_num dimensions is a 1-hot encoding to specify which function to use.
The next 11 dimensions specify which 'probability' to choose.
(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):
'''
generate a new random operation in the form of a tensor of dimension:
(fun_num + 11 + 10)
The first fun_num dimensions is a 1-hot encoding to specify which function to use.
The next 11 dimensions specify which 'probability' to choose.
(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
return torch.cat([fun_t, prob_t, mag_t])
return torch.cat([fun_t, prob_t, mag_t])
def generate_new_continuous_operation(self, fun_num=14, p_bins=10, m_bins=10):
'''
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 generate_new_continuous_operation(fun_num=14, p_bins=10, m_bins=10):
'''
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,
def translate_operation_tensor(self, operation_tensor, fun_num=14,
p_bins=10, m_bins=10,
discrete_p_m=False):
'''
takes in a tensor representing a operation and returns an actual operation which
is in the form of:
("Invert", 0.8, None)
or
("Contrast", 0.2, 6)
Args:
operation_tensor
continuous_p_m (boolean): whether the operation_tensor has continuous representations
of probability and magnitude
'''
# if input operation_tensor is discrete
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
'''
takes in a tensor representing a operation and returns an actual operation which
is in the form of:
("Invert", 0.8, None)
or
("Contrast", 0.2, 6)
Args:
operation_tensor
continuous_p_m (boolean): whether the operation_tensor has continuous representations
of probability and magnitude
'''
# if input operation_tensor is discrete
if discrete_p_m:
fun_t = operation_tensor[:fun_num]
p = operation_tensor[-2].item() # 0 < p < 1
m = operation_tensor[-1].item() # 0 < m < 9
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) # 0 <= p <= 10
mag = torch.argmax(mag_t) # 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)
fun = augmentation_space[fun][0]
prob = prob/10
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 = []
for _ in range(self.sp_num):
# generate 2 operations for each subpolicy
ops = []
for i in range(2):
new_op = generate_new_continuous_operation(self.fun_num)
new_op = translate_operation_tensor(new_op)
new_op = self.generate_new_continuous_operation(self.fun_num)
new_op = self.translate_operation_tensor(new_op)
ops.append(new_op)
new_subpolicy = tuple(ops)
......
......@@ -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,
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():
device = torch.device('cuda')
else:
......@@ -102,12 +103,13 @@ def train_child_network(child_network, train_loader, test_loader, sgd,
if early_stop_cnt >= early_stop_num:
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)
if logging:
return best_acc, acc_log
return best_acc
return best_acc.item(), acc_log
return best_acc.item()
if __name__=='__main__':
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