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 test_genome_visualization(self): """> Test if a genome from the population can be visualized.""" # Folder must be root to load in make_net properly if os.getcwd().split('\\')[-1] == 'tests': os.chdir('..') pop = get_population() genome = pop.best_genome if pop.best_genome else list( pop.population.values())[-1] visualize_genome( population=pop, genome=genome, debug=True, show=False, )
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
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