From 298a757ad88cf2e3898690d622bbe9d56faba540 Mon Sep 17 00:00:00 2001 From: Evair Date: Tue, 12 Mar 2024 15:14:48 -0300 Subject: [PATCH 1/2] Improvement on memory usage --- examples/KerasGA/image_classification_CNN.py | 33 +++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/examples/KerasGA/image_classification_CNN.py b/examples/KerasGA/image_classification_CNN.py index a8084ee..5e46760 100644 --- a/examples/KerasGA/image_classification_CNN.py +++ b/examples/KerasGA/image_classification_CNN.py @@ -2,6 +2,8 @@ import pygad.kerasga import numpy import pygad +import gc + def fitness_func(ga_instanse, solution, sol_idx): global data_inputs, data_outputs, keras_ga, model @@ -11,27 +13,33 @@ def fitness_func(ga_instanse, solution, sol_idx): data=data_inputs) cce = tensorflow.keras.losses.CategoricalCrossentropy() - solution_fitness = 1.0 / (cce(data_outputs, predictions).numpy() + 0.00000001) + solution_fitness = 1.0 / \ + (cce(data_outputs, predictions).numpy() + 0.00000001) return solution_fitness + def on_generation(ga_instance): print(f"Generation = {ga_instance.generations_completed}") print(f"Fitness = {ga_instance.best_solution()[1]}") + gc.collect() # can useful for not exploding the memory usage on notebooks (ipynb) freeing memory + # Build the keras model using the functional API. input_layer = tensorflow.keras.layers.Input(shape=(100, 100, 3)) conv_layer1 = tensorflow.keras.layers.Conv2D(filters=5, kernel_size=7, activation="relu")(input_layer) -max_pool1 = tensorflow.keras.layers.MaxPooling2D(pool_size=(5,5), +max_pool1 = tensorflow.keras.layers.MaxPooling2D(pool_size=(5, 5), strides=5)(conv_layer1) conv_layer2 = tensorflow.keras.layers.Conv2D(filters=3, kernel_size=3, activation="relu")(max_pool1) -flatten_layer = tensorflow.keras.layers.Flatten()(conv_layer2) -dense_layer = tensorflow.keras.layers.Dense(15, activation="relu")(flatten_layer) -output_layer = tensorflow.keras.layers.Dense(4, activation="softmax")(dense_layer) +flatten_layer = tensorflow.keras.layers.Flatten()(conv_layer2) +dense_layer = tensorflow.keras.layers.Dense( + 15, activation="relu")(flatten_layer) +output_layer = tensorflow.keras.layers.Dense( + 4, activation="softmax")(dense_layer) model = tensorflow.keras.Model(inputs=input_layer, outputs=output_layer) @@ -47,13 +55,15 @@ def on_generation(ga_instance): data_outputs = tensorflow.keras.utils.to_categorical(data_outputs) # Prepare the PyGAD parameters. Check the documentation for more information: https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#pygad-ga-class -num_generations = 200 # Number of generations. -num_parents_mating = 5 # Number of solutions to be selected as parents in the mating pool. -initial_population = keras_ga.population_weights # Initial population of network weights. +num_generations = 200 # Number of generations. +# Number of solutions to be selected as parents in the mating pool. +num_parents_mating = 5 +# Initial population of network weights. +initial_population = keras_ga.population_weights # Create an instance of the pygad.GA class -ga_instance = pygad.GA(num_generations=num_generations, - num_parents_mating=num_parents_mating, +ga_instance = pygad.GA(num_generations=num_generations, + num_parents_mating=num_parents_mating, initial_population=initial_population, fitness_func=fitness_func, on_generation=on_generation) @@ -62,7 +72,8 @@ def on_generation(ga_instance): ga_instance.run() # After the generations complete, some plots are showed that summarize how the outputs/fitness values evolve over generations. -ga_instance.plot_fitness(title="PyGAD & Keras - Iteration vs. Fitness", linewidth=4) +ga_instance.plot_fitness( + title="PyGAD & Keras - Iteration vs. Fitness", linewidth=4) # Returning the details of the best solution. solution, solution_fitness, solution_idx = ga_instance.best_solution() From f98f0c978e5d1b1cc4e1bc6ab75d9f6f9bd5cbbc Mon Sep 17 00:00:00 2001 From: Paul Morelle Date: Sat, 13 Apr 2024 07:24:52 +0200 Subject: [PATCH 2/2] Fix a typo in example_custom_operators In the crossover function, the split point is chosen in the range of the offspring size, instead of the solution size. An out-of-range split point is silently ignored by the range selection: it selects all genes from parent1, and none from parent2. However, the error can be demonstrated by throwing an exception if the split point is out of range. --- examples/example_custom_operators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_custom_operators.py b/examples/example_custom_operators.py index 88d3e6a..84949aa 100644 --- a/examples/example_custom_operators.py +++ b/examples/example_custom_operators.py @@ -41,7 +41,7 @@ def crossover_func(parents, offspring_size, ga_instance): parent1 = parents[idx % parents.shape[0], :].copy() parent2 = parents[(idx + 1) % parents.shape[0], :].copy() - random_split_point = numpy.random.choice(range(offspring_size[0])) + random_split_point = numpy.random.choice(range(offspring_size[1])) parent1[random_split_point:] = parent2[random_split_point:]