def train(topology_id: int, batch_size: int = 1000, unused_cpu: int = 2, use_backup: bool = False): """Create an infinite amount of genomes for the requested topology.""" # Get the config cfg = get_config() # Get initial genome key g_key, csv_path = get_initial_keys(topology_id, use_backup=use_backup) # Setup the environment _, games = get_game_ids(experiment_id=6) multi_env = get_multi_env(config=cfg) multi_env.set_games(games, noise=False) # Create genomes t = time.localtime() print(f"\nCurrent time: {t.tm_hour:02d}h-{t.tm_min:02d}m-{t.tm_sec:02d}s") print( f"> Evaluating {batch_size} genomes in csv '{csv_path.split('/')[-1]}'" ) genomes = list( iteritems({ g_key + i: get_genome(topology_id, g_id=g_key + i, cfg=cfg) for i in range(batch_size) })) g_key += batch_size # Evaluate the genome-dictionary in parallel try: pool = mp.Pool(mp.cpu_count() - unused_cpu) manager = mp.Manager() return_dict = manager.dict() for genome in genomes: pool.apply_async(func=multi_env.eval_genome, args=(genome, return_dict)) pool.close() # Close the pool pool.join() # Postpone continuation until everything is finished # Calculate the fitness from the given return_dict fitness = calc_pop_fitness( fitness_cfg=cfg.evaluation, game_cfg=cfg.game, game_obs=return_dict, ) for i, genome in genomes: genome.fitness = fitness[i] # Write the result to CSV with open(csv_path, 'a', newline='') as f: writer = csv.writer(f) for _, g in genomes: writer.writerow( get_genome_parameters(g, topology_id=topology_id)) except KeyboardInterrupt: # Remove the temporary CSV first os.remove(csv_path) raise KeyboardInterrupt
def evaluate_generations(name, experiment_id, folder=None, hops: int = 10, unused_cpu: int = 2): """ Evaluate the population across its lifetime. At each generation, the ten best genomes are evaluated together with the elite genome of the past five generations. :param name: Name of the population :param experiment_id: Experiment for which the population is trained (and now will be evaluated) :param folder: Population-folder (~experiment level) :param hops: Number of generations between each saved population :param unused_cpu: Number of CPU cores not used """ # Fetch population and evaluation games folder = folder if folder else get_folder(experiment_id) pop = Population( name=name, folder_name=folder, log_print=False, use_backup=True, ) _, game_ids_eval = get_game_ids(experiment_id=experiment_id) # Perform the evaluations max_gen = pop.generation for gen in tqdm(range(0, max_gen + 1, hops)): # Load in the current generation if not pop.load(gen=gen): raise Exception( f"Population {name} is not trained for generation {gen}") # Collect the used genomes if gen > 5: genomes = sorted([g for g in pop.population.values()], key=lambda x: x.fitness if x.fitness else 0, reverse=True)[:10] for i in range(1, 6): keys = [g.key for g in genomes] g = copy.deepcopy(pop.best_genome_hist[gen - i] [1]) # Copy since chance of mutation while g.key in keys: # Already added to genomes, update keys g.key += 1 genomes.append(g) else: # No history yet, use only the ten most fit genomes from the current generation genomes = sorted([g for g in pop.population.values()], key=lambda x: x.fitness if x.fitness else 0, reverse=True)[:15] # Evaluate the selected genomes evaluate( population=pop, games=game_ids_eval, genomes=genomes, unused_cpu=unused_cpu, overwrite=True, )
def evaluate_population(pop: Population, cfg: Config, cpu: int, experiment_id: int): """Evaluate the given population.""" pop.log(f"{pop.name} - Evaluating the population...") _, game_ids_eval = get_game_ids(experiment_id=experiment_id) multi_env = get_multi_env(pop=pop, game_config=cfg) multi_env.set_games(game_ids_eval, noise=False) pool = mp.Pool(mp.cpu_count() - cpu) manager = mp.Manager() return_dict = manager.dict() pbar = tqdm(total=len(pop.population), desc="Evaluating") def update(*_): pbar.update() for genome_id, genome in pop.population.items(): pool.apply_async(func=multi_env.eval_genome, args=((genome_id, genome), return_dict), callback=update) pool.close() # Close the pool pool.join() # Postpone continuation until everything is finished pbar.close() # Calculate the fitness from the given return_dict pop.log(f"{pop.name} - Calculating fitness scores...") fitness = calc_pop_fitness( fitness_cfg=pop.config.evaluation, game_cfg=cfg.game, game_obs=return_dict, gen=pop.generation, ) for i, genome in pop.population.items(): genome.fitness = fitness[i] # Get the fittest genome best = None for g in pop.population.values(): if best is None or g.fitness > best.fitness: best = g pop.best_genome = best # Save the results pop.save() # Visualize most fit genome visualize_genome( debug=True, genome=best, population=pop, ) # Trace the most fit genome trace_most_fit( debug=False, games=game_ids_eval, genome=best, population=pop, unused_cpu=cpu, )
def simulation(cython: bool = False, parallel: bool = False): """Execute a simulation of one training iteration.""" # Create the population cfg = Config() cfg.game.duration = 200 cfg.update() pop = Population( name="delete_me", config=cfg, folder_name="test_performance", use_backup=True, overwrite=True, # Every iteration, create a new population from scratch ) # Perform the simulations of experiment3 train_games, _ = get_game_ids(experiment_id=3) if cython: multi_env = MultiEnvironmentCy(game_config=cfg, pop_config=pop.config) else: multi_env = MultiEnvironment(game_config=cfg, pop_config=pop.config) multi_env.set_games(train_games, noise=True) # Prepare the generation's reporters for the generation pop.reporters.start_generation(gen=pop.generation, logger=pop.log) # Fetch the dictionary of genomes genomes = list(iteritems(pop.population)) if parallel: # Initialize the evaluation-pool pool = mp.Pool(mp.cpu_count()) manager = mp.Manager() return_dict = manager.dict() for genome in genomes: pool.apply_async(func=multi_env.eval_genome, args=(genome, return_dict)) pool.close() # Close the pool pool.join() # Postpone continuation until everything is finished else: return_dict = dict() for genome in genomes: multi_env.eval_genome(genome, return_dict) path = f"population_backup/storage/test_performance/" if os.path.exists(path): shutil.rmtree(path)
# Get game's blueprint game.get_blueprint(show_player=True) plt.title("Blueprint - Game {id:05d}".format(id=game.id)) plt.savefig(f'environment/visualizations/blueprint_game{game.id:05d}') if show: plt.show() plt.close() if __name__ == '__main__': os.chdir("../..") cfg = Config() games = [0] # Game Dummy # Experiment 1 exp1_train, exp1_eval = get_game_ids(1) games += exp1_train[:1] # Repeats itself games += exp1_eval # Experiment 2 exp2_train, exp2_eval = get_game_ids(2) games += exp2_train[:1] # Repeats itself games += exp2_eval # Experiment 3 exp3_train, exp3_eval = get_game_ids(3) games += exp3_train[:1] # Repeats itself games += exp3_eval # Experiment 6 exp6_train, exp6_eval = get_game_ids(6)
def main( fitness, prob_gru: float, prob_gru_nr: float, prob_gru_nu: float, prob_simple_rnn: float, train_iterations=0, version=0, unused_cpu=1, ): """ Run a population's configuration. :param fitness: Fitness function used to evaluate the population :param prob_gru: Probability of mutating towards a GRU-node :param prob_gru_nr: Probability of mutating towards a GRU-NR-node :param prob_gru_nu: Probability of mutating towards a GRU-NU-node :param prob_simple_rnn: Probability of mutating towards a SimpleRNN-node :param train_iterations: Number of training generations :param version: Version of the model :param unused_cpu: Number of CPUs not used during training """ # Re-configure the config-file cfg = Config() cfg.bot.angular_dir = [] cfg.bot.delta_dist_enabled = False cfg.bot.dist_enabled = True cfg.game.duration = 60 # 60 seconds should be enough to reach the target from each starting orientation cfg.genome.node_add_prob = 0 # Do not change number of hidden nodes cfg.genome.node_disable_prob = 0 # Do not change number of hidden nodes cfg.population.pop_size = 512 cfg.population.compatibility_thr = 1. # Very small since all architectures have strictly one hidden node # Let inputs apply to configuration cfg.genome.rnn_prob_gru = prob_gru cfg.genome.rnn_prob_gru_nr = prob_gru_nr cfg.genome.rnn_prob_gru_nu = prob_gru_nu cfg.genome.rnn_prob_simple_rnn = prob_simple_rnn cfg.evaluation.fitness = fitness cfg.update() # Create the population folder = get_folder(experiment_id=4) name = get_name(cfg=cfg, version=version) pop = Population( name=name, config=cfg, folder_name=folder, use_backup=False, ) # Make sure that all of the genomes in the initial population have exactly one hidden node if pop.generation == 0: for g in pop.population.values(): g.mutate_add_node(pop.config.genome) # Give overview of population gru = cfg.genome.rnn_prob_gru gru_nr = cfg.genome.rnn_prob_gru_nr gru_nu = cfg.genome.rnn_prob_gru_nu rnn = cfg.genome.rnn_prob_simple_rnn msg = f"\n\n\n\n\n===> RUNNING EXPERIMENT 4 FOR THE FOLLOWING CONFIGURATION: <===" \ f"\n\t> fitness: {cfg.evaluation.fitness}" \ f"\n\t> GRU enabled: {gru > 0} (probability={round(gru, 2)})" \ f"\n\t> GRU-NR enabled: {gru_nr > 0} (probability={round(gru_nr, 2)})" \ f"\n\t> GRU-NU enabled: {gru_nu > 0} (probability={round(gru_nu, 2)})" \ f"\n\t> SRU enabled: {rnn > 0} (probability={round(rnn, 2)})" \ f"\n\t> Saving under folder: {folder}" \ f"\n\t> Training iterations: {train_iterations}\n" pop.log(msg) # Set games used for evaluation games_train, games_eval = get_game_ids(experiment_id=4) # Execute the requested segments try: train( game_config=cfg, games=games_train, iterations=train_iterations, population=pop, unused_cpu=unused_cpu, ) # Evaluate the trained population evaluate( games=games_eval, population=pop, unused_cpu=unused_cpu, ) training_overview(population=pop, ) visualize_genome( genome=pop.best_genome, population=pop, ) # Perform GRU-analysis if population is NEAT-GRU if gru > 0: gru_analysis( population=pop, unused_cpu=unused_cpu, experiment_id=4, ) monitor( game_id=games_eval[0], population=pop, genome=pop.best_genome, ) except Exception as e: pop.log(traceback.format_exc(), print_result=False) raise e finally: process_killer('run_population.py') # Close all the terminated files
plt.imshow(result) plt.tight_layout() plt.savefig(f"{path[:-1]}.png", bbox_inches='tight', pad_inches=0) plt.close() if __name__ == '__main__': parser = argparse.ArgumentParser(description='') parser.add_argument('--game_id', type=int, default=10002) parser.add_argument('--debug', type=bool, default=False) args = parser.parse_args() # Go back to root os.chdir("../../../") _, eval_games = get_game_ids(experiment_id=4) # Create the population config = Config() pop = Population( name='test', # name='NEAT-SRU/v1', folder_name='test', # folder_name=get_folder(args.experiment), config=config, ) chosen_genome = pop.best_genome # chosen_genome = pop.population[47280] # Run the monitor-tool main(
def main( fitness, prob_gru: float, prob_sru: float, prob_lstm: float, version=0, unused_cpu=1, ): """ Run a population's configuration. :param fitness: Fitness function used to evaluate the population :param prob_gru: Probability of mutating towards a GRU-node :param prob_sru: Probability of mutating towards a SRU-node :param prob_lstm: Probability of mutating towards a LSTM-node :param version: Version of the model :param unused_cpu: Number of CPUs not used during training """ # Re-configure the config-file cfg = Config() cfg.bot.angular_dir = [] cfg.bot.delta_dist_enabled = False cfg.bot.dist_enabled = True cfg.game.duration = 60 # 60 seconds should be enough to reach the target from each starting orientation cfg.population.pop_size = 512 # Let inputs apply to configuration cfg.genome.rnn_prob_gru = prob_gru cfg.genome.rnn_prob_simple_rnn = prob_sru cfg.genome.rnn_prob_lstm = prob_lstm cfg.evaluation.fitness = fitness cfg.update() # Copy population over from experiment1 name = get_name(cfg=cfg, version=version) path_exp1 = f'population/storage/experiment1/{name}/' if not os.path.exists(path_exp1): raise Exception( f"Experiment 1 must be executed first for population {name}, terminating experiment 2..." ) # Population exists in experiment1, copy over to experiment2 (change experiment1 population's folder and save) pop = Population(name=name, config=cfg, folder_name=get_folder(experiment_id=1), use_backup=False) assert pop.generation > 0 # Population is not new (redundant check) folder = get_folder(experiment_id=2) pop.folder_name = folder pop.save() # Overrides pre-existing populations! # Copy over all generations as well, since these are used during population evaluation path = f"population{'_backup' if pop.use_backup else ''}/storage/{pop.folder_name}/{pop}/" copy_tree(f"{path_exp1}generations", f"{path}generations") # Give overview of population gru = cfg.genome.rnn_prob_gru sru = cfg.genome.rnn_prob_simple_rnn lstm = cfg.genome.rnn_prob_lstm msg = f"\n\n\n\n\n===> RUNNING EXPERIMENT 2 FOR THE FOLLOWING CONFIGURATION: <===" \ f"\n\t> fitness: {cfg.evaluation.fitness}" \ f"\n\t> GRU enabled: {gru > 0} (probability={round(gru, 2)})" \ f"\n\t> SRU enabled: {sru > 0} (probability={round(sru, 2)})" \ f"\n\t> LSTM enabled: {lstm > 0} (probability={round(lstm, 2)})" \ f"\n\t> Saving under folder: {folder}\n" pop.log(msg) # Set games used for evaluation _, games_eval = get_game_ids(experiment_id=2) # Execute the requested segments try: # Evaluate the trained population evaluate( games=games_eval, population=pop, unused_cpu=unused_cpu, ) except Exception as e: pop.log(traceback.format_exc(), print_result=False) raise e finally: process_killer('run_population.py') # Close all the terminated files
def main(pop_name: str, version: int, unused_cpu: int = 2, use_backup: bool = False): # Check if valid population name if pop_name not in SUPPORTED: raise Exception(f"Population '{pop_name}' not supported!") # Create the population cfg = get_config() cfg.population.specie_elitism = 1 folder = get_folder(experiment_id=7) pop = Population( name=f'{pop_name}/v{version}', config=cfg, folder_name=folder, use_backup=use_backup, ) # Replace the population's initial population with the requested topologies genomes if pop.generation == 0: for g_id in pop.population.keys(): pop.population[g_id] = get_topology(pop_name, gid=g_id, cfg=cfg) pop.species.speciate(config=pop.config, population=pop.population, generation=pop.generation, logger=pop.log) pop.log(f"\n\n\n===> RUNNING EXPERIMENT 7 <===\n") # Set games and environment used for training and evaluation games_train, games_eval = get_game_ids(experiment_id=7) train_env = get_multi_env(config=cfg) eval_env = get_multi_env(config=cfg) eval_env.set_games(games_eval, noise=False) solution_found = False while not solution_found: # Train the population for a single iteration pop.log("\n===> TRAINING <===") train_env.set_games(games_train, noise=True) # Prepare the generation's reporters for the generation pop.reporters.start_generation(gen=pop.generation, logger=pop.log) # Fetch the dictionary of genomes genomes = list(iteritems(pop.population)) # Initialize the evaluation-pool pool = mp.Pool(mp.cpu_count() - unused_cpu) manager = mp.Manager() return_dict = manager.dict() for genome in genomes: pool.apply_async(func=train_env.eval_genome, args=(genome, return_dict)) pool.close() # Close the pool pool.join() # Postpone continuation until everything is finished # Calculate the fitness from the given return_dict fitness = calc_pop_fitness( fitness_cfg=pop.config.evaluation, game_cfg=cfg.game, game_obs=return_dict, gen=pop.generation, ) for i, genome in genomes: genome.fitness = fitness[i] # Update the population's best_genome best = None for g in itervalues(pop.population): if best is None or g.fitness > best.fitness: best = g pop.reporters.post_evaluate(population=pop.population, species=pop.species, best_genome=best, logger=pop.log) # Update the population's best_genome genomes = sorted(pop.population.items(), key=lambda x: x[1].fitness, reverse=True) pop.best_fitness[pop.generation] = genomes[0][1].fitness pop.best_genome_hist[pop.generation] = genomes[0] pop.best_genome = best # Let population evolve evolve(pop, pop_name) # End generation pop.reporters.end_generation(population=pop.population, name=str(pop), species_set=pop.species, logger=pop.log) # Test if evaluation finds a solution for the new generation, impossible if fitness < 0.7 if pop.best_genome.fitness > 0.7 or pop.generation % 10 == 0: pop.log("\n===> EVALUATING <===") genomes = list(iteritems(pop.population)) pool = mp.Pool(mp.cpu_count() - unused_cpu) manager = mp.Manager() return_dict = manager.dict() for genome in genomes: pool.apply_async(func=eval_env.eval_genome, args=(genome, return_dict)) pool.close() # Close the pool pool.join() # Postpone continuation until everything is finished # Calculate the fitness from the given return_dict finished = calc_finished_ratio( fitness_cfg=cfg.evaluation, game_obs=return_dict, ) best = None for i, genome in genomes: genome.fitness = finished[i] if best is None or finished[i] > best.fitness: best = genome pop.log(f"Best genome:\n{best}\n{best.nodes[2]}") # Solution is found if best.fitness == 1: pop.best_genome = best pop.log(f"Solution found!") solution_found = True # End the outer while-loop # Save the population with their evaluation results pop.save()
def main(topology_id: int, iterations: int, eval_interval: int, experiment_id: int, hops: float = 0.1, weight_range: float = 1, mutate_combine: bool = False, mutate_bias: bool = True, mutate_reset: bool = True, mutate_update: bool = True, mutate_candidate: bool = True, init_population_size: int = 1000, unused_cpu: int = 2): """ Run the fifth experiment. :param topology_id: Chosen topology to investigate :param iterations: Number of training iterations performed :param eval_interval: After how much training iterations evaluation is performed :param experiment_id: ID of the experiment used to train and evaluate the population on :param hops: Hops between variable-configurations :param weight_range: Range of deviation for one's weights :param mutate_combine: Combine the best results of each mutation type :param mutate_bias: Mutate the GRU's bias values :param mutate_reset: Mutate the reset-gate's weights :param mutate_update: Mutate the update-gate's weights :param mutate_candidate: Mutate the candidate-state's weights :param init_population_size: Initial size of the randomized population :param unused_cpu: Number of CPU-cores not used """ # Get the population name = f"experiment{experiment_id}_topology{topology_id}_hops{hops}_range{weight_range}" pop = Population( name=name, folder_name='experiment5', use_backup=False, ) # Define the games specific to the experiment _, game_ids_eval = get_game_ids(experiment_id=experiment_id) # Set the genomes if population is new if pop.generation == 0: # Get the requested topology-type if topology_id == 1: topology = get_topology1 elif topology_id == 2: topology = get_topology2 else: raise Exception(f"Topology {topology_id} not supported.") # Initialize the population with a randomized population pop.population = dict() for gid in range(init_population_size): new_genome = topology(pop.config, random_init=True) new_genome.key = gid pop.population[gid] = new_genome # Perform an initial training train_population(pop=pop, games=game_ids_eval, unused_cpu=unused_cpu) pop.generation = 0 # Don't count initial training as a generation # Get the fittest genome best = None for g in pop.population.values(): if best is None or g.fitness > best.fitness: best = g pop.best_genome = best visualize_best_genome(pop=pop) # Test the initial population test_population(pop=pop, games=game_ids_eval) # Set the most fit genome as the starting-point set_population(pop=pop, hops=hops, weight_range=weight_range, mutate_bias=mutate_bias, mutate_reset=mutate_reset, mutate_update=mutate_update, mutate_candidate=mutate_candidate) # Evaluate the population for i in range(iterations): train_population(pop=pop, games=game_ids_eval, unused_cpu=unused_cpu) evaluate_fitness(pop=pop, hops=hops, weight_range=weight_range, mutate_combine=mutate_combine, mutate_bias=mutate_bias, mutate_reset=mutate_reset, mutate_update=mutate_update, mutate_candidate=mutate_candidate) visualize_best_genome(pop=pop) if pop.generation % eval_interval == 0: test_population(pop=pop, games=game_ids_eval) set_population(pop=pop, hops=hops, weight_range=weight_range, mutate_bias=mutate_bias, mutate_reset=mutate_reset, mutate_update=mutate_update, mutate_candidate=mutate_candidate)
def main(topology_id: int, batch_size: int = 1000, train_batch: int = 3, min_finished: float = MIN_FINISHED, unused_cpu: int = 2, save_pop: bool = False, use_backup: bool = False): """Run a population infinitely long and store all its good genomes.""" # Get the CSV used to store the results in csv_path, csv_name, added = get_csv_path(topology_id, use_backup=use_backup, batch_size=batch_size) # Create the population name = csv_name if save_pop else 'dummy' cfg = get_config() folder = get_folder(experiment_id=6) pop = Population( name=name, config=cfg, folder_name=folder, use_backup=use_backup, overwrite=True, # Every iteration, create a new population from scratch ) # Replace the population's initial population with the requested topologies genomes for g_id in pop.population.keys(): pop.population[g_id] = get_genome(topology_id, g_id=g_id, cfg=cfg) pop.species.speciate(config=pop.config, population=pop.population, generation=pop.generation, logger=pop.log) # Set games and environment used for training and evaluation pop.log(f"\n\n\n===> RUNNING EXPERIMENT 6 <===\n") games_train, games_eval = get_game_ids(experiment_id=6) train_env = get_multi_env(config=cfg) eval_env = get_multi_env(config=cfg) eval_env.set_games(games_eval, noise=False) # Keep training and evolving the network until the complete CSV is filled last_saved = pop.generation try: while added < batch_size: t = time.localtime() pop.log(f"\n\n===> Selective genome creation at {added / batch_size * 100}%, " f"storing in csv '{csv_path.split('/')[-1]}' " f"({t.tm_hour:02d}h-{t.tm_min:02d}m-{t.tm_sec:02d}s) <===") # Train the population pop.log("\n===> Training <===") for _ in tqdm(range(train_batch), desc="Training"): train_env.set_games(games_train, noise=True) genomes = list(iteritems(pop.population)) # Initialize the evaluation-pool pool = mp.Pool(mp.cpu_count() - unused_cpu) manager = mp.Manager() return_dict = manager.dict() for genome in genomes: pool.apply_async(func=train_env.eval_genome, args=(genome, return_dict)) pool.close() # Close the pool pool.join() # Postpone continuation until everything is finished # Calculate the fitness from the given return_dict fitness = calc_pop_fitness( fitness_cfg=pop.config.evaluation, game_cfg=cfg.game, game_obs=return_dict, gen=pop.generation, ) for i, genome in genomes: genome.fitness = fitness[i] # Update the population's best_genome best = None for g in itervalues(pop.population): if best is None or g.fitness > best.fitness: best = g genomes = sorted(pop.population.items(), key=lambda x: x[1].fitness, reverse=True) pop.best_fitness[pop.generation] = genomes[0][1].fitness pop.best_genome_hist[pop.generation] = genomes[0] pop.best_genome = best pop.log(f"Best training fitness: {best.fitness}") # Let population evolve pop.evolve() # Constraint each of the population's new genomes to the given topology for g in pop.population.values(): enforce_topology(g, topology_id=topology_id) # Save the population after training if pop.generation - last_saved >= 100: pop.save() last_saved = pop.generation # Evaluate the current population as was done in experiment6 pop.log("\n===> EVALUATING <===") genomes = list(iteritems(pop.population)) pool = mp.Pool(mp.cpu_count() - unused_cpu) manager = mp.Manager() return_dict = manager.dict() for genome in genomes: pool.apply_async(func=eval_env.eval_genome, args=(genome, return_dict)) pool.close() # Close the pool pool.join() # Postpone continuation until everything is finished # Calculate the fitness from the given return_dict finished = calc_finished_ratio( fitness_cfg=cfg.evaluation, game_obs=return_dict, ) best = None for i, genome in genomes: genome.fitness = finished[i] if best is None or finished[i] > best.fitness: best = genome # Give evaluation overview of population pop.log(f"Best evaluation finish ratio: {round(best.fitness, 2)}") best_str = str(best).replace("\n", "\n\t") best_str += "\n\t" + str(best.nodes[2]).replace("\n", "\n\t") pop.log(f"Best genome: \n\t{best_str}") sids = list(iterkeys(pop.species.species)) sids.sort() msg = f"\nPopulation '{name}' has {len(pop.species.species):d} species:" \ f"\n\t specie age size finished stag " \ f"\n\t======== ===== ====== ========== ======" pop.log(msg) if pop.log else print(msg) for sid in sids: s = pop.species.species[sid] a = pop.generation - s.created n = len(s.members) sf = [g.fitness for g in s.members.values() if g.fitness] f = "--" if len(sf) == 0 else f"{max(sf):.2f}" st = pop.generation - s.last_improved msg = f"\t{sid:^8} {a:^5} {n:^6} {f:^10} {st:^6}" pop.log(msg) if pop.log else print(msg) # Write the result to CSV with open(csv_path, 'a', newline='') as f: writer = csv.writer(f) for _, g in genomes: # Only write the genomes that exceed the minimum 'finished ratio' threshold! if g.fitness >= min_finished: writer.writerow(get_genome_parameters(g, topology_id=topology_id)) added += 1 finally: # Remove the dummy population if it exists pop.save() path = f"population{'_backup' if use_backup else ''}/storage/{pop.folder_name}/dummy/" if os.path.exists(path): shutil.rmtree(path)
def main( fitness, prob_gru: float, prob_sru: float, prob_lstm: float, train_iterations=0, version=0, unused_cpu=1, ): """ Run a population's configuration. :param fitness: Fitness function used to evaluate the population :param prob_gru: Probability of mutating towards a GRU-node :param prob_sru: Probability of mutating towards a SRU-node :param prob_lstm: Probability of mutating towards a LSTM-node :param train_iterations: Number of training generations :param version: Version of the model :param unused_cpu: Number of CPUs not used during training """ # Re-configure the config-file cfg = Config() cfg.bot.angular_dir = [] cfg.bot.delta_dist_enabled = False cfg.bot.dist_enabled = True cfg.game.duration = 60 # 60 seconds should be enough to reach the target from each starting orientation cfg.population.pop_size = 512 # Let inputs apply to configuration cfg.genome.rnn_prob_gru = prob_gru cfg.genome.rnn_prob_simple_rnn = prob_sru cfg.genome.rnn_prob_lstm = prob_lstm cfg.evaluation.fitness = fitness cfg.update() # Create the population folder = get_folder(experiment_id=1) name = get_name(cfg=cfg, version=version) pop = Population( name=name, config=cfg, folder_name=folder, use_backup=False, ) # Give overview of population gru = cfg.genome.rnn_prob_gru sru = cfg.genome.rnn_prob_simple_rnn lstm = cfg.genome.rnn_prob_lstm msg = f"\n\n\n\n\n===> RUNNING EXPERIMENT 1 FOR THE FOLLOWING CONFIGURATION: <===" \ f"\n\t> fitness: {cfg.evaluation.fitness}" \ f"\n\t> GRU enabled: {gru > 0} (probability={round(gru, 2)})" \ f"\n\t> SRU enabled: {sru > 0} (probability={round(sru, 2)})" \ f"\n\t> LSTM enabled: {lstm > 0} (probability={round(lstm, 2)})" \ f"\n\t> Saving under folder: {folder}" \ f"\n\t> Training iterations: {train_iterations}\n" pop.log(msg) # Set games used for evaluation games_train, games_eval = get_game_ids(experiment_id=1) # Execute the requested segments try: train( debug=False, games=games_train, iterations=train_iterations, population=pop, unused_cpu=unused_cpu, ) # Evaluate the trained population evaluate( games=games_eval, population=pop, unused_cpu=unused_cpu, ) training_overview(population=pop, ) visualize_genome( genome=pop.best_genome, population=pop, ) except Exception as e: pop.log(traceback.format_exc(), print_result=False) raise e finally: process_killer('run_population.py') # Close all the terminated files