def post_evaluate(self, config, population, species, best_genome): fitnesses = [c.fitness for c in population.values()] fit_mean = mean(fitnesses) fit_stdev = std(fitnesses) best_species_key = species.get_species_key(best_genome.key) print("Population's average fitness: {0:3.5f} stdev: {1:3.5f}".format( fit_mean, fit_stdev)) print("Best fitness: {0:3.5f} - size: {1!r} - species {2} - id {3}". format(best_genome.fitness, best_genome.size(), best_species_key, best_genome.key))
def speciate(self, config, population, generation): assert isinstance(population, dict) compatibility_threshold = self.species_set_config.compatibility_threshold # find the best representative for each species unspeciated = set(population.keys()) distances = GenomeDistanceCache(config.genome_config) new_representatives = {} new_members = {} for skey, s in self.species.items(): candidates = [] for gkey in unspeciated: g = population[gkey] distance = distances(s.representative, g) candidates.append((distance, g)) # new representative is the closest to current representative ignored_rdist, new_rep = min(candidates, key=lambda x: x[0]) new_rep_key = new_rep.key new_representatives[skey] = new_rep_key new_members[skey] = [new_rep_key] unspeciated.remove(new_rep_key) # break population into species niches based on genetic similarity while unspeciated: gkey = unspeciated.pop() g = population[gkey] # find species with the most similar representative candidates = [] for skey, rep_key in new_representatives.items(): rep = population[rep_key] distance = distances(rep, g) if distance < compatibility_threshold: candidates.append((distance, skey)) if candidates: ignored_sdist, skey = min(candidates, key=lambda x: x[0]) new_members[skey].append(gkey) else: # if no species is similar enough, create new one skey = next(self.indexer) new_representatives[skey] = gkey new_members[skey] = [gkey] self.genome_to_species = {} for skey, rep_key in new_representatives.items(): s = self.species.get(skey) if s is None: s = Species(skey, generation) self.species[skey] = s members = new_members[skey] for gkey in members: self.genome_to_species[gkey] = skey member_dict = dict((gkey, population[gkey]) for gkey in members) s.update(population[rep_key], member_dict) gdmean = mean(distances.distances.values()) gdstdev = std(distances.distances.values()) self.reporters.info("Genetic distance: mean {0:.3f}, stdev {1:.3f}".format(gdmean, gdstdev))
def end_generation(self, config, population, species_set): ng = len(population) self.log_dict["pop_size"] = ng ns = len(species_set.species) self.log_dict["n_species"] = ns elapsed = time.time() - self.generation_start_time self.log_dict["time_elapsed"] = elapsed self.generation_times.append(elapsed) self.generation_times = self.generation_times[-10:] average = mean(self.generation_times) self.log_dict["time_elapsed_avg"] = average self.log_dict["n_extinctions"] = self.num_extinctions pprint(self.log_dict) self.log.write(json.dumps(self.log_dict) + "\n")
def get_species_fitness(self, null_value=''): all_species = set() for gen_data in self.generation_statistics: all_species = all_species.union(gen_data.keys()) max_species = max(all_species) species_fitness = [] for gen_data in self.generation_statistics: member_fitness = [ gen_data.get(sid, []) for sid in range(1, max_species + 1) ] fitness = [] for mf in member_fitness: if mf: fitness.append(mean(mf)) else: fitness.append(null_value) species_fitness.append(fitness) return species_fitness
def post_evaluate(self, config, population, species, best_genome): fitnesses = [c.fitness for c in population.values()] fit_mean = mean(fitnesses) fit_stdev = std(fitnesses) self.log_dict["fitness_avg"] = fit_mean self.log_dict["fitness_std"] = fit_stdev self.log_dict["fitness_best"] = best_genome.fitness print("=" * 50 + " Best Genome: " + "=" * 50) if self.eval_debug: print(best_genome) best_fitness_val = self.eval_best(best_genome, config, debug=self.eval_debug) self.log_dict["fitness_best_val"] = best_fitness_val n_neurons_best, n_conns_best = best_genome.size() self.log_dict["n_neurons_best"] = n_neurons_best self.log_dict["n_conns_best"] = n_conns_best
def reproduce(self, config, species, pop_size, generation): all_fitnesses = [] remaining_species = [] # removes stagnant species for stag_key, stag_species, stagnant in self.stagnation.update(species, generation): if stagnant: self.reporters.species_stagnant(stag_key, stag_species) else: all_fitnesses.extend(member.fitness for member in stag_species.members.values()) remaining_species.append(stag_species) if not remaining_species: # all species were stagnant & therefore eliminated species.species = {} return {} min_fitness = min(all_fitnesses) max_fitness = max(all_fitnesses) fitness_range = max(1.0, max_fitness - min_fitness) for spec in remaining_species: mean_species_fit = mean([member.fitness for member in spec.members.values()]) adj_fit = (mean_species_fit - min_fitness) / fitness_range spec.adjusted_fitness = adj_fit adj_fitnesses = [spec.adjusted_fitness for spec in remaining_species] mean_adj_fit = mean(adj_fitnesses) self.reporters.info("Average adjusted fitness: {:.3f}".format(mean_adj_fit)) prev_sizes = [len(spec.members) for spec in remaining_species] min_species_size = max(self.reproduction_config.min_species_size, self.reproduction_config.elitism) spawn_amounts = self.compute_spawn(adj_fitnesses, prev_sizes, pop_size, min_species_size) new_population = {} species.species = {} for spawn, spec in zip(spawn_amounts, remaining_species): spawn = max(spawn, self.reproduction_config.elitism) assert spawn > 0 old_members = list(spec.members.items()) old_members.sort(reverse=True, key=lambda x: x[1].fitness) spec.members = {} species.species[spec.key] = spec if self.reproduction_config.elitism > 0: for key, member in old_members[:self.reproduction_config.elitism]: new_population[key] = member spawn -= 1 if spawn <= 0: continue cutoff = int(ceil(self.reproduction_config.survival_threshold * len(old_members))) cutoff = max(cutoff, 2) old_members = old_members[:cutoff] while spawn > 0: spawn -= 1 parent1_key, parent1 = random.choice(old_members) parent2_key, parent2 = random.choice(old_members) gkey = next(self.genome_indexer) child = config.genome_type(gkey) child.configure_crossover(parent1, parent2, config.genome_config) child.mutate(config.genome_config) new_population[gkey] = child self.ancestors[gkey] = (parent1_key, parent2_key) return new_population
def mean_agg(inputs): return mean(inputs)