Progress Plotter
- class ProgressPlotter(generations, get_property, y_label, filter=<function ProgressPlotter.<lambda>>)[source]
Bases:
object
Plots how a property changes during an EA run.
The produced plot will show the EA generations on the x axis and the min, mean and max values of an attribute on the y axis.
Examples
Plotting How Fitness Values Change Across Generations
import stk # Initialize an EA somehow. ea = stk.EvolutionaryAlgorithm( initial_population=( stk.MoleculeRecord( topology_graph=stk.polymer.Linear( building_blocks=( stk.BuildingBlock( smiles='BrCCBr', functional_groups=[stk.BromoFactory()], ), ), repeating_unit='A', num_repeating_units=i, ), ) for i in range(2, 22) ), fitness_calculator=stk.FitnessFunction( fitness_function=lambda molecule: molecule.get_num_atoms(), ), mutator=stk.RandomBuildingBlock( building_blocks=( stk.BuildingBlock( smiles='BrC[Si]CCBr', functional_groups=[stk.BromoFactory()], ), stk.BuildingBlock( smiles='BrCCCCCCCBr', functional_groups=[stk.BromoFactory()], ), ), is_replaceable=lambda building_block: True ), crosser=stk.GeneticRecombination( get_gene=lambda building_block: 0 ), generation_selector=stk.Best( num_batches=22, duplicate_molecules=False, ), mutation_selector=stk.Roulette( num_batches=5, random_seed=10, ), crossover_selector=stk.Roulette( num_batches=5, batch_size=2, random_seed=10, ), num_processes=1, ) generations = [] for generation in ea.get_generations(10): generations.append(generation) # Make the plotter which plots the fitness change across # generations. progress = stk.ProgressPlotter( generations=generations, get_property=lambda record: record.get_fitness_value(), y_label='Fitness' ) progress.write('fitness_plot.png')
Plotting How a Molecular Property Changes Across Generations
As an example, plotting how the number of atoms changes across generations
import stk # Initialize an EA somehow. ea = stk.EvolutionaryAlgorithm( initial_population=( stk.MoleculeRecord( topology_graph=stk.polymer.Linear( building_blocks=( stk.BuildingBlock( smiles='BrCCBr', functional_groups=[stk.BromoFactory()], ), ), repeating_unit='A', num_repeating_units=i, ), ) for i in range(2, 22) ), fitness_calculator=stk.FitnessFunction( fitness_function=lambda molecule: molecule.get_num_atoms(), ), mutator=stk.RandomBuildingBlock( building_blocks=( stk.BuildingBlock( smiles='BrC[Si]CCBr', functional_groups=[stk.BromoFactory()], ), stk.BuildingBlock( smiles='BrCCCCCCCBr', functional_groups=[stk.BromoFactory()], ), ), is_replaceable=lambda building_block: True ), crosser=stk.GeneticRecombination( get_gene=lambda building_block: 0 ), generation_selector=stk.Best( num_batches=22, duplicate_molecules=False, ), mutation_selector=stk.Roulette( num_batches=5, random_seed=10, ), crossover_selector=stk.Roulette( num_batches=5, batch_size=2, random_seed=10, ), num_processes=1, ) generations = [] for generation in ea.get_generations(10): generations.append(generation) # Make the plotter which plots the number of atoms across # generations. progress = stk.ProgressPlotter( generations=generations, get_property=lambda record: record.get_molecule().get_num_atoms(), y_label='Number of Atoms' ) progress.write('number_of_atoms_plot.png')
Excluding Molecules From the Plot
Sometimes, you want to ignore some molecules from the plot you make. For example, If the fitness calculation failed on a molecule, you not want to include in a plot of fitness.
import stk # Initialize an EA somehow. ea = stk.EvolutionaryAlgorithm( initial_population=( stk.MoleculeRecord( topology_graph=stk.polymer.Linear( building_blocks=( stk.BuildingBlock( smiles='BrCCBr', functional_groups=[stk.BromoFactory()], ), ), repeating_unit='A', num_repeating_units=i, ), ) for i in range(2, 22) ), fitness_calculator=stk.FitnessFunction( fitness_function=lambda molecule: molecule.get_num_atoms(), ), mutator=stk.RandomBuildingBlock( building_blocks=( stk.BuildingBlock( smiles='BrC[Si]CCBr', functional_groups=[stk.BromoFactory()], ), stk.BuildingBlock( smiles='BrCCCCCCCBr', functional_groups=[stk.BromoFactory()], ), ), is_replaceable=lambda building_block: True ), crosser=stk.GeneticRecombination( get_gene=lambda building_block: 0 ), generation_selector=stk.Best( num_batches=22, duplicate_molecules=False, ), mutation_selector=stk.Roulette( num_batches=5, random_seed=10, ), crossover_selector=stk.Roulette( num_batches=5, batch_size=2, random_seed=10, ), num_processes=1, ) generations = [] for generation in ea.get_generations(10): generations.append(generation) # Make the plotter which plots the fitness change across # generations. progress = stk.ProgressPlotter( generations=generations, get_property=lambda record: record.get_fitness_value(), y_label='Fitness', # Only plot records whose unnormalized fitness value is not # None, which means the fitness calculation did not fail. filter=lambda record: record.get_fitness_value(normalized=False) is not None, ) progress.write('fitness_plot.png')
Methods
Get the plot data.
write
(path[, dpi])Write a progress plot to a file.
- __init__(generations, get_property, y_label, filter=<function ProgressPlotter.<lambda>>)[source]
Initialize a
ProgressPlotter
instance.- Parameters:
generations (
iterable
ofGeneration
) – The generations of the EA, which are plotted.get_property (
callable
) – Acallable
which takes aMoleculeRecord
and returns a property value of that molecule, which is used for the plot. Thecallable
must return a valid value for eachMoleculeRecord
in generations.y_label (
str
) – The y label for the produced graph.filter (
callable
, optional) – Takes anMoleculeRecord
and returnsTrue
orFalse
. Only records which returnTrue
are included in the plot. By default, all records will be plotted.
- get_plot_data()[source]
Get the plot data.
- Returns:
A data frame holding the plot data.
- Return type:
pandas.DataFrame