Callbacks

Introduction

A callback is a powerful tool to customize the behaviour of a population of genomes during the neuroevolutionary process. Examples include FitnessEarlyStopping to stop the evolution when a certain fitness has been achieved by the population, or BestGenomeCheckpoint to periodically save the best genome of a population during evolution. For a list with all the pre-implemented callbacks, take a look at nevopy.callbacks.

In this quick guide you’ll learn what a NEvoPy callback is, what it can do, and how you can build your own.

NEvoPy callbacks overview

In NEvoPy, all callbacks subclass the Callback class and override a set of methods called at various stages of the evolutionary process. Callbacks are useful to get a view on internal states and statistics of a population and its genomes, as well as for modifying the behavior of the evolutionary algorithm being used.

You can pass a list of callbacks (as the keyword argument callbacks) to the evolve() method of your population.

An overview of callback methods

A callback implements one or more of the following methods (check each method’s documentation for a list of accepted parameters):

  • on_generation_start: called at the beginning of each new generation.

  • on_fitness_calculated: called right after the fitness values of the population’s genomes are calculated.

  • on_mass_extinction_counter_updated: called right after the mass extinction counter is updated. The mass extinction counter counts how many generations have passed since the fitness of the population’s best genomes improved.

  • on_mass_extinction_start: called at the beginning of a mass extinction event. A mass extinction event occurs when the population’s fitness haven’t improved for a predefined number of generations. It results in the replacement of all the population’s genomes (except for the fittest genome) for new randomly generated genomes.

  • on_reproduction_start: called at the beginning of the reproductive process.

  • on_speciation_start: called at the beginning of the speciation process. If the neuroevolutionary algorithm doesn’t use speciation, this method isn’t called at all.

  • on_generation_end: called at the end of each generation.

  • on_evolution_end: called when the evolutionary process ends.

Writing your own callbacks

To build your own callback, simply create a new class that has Callback as its parent class:

class MyCallback(Callback):
    def on_generation_start(self,
                            current_generation,
                            max_generations):
        print("This is printed at the start of every generation!")
        print(f"Starting generation {current_generation} of "
              f"{max_generations}.")

Then, just create a new instance of your callback and pass it to the evolve() of your population:

population.evolve(generations=100,
                  fitness_function=my_func,
                  callbacks=[MyCallback()])