Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e32c106
commit 8d39a1a
Showing
8 changed files
with
1,156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
""" Class that keeps track of all genomes trained so far, and their scores. | ||
Among other things, ensures that genomes are unique. | ||
""" | ||
|
||
import random | ||
import logging | ||
|
||
from genome import Genome | ||
|
||
class AllGenomes(): | ||
"""Store all genomes | ||
""" | ||
|
||
def __init__(self, firstgenome): | ||
"""Initialize | ||
""" | ||
|
||
self.population = [] | ||
self.population.append(firstgenome) | ||
|
||
def add_genome(self, genome): | ||
"""Add the genome to our population. | ||
""" | ||
|
||
for i in range(0,len(self.population)): | ||
if (genome.hash == self.population[i].hash): | ||
logging.info("add_genome() ERROR: hash clash - duplicate genome") | ||
return False | ||
|
||
self.population.append(genome) | ||
|
||
return True | ||
|
||
def set_accuracy(self, genome): | ||
"""Add the genome to our population. | ||
""" | ||
|
||
for i in range(0,len(self.population)): | ||
if (genome.hash == self.population[i].hash): | ||
self.population[i].accuracy = genome.accuracy | ||
return | ||
|
||
logging.info("set_accuracy() ERROR: Genome not found") | ||
|
||
def is_duplicate(self, genome): | ||
"""Add the genome to our population. | ||
""" | ||
|
||
for i in range(0,len(self.population)): | ||
if (genome.hash == self.population[i].hash): | ||
return True | ||
|
||
return False | ||
|
||
def print_all_genomes(self): | ||
"""Print out a genome. | ||
""" | ||
|
||
for genome in self.population: | ||
genome.print_genome_ma() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
"""Iterate over every combination of hyperparameters.""" | ||
from __future__ import print_function | ||
import logging | ||
from genome import Genome | ||
from tqdm import tqdm | ||
|
||
# Setup logging. | ||
logging.basicConfig( | ||
format='%(asctime)s - %(levelname)s - %(message)s', | ||
datefmt='%m/%d/%Y %I:%M:%S %p', | ||
level=logging.INFO#, | ||
#filename='brute-log.txt' | ||
) | ||
|
||
def train_genomes(genomes, dataset): | ||
"""Train each network. | ||
Args: | ||
networks (list): Current population of networks | ||
dataset (str): Dataset to use for training/evaluating | ||
""" | ||
pbar = tqdm(total=len(genomes)) | ||
|
||
for genome in genomes: | ||
genome.train(dataset) | ||
genome.print_genome() | ||
pbar.update(1) | ||
pbar.close() | ||
|
||
# Sort our final population. | ||
genomes = sorted(genomes, key=lambda x: x.accuracy, reverse=True) | ||
|
||
# Print out the top 5 networks. | ||
print_genomes(genomes[:5]) | ||
|
||
def print_genomes(genomes): | ||
"""Print a list of networks. | ||
Args: | ||
networks (list): The population of networks | ||
""" | ||
logging.info('-'*80) | ||
for genome in genomes: | ||
genome.print_genome() | ||
|
||
def generate_genome_list(all_possible_genes): | ||
"""Generate a list of all possible networks. | ||
Args: | ||
all_possible_genes (dict): The parameter choices | ||
Returns: | ||
networks (list): A list of network objects | ||
""" | ||
genomes = [] | ||
|
||
# This is silly. | ||
for nbn in all_possible_genes['nb_neurons']: | ||
for nbl in all_possible_genes['nb_layers']: | ||
for a in all_possible_genes['activation']: | ||
for o in all_possible_genes['optimizer']: | ||
|
||
# Set the parameters. | ||
genome = { | ||
'nb_neurons': nbn, | ||
'nb_layers': nbl, | ||
'activation': a, | ||
'optimizer': o, | ||
} | ||
|
||
# Instantiate a network object with set parameters. | ||
genome_obj = Genome() | ||
genome_obj.set_genes_to(genome, 0, 0) | ||
genomes.append(genome_obj) | ||
|
||
return genomes | ||
|
||
def main(): | ||
"""Brute force test every network.""" | ||
dataset = 'cifar10_cnn' | ||
|
||
all_possible_genes = { | ||
'nb_neurons': [16, 32, 64, 128], | ||
'nb_layers': [1, 2, 3], | ||
'activation': ['relu', 'elu', 'tanh', 'sigmoid', 'hard_sigmoid','softplus','linear'], | ||
'optimizer': ['rmsprop', 'adam', 'sgd', 'adagrad', 'adadelta', 'adamax', 'nadam'], | ||
} | ||
|
||
logging.info("***Brute forcing networks***") | ||
|
||
genomes = generate_genome_list(all_possible_genes) | ||
|
||
train_genomes(genomes, dataset) | ||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import random | ||
import logging | ||
import hashlib | ||
|
||
|
||
children = [] | ||
|
||
#where do we recombine? 0, 1, 2, 3, 4? | ||
#with four genes, there are three choices for the recombination | ||
#0 and 4 just (re)create more copies of the parents | ||
# ___ * ____ * _____ * ____ | ||
#recomb_loc = random.randint(1,3) | ||
|
||
#print("rl ", recomb_loc) | ||
|
||
#for _ in range(2): #make _two_ children - could also make more? | ||
|
||
child1 = {} # {} = create empty dictionary | ||
child2 = {} | ||
|
||
all_possible_genes = { | ||
'optimizer': ['rmsprop', 'adam', 'sgd', 'adagrad','adadelta', 'adamax', 'nadam'], | ||
'nb_neurons': [64, 128, 256, 512, 768, 1024], | ||
'nb_layers': [1, 2, 3, 4], # only relevant to mlp | ||
'activation': ['relu', 'elu', 'tanh', 'sigmoid'] | ||
} | ||
|
||
#print(all_possible_genes['nb_layers']) | ||
#print(len(all_possible_genes)) | ||
|
||
#0 -> no recombination, and N == length of dictionary -> no recombination | ||
#so the range is always 1 to len(all_possible_genes) - 1 | ||
recomb_loc = random.randint(1,(len(all_possible_genes) - 1)) | ||
print("rl:", recomb_loc) | ||
|
||
#keys = ['nb_neurons', 'nb_layers', 'activation', 'optimizer'] | ||
#we can't make assumptions about the length/nature of the dictionary | ||
kn = list(all_possible_genes) | ||
print("keys bf:", kn) | ||
kn = sorted(kn) | ||
print("keys as:", kn) | ||
|
||
print("keys[]:", kn[0]) | ||
|
||
keys = ['nb_neurons', 'nb_layers', 'activation', 'optimizer'] | ||
|
||
print("keys[]:", keys[0]) | ||
|
||
print("keys[] b:", keys) | ||
print("keys[] s:", keys.sort()) | ||
|
||
mom = {'nb_neurons': 128, 'nb_layers': 4, 'activation': 'tanh', 'optimizer': 'adadelta'} | ||
dad = {'nb_neurons': 64, 'nb_layers': 2, 'activation': 'sigm', 'optimizer': 'bedelta'} | ||
|
||
print(str(dad['nb_neurons'])+dad['activation']) | ||
print(str(mom['nb_neurons'])+mom['activation']) | ||
|
||
gen = str(dad['nb_neurons'])+dad['activation'] | ||
hash_object = hashlib.md5(gen) | ||
print(hash_object.hexdigest()) | ||
|
||
gen = str(mom['nb_neurons'])+mom['activation'] | ||
hash_object = hashlib.md5(gen) | ||
print(hash_object.hexdigest()) | ||
|
||
|
||
for x in range(0, len(all_possible_genes)): | ||
if x < recomb_loc: | ||
child1[keys[x]] = mom[keys[x]]#mom.genome[keys[x-1]] | ||
child2[keys[x]] = dad[keys[x]]#dad.genome[keys[x-1]] | ||
else: | ||
child1[keys[x]] = dad[keys[x]]#dad.genome[keys[x-1]] | ||
child2[keys[x]] = mom[keys[x]]#mom.genome[keys[x-1]] | ||
|
||
print(mom) | ||
print(dad) | ||
print(child1) | ||
print(child2) | ||
|
||
#for key in all_possible_genes: | ||
# print(random.choice(all_possible_genes[key])) | ||
# child1[key] = random.choice(all_possible_genes[key]) | ||
|
||
#print("keys[0]: ", keys[0]) | ||
|
||
#print(child1[keys[0]]) | ||
|
||
# nb_layers = genome['nb_layers'] | ||
# nb_neurons = genome['nb_neurons'] | ||
# activation = genome['activation'] | ||
# optimizer = genome['optimizer'] | ||
|
||
# all_possible_genes (dict): Parameters for the genome, includes: | ||
# gene_nb_neurons (list): [64, 128, 256] | ||
# gene_nb_layers (list): [1, 2, 3, 4] | ||
# gene_activation (list): ['relu', 'elu'] | ||
# gene_optimizer (list): ['rmsprop', 'adam'] | ||
|
||
# is there much more elegant way to do this - yes of course. | ||
|
||
# if recomb_loc == 1: | ||
# child1['nb_layers' ] = mom.genome['nb_layers' ] | ||
# child1['nb_neurons'] = dad.genome['nb_neurons'] | ||
# child1['activation'] = dad.genome['activation'] | ||
# child1['optimizer' ] = dad.genome['optimizer' ] |
Oops, something went wrong.