Skip to content

Commit

Permalink
PyGAD 3.0.0 parallel processing
Browse files Browse the repository at this point in the history
There was an issue when using the `parallel_processing` parameter with Keras and PyTorch. As Keras/PyTorch are not thread-safe, the `predict()` method gives incorrect and weird results when more than 1 thread is used. ahmedfgad/GeneticAlgorithmPython#145 #5 ahmedfgad/KerasGA#6. Thanks to this StackOverflow answer https://stackoverflow.com/a/75606666/5426539.
  • Loading branch information
ahmedfgad committed Apr 8, 2023
1 parent c774f58 commit 43e8503
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 14 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ pip install pygad

# Donation

You can donate via [Open Collective](https://opencollective.com/pygad): [opencollective.com/pygad](https://opencollective.com/pygad).

To donate using PayPal, use either this link: [paypal.me/ahmedfgad](https://paypal.me/ahmedfgad) or the e-mail address ahmed.f.gad@gmail.com.
- [Credit/Debit Card](https://donate.stripe.com/eVa5kO866elKgM0144): https://donate.stripe.com/eVa5kO866elKgM0144
- [Open Collective](https://opencollective.com/pygad): [opencollective.com/pygad](https://opencollective.com/pygad)
- PayPal: Use either this link: [paypal.me/ahmedfgad](https://paypal.me/ahmedfgad) or the e-mail address ahmed.f.gad@gmail.com
- Interac e-Transfer: Use e-mail address ahmed.f.gad@gmail.com

# Installation

Expand Down Expand Up @@ -72,7 +73,7 @@ import numpy
function_inputs = [4,-2,3.5,5,-11,-4.7]
desired_output = 44

def fitness_func(solution, solution_idx):
def fitness_func(ga_instance, solution, solution_idx):
output = numpy.sum(solution*function_inputs)
fitness = 1.0 / (numpy.abs(output - desired_output) + 0.000001)
return fitness
Expand Down Expand Up @@ -153,7 +154,7 @@ import torch
import torchga
import pygad

def fitness_func(solution, sol_idx):
def fitness_func(ga_instance, solution, sol_idx):
global data_inputs, data_outputs, torch_ga, model, loss_function

model_weights_dict = torchga.model_weights_as_dict(model=model,
Expand Down Expand Up @@ -240,7 +241,7 @@ import torch
import torchga
import pygad

def fitness_func(solution, sol_idx):
def fitness_func(ga_instance, solution, sol_idx):
global data_inputs, data_outputs, torch_ga, model, loss_function

model_weights_dict = torchga.model_weights_as_dict(model=model,
Expand Down
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .torchga import *

__version__ = "1.1.0"
__version__ = "1.2.0"
3 changes: 2 additions & 1 deletion pytorch_pygad_XOR_classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pygad.torchga
import pygad

def fitness_func(solution, sol_idx):
def fitness_func(ga_instanse, solution, sol_idx):
global data_inputs, data_outputs, torch_ga, model, loss_function

predictions = pygad.torchga.predict(model=model,
Expand Down Expand Up @@ -57,6 +57,7 @@ def callback_generation(ga_instance):
num_parents_mating=num_parents_mating,
initial_population=initial_population,
fitness_func=fitness_func,
parallel_processing=3,
on_generation=callback_generation)

# Start the genetic algorithm evolution.
Expand Down
2 changes: 1 addition & 1 deletion pytorch_pygad_image_classification_CNN.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pygad
import numpy

def fitness_func(solution, sol_idx):
def fitness_func(ga_instanse, solution, sol_idx):
global data_inputs, data_outputs, torch_ga, model, loss_function

predictions = pygad.torchga.predict(model=model,
Expand Down
2 changes: 1 addition & 1 deletion pytorch_pygad_image_classification_Dense.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pygad
import numpy

def fitness_func(solution, sol_idx):
def fitness_func(ga_instanse, solution, sol_idx):
global data_inputs, data_outputs, torch_ga, model, loss_function

predictions = pygad.torchga.predict(model=model,
Expand Down
2 changes: 1 addition & 1 deletion pytorch_pygad_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pygad.torchga
import pygad

def fitness_func(solution, sol_idx):
def fitness_func(ga_instanse, solution, sol_idx):
global data_inputs, data_outputs, torch_ga, model, loss_function

predictions = pygad.torchga.predict(model=model,
Expand Down
7 changes: 4 additions & 3 deletions torchga.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def model_weights_as_dict(model, weights_vector):

start = 0
for key in weights_dict:
# Calling detach() to remove the computational graph from the layer.
# Calling detach() to remove the computational graph from the layer.
# cpu() is called for making shore the data is moved from GPU to cpu
# numpy() is called for converting the tensor into a NumPy array.
w_matrix = weights_dict[key].cpu().detach().numpy()
Expand All @@ -41,9 +41,10 @@ def predict(model, solution, data):
weights_vector=solution)

# Use the current solution as the model parameters.
model.load_state_dict(model_weights_dict)
_model = copy.deepcopy(model)
_model.load_state_dict(model_weights_dict)

predictions = model(data)
predictions = _model(data)

return predictions

Expand Down

0 comments on commit 43e8503

Please sign in to comment.