Пример #1
0
def train_population(pop: Population, games: list, unused_cpu: int = 2):
    """Evaluate the given population on a training set."""
    multi_env = get_multi_env(pop=pop, game_config=pop.config)
    multi_env.set_games(games, noise=False)
    pool = mp.Pool(mp.cpu_count() - unused_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
    fitness = calc_pop_fitness(
        fitness_cfg=pop.config.evaluation,
        game_cfg=pop.config.game,
        game_obs=return_dict,
        gen=pop.generation,
    )
    for i, genome in pop.population.items():
        genome.fitness = fitness[i]

    # Save the results
    pop.generation += 1
    pop.save()
Пример #2
0
    def trace_genomes(self,
                      pop: Population,
                      given_genome: Genome = None,
                      parallel: bool = True):
        """
        Create blueprints that contain the walking-traces for all the requested mazes.

        :param pop: Population object
        :param given_genome: Single genomes for which the trace must be made
        :param parallel: Create the traces in parallel
        """
        multi_env = get_multi_env(pop=pop, game_config=self.game_config)
        if len(self.games) > 20 and given_genome is None:
            raise Exception(
                "It is not advised to evaluate on more than 20 at once")
        elif len(self.games) > 100:
            raise Exception(
                "It is not advised to evaluate on more than 100 at once")

        # Set the games for which traces will be made
        multi_env.set_games(self.games, noise=False)

        # Fetch the dictionary of genomes
        genomes = [(given_genome.key, given_genome)] if given_genome else list(
            iteritems(pop.population))

        if parallel:
            # Initialize the evaluation-pool
            pool = mp.Pool(mp.cpu_count() - self.unused_cpu)
            manager = mp.Manager()
            return_dict = manager.dict()

            # Evaluate the genomes
            for genome in genomes:
                pool.apply_async(func=multi_env.trace_genome,
                                 args=(genome, return_dict))
            pool.close()  # Close the pool
            pool.join()  # Postpone continuation until everything is finished
        else:  # Train sequentially
            return_dict = dict()
            for genome in tqdm(genomes, desc="sequential evaluating"):
                multi_env.trace_genome(genome, return_dict)

        # Create blueprint of final result
        game_objects = [get_game(g, cfg=self.game_config) for g in self.games]
        path = get_subfolder(
            f"population{'_backup' if pop.use_backup else ''}/storage/{pop.folder_name}/{pop}/",
            'images')
        path = get_subfolder(path, 'games')
        create_traces(
            traces=return_dict,
            games=game_objects,
            gen=pop.generation,
            save_path=path,
            save_name=f'trace_{given_genome.key}' if given_genome else 'trace',
        )
Пример #3
0
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 trace_genomes(self, pop: Population, given_genome: Genome = None):
        """
        Create blueprints that contain the walking-traces for all the requested mazes.

        :param pop: Population object
        :param given_genome: Single genomes for which the trace must be made
        """
        multi_env = get_multi_env(pop=pop, game_config=self.game_config)
        if len(self.games) > 20:
            raise Exception(
                "It is not advised to evaluate on more than 20 at once")

        multi_env.set_games(self.games)

        # Initialize the evaluation-pool
        pool = mp.Pool(mp.cpu_count())
        manager = mp.Manager()
        return_dict = manager.dict()

        # Fetch the dictionary of genomes
        genomes = [(given_genome.key, given_genome)] if given_genome else list(
            iteritems(pop.population))

        # Progress bar during evaluation
        pbar = tqdm(total=len(genomes), desc="parallel evaluating")

        def cb(*_):
            """Update progressbar after finishing a single genome's evaluation."""
            pbar.update()

        # Evaluate the genomes
        for genome in genomes:
            pool.apply_async(func=multi_env.trace_genome,
                             args=(genome, return_dict),
                             callback=cb)
        pool.close()  # Close the pool
        pool.join()  # Postpone continuation until everything is finished

        # Create blueprint of final result
        game_objects = [get_game(g, cfg=self.game_config) for g in self.games]
        create_traces(
            traces=return_dict,
            games=game_objects,
            gen=pop.generation,
            save_path=get_subfolder(
                f'population/storage/{pop.folder_name}/{pop}/', 'images'),
            save_name=f'trace_{given_genome.key}' if given_genome else 'trace',
        )
Пример #5
0
    def blueprint_genomes(self, pop: Population, parallel: bool = True):
        """
        Create blueprints for all the requested mazes.

        :param pop: Population object
        :param parallel: Evaluate the population in parallel
        """
        multi_env = get_multi_env(pop=pop, game_config=self.game_config)
        if len(self.games) > 100:
            raise Exception(
                "It is not advised to evaluate on more than 100 at once")

        multi_env.set_games(self.games, noise=False)

        # Fetch the dictionary of genomes
        genomes = list(iteritems(pop.population))

        if parallel:
            # Initialize the evaluation-pool
            pool = mp.Pool(mp.cpu_count() - self.unused_cpu)
            manager = mp.Manager()
            return_dict = manager.dict()

            # Evaluate the genomes
            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:  # Evaluate sequentially
            return_dict = dict()
            for genome in genomes:
                multi_env.eval_genome(genome, return_dict)

        # Create blueprint of final result
        game_objects = [get_game(g, cfg=self.game_config) for g in self.games]
        path = get_subfolder(
            f"population{'_backup' if pop.use_backup else ''}/storage/{pop.folder_name}/{pop}/",
            'images')
        path = get_subfolder(path, 'games')
        create_blueprints(
            final_observations=return_dict,
            games=game_objects,
            gen=pop.generation,
            save_path=path,
        )
Пример #6
0
    def evaluate_same_games_and_evolve(
        self,
        games: list,
        pop: Population,
        n: int = 1,
        parallel=True,
        save_interval: int = 1,
    ):
        """
        Evaluate the population on the same games.
        
        :param games: List of games used for training
        :param pop: Population object
        :param n: Number of generations
        :param parallel: Parallel the code (disable parallelization for debugging purposes)
        :param save_interval: Indicates how often a population gets saved
        """
        multi_env = get_multi_env(pop=pop, game_config=self.game_config)
        msg = f"Repetitive evaluating games: {games}"
        pop.log(msg, print_result=False)
        multi_env.set_games(games)

        # Iterate and evaluate over the games
        saved = True
        for iteration in range(n):
            single_evaluation(
                multi_env=multi_env,
                parallel=parallel,
                pop=pop,
                unused_cpu=self.unused_cpu,
            )

            # Save the population
            if (iteration + 1) % save_interval == 0:
                pop.save()
                saved = True
            else:
                saved = False

        # Make sure that last iterations saves
        if not saved: pop.save()
Пример #7
0
    def evaluate_and_evolve(
        self,
        pop: Population,
        n: int = 1,
        parallel=True,
        save_interval: int = 1,
    ):
        """
        Evaluate the population for a single evaluation-process.
        
        :param pop: Population object
        :param n: Number of generations
        :param parallel: Parallel the code (disable parallelization for debugging purposes)
        :param save_interval: Indicates how often a population gets saved
        """
        multi_env = get_multi_env(pop=pop, game_config=self.game_config)
        saved = True
        for iteration in range(n):
            # Set random set of games
            self.sample_games(multi_env, pop.log)

            # Evaluate the population on the newly sampled games
            single_evaluation(
                multi_env=multi_env,
                parallel=parallel,
                pop=pop,
                unused_cpu=self.unused_cpu,
            )

            # Save the population
            if (iteration + 1) % save_interval == 0:
                pop.save()
                saved = True
            else:
                saved = False

        # Make sure that last iterations saves
        if not saved: pop.save()
Пример #8
0
def train(
    population: Population,
    game_config: Config,
    games: list,
    iterations: int,
    unused_cpu: int = 0,
    save_interval: int = 10,
):
    """Train the population on the requested number of iterations. Manual adaptation of main's train()."""

    population.log("\n===> TRAINING <===\n")

    multi_env = get_multi_env(pop=population, game_config=game_config)
    msg = f"Repetitive evaluating on games: {games} for {iterations} iterations"
    population.log(msg, print_result=False)

    # Iterate and evaluate over the games
    saved = True
    for iteration in range(iterations):
        # Set and randomize the games
        multi_env.set_games(games, noise=True)

        # Prepare the generation's reporters for the generation
        population.reporters.start_generation(gen=population.generation,
                                              logger=population.log)

        # Fetch the dictionary of genomes
        genomes = list(iteritems(population.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=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=population.config.evaluation,
            game_cfg=game_config.game,
            game_obs=return_dict,
            gen=population.generation,
        )
        for i, genome in genomes:
            genome.fitness = fitness[i]

        # Gather and report statistics
        best = None
        for g in itervalues(population.population):
            if best is None or g.fitness > best.fitness: best = g
        population.reporters.post_evaluate(population=population.population,
                                           species=population.species,
                                           best_genome=best,
                                           logger=population.log)

        # Update the population's best_genome
        genomes = sorted(population.population.items(),
                         key=lambda x: x[1].fitness,
                         reverse=True)
        population.best_fitness[population.generation] = genomes[0][1].fitness
        population.best_genome_hist[population.generation] = genomes[0]
        population.best_genome = best

        # Let population evolve
        population.evolve()

        # Update the genomes such all have one hidden node
        for g in population.population.values():
            n_hidden, _ = g.size()
            while n_hidden < 1:
                g.mutate_add_connection(population.config.genome)
                n_hidden, _ = g.size()

        # End generation
        population.reporters.end_generation(population=population.population,
                                            name=str(population),
                                            species_set=population.species,
                                            logger=population.log)

        # Save the population
        if (iteration + 1) % save_interval == 0:
            population.save()
            saved = True
        else:
            saved = False

    # Make sure that last iterations saves
    if not saved: population.save()
Пример #9
0
    def evaluate_and_evolve(
        self,
        pop: Population,
        n: int = 1,
        parallel=True,
        save_interval: int = 1,
    ):
        """
        Evaluate the population on the same set of games.
        
        :param pop: Population object
        :param n: Number of generations
        :param parallel: Parallel the code (disable parallelization for debugging purposes)
        :param save_interval: Indicates how often a population gets saved
        """
        multi_env = get_multi_env(pop=pop, game_config=self.game_config)
        msg = f"Repetitive evaluating on games: {self.games} for {n} iterations"
        pop.log(msg, print_result=False)

        # Iterate and evaluate over the games
        saved = True
        for iteration in range(n):
            # Set and randomize the games
            multi_env.set_games(self.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() - self.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
            else:
                return_dict = dict()
                for genome in tqdm(genomes, desc="sequential training"):
                    multi_env.eval_genome(genome, return_dict)

            # Calculate the fitness from the given return_dict
            fitness = calc_pop_fitness(
                fitness_cfg=pop.config.evaluation,
                game_cfg=self.game_config.game,
                game_obs=return_dict,
                gen=pop.generation,
            )
            for i, genome in genomes:
                genome.fitness = fitness[i]

            # Gather and report statistics
            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
            pop.evolve()

            # End generation
            pop.reporters.end_generation(population=pop.population,
                                         name=str(pop),
                                         species_set=pop.species,
                                         logger=pop.log)

            # Save the population
            if (iteration + 1) % save_interval == 0:
                pop.save()
                saved = True
            else:
                saved = False

        # Make sure that last iterations saves
        if not saved: pop.save()