From 9294fafd1a396f628fceedc399e955853daed1f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rog=C3=A9rio=20Gouv=C3=AAa?= Date: Tue, 24 Mar 2026 12:13:25 +0100 Subject: [PATCH 1/2] Fix type casting and prevent errors in genetic algorithm Fixed issues related to type casting and potential errors in the genetic algorithm's hyperparameter handling in newer python versions. --- modnet/hyper_opt/fit_genetic.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/modnet/hyper_opt/fit_genetic.py b/modnet/hyper_opt/fit_genetic.py index 7d0b8b7f..798940b7 100644 --- a/modnet/hyper_opt/fit_genetic.py +++ b/modnet/hyper_opt/fit_genetic.py @@ -15,7 +15,7 @@ class Individual: """Class representing a set of hyperparameters for the genetic algorithm.""" - def __init__( +def __init__( self, max_feat: int, num_classes: dict, @@ -77,11 +77,12 @@ def __init__( b = int(max_feat / 2) self.genes["n_feat"] = random.randint(1, b) + b elif max_feat > 100 and max_feat < 2000: - max = max_feat - self.genes["n_feat"] = 10 * random.randint(1, int(max / 10)) + max_val = max_feat + self.genes["n_feat"] = 10 * random.randint(1, int(max_val / 10)) else: - max = np.sqrt(max_feat) - self.genes["n_feat"] = random.randint(1, max) ** 2 + # FIX: Cast np.sqrt to int to prevent random.randint float crash + max_val = int(np.sqrt(max_feat)) + self.genes["n_feat"] = random.randint(1, max_val) ** 2 def crossover(self, partner: Individual) -> Individual: """Does the crossover of two parents and returns a 'child' which has a mix of the parents hyperparams. @@ -91,8 +92,8 @@ def crossover(self, partner: Individual) -> Individual: Returns: Individual: Child. """ - # creates indices to take randomly half the genes from one parent, and half the genes from the other - mother_genes = random.sample(self.genes.keys(), k=len(self.genes) // 2) + # FIX: Cast dict_keys to list for random.sample in Python 3.9+ + mother_genes = random.sample(list(self.genes.keys()), k=len(self.genes) // 2) child_genes = { gene: self.genes[gene] if gene in mother_genes else partner.genes[gene] @@ -575,13 +576,17 @@ def run( 1 / lw**5 for lw in val_loss[ranking] ] # **5 in order to give relatively more importance to the best individuals weights = [1e-5 if math.isnan(weight) else weight for weight in weights] - weights = [w / sum(weights) for w in weights] - # selection: weighted choice of the parents -> parents with a low MAE have more chance to be selected + + # FIX: Add tiny epsilon to sum to prevent ZeroDivisionError + weight_sum = sum(weights) + 1e-10 + weights = [w / weight_sum for w in weights] + + # FIX: wrap NumPy arrays in list() for random.choices compatibility parents_1 = random.choices( - individuals[ranking], weights=weights, k=size_pop + list(individuals[ranking]), weights=weights, k=size_pop ) parents_2 = random.choices( - individuals[ranking], weights=weights, k=size_pop + list(individuals[ranking]), weights=weights, k=size_pop ) # crossover From fe0d361a23788fa482430c4ad5576b8a3462cb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rog=C3=A9rio=20Gouv=C3=AAa?= Date: Tue, 24 Mar 2026 12:23:40 +0100 Subject: [PATCH 2/2] Fix missing tab __init__ method definition in Individual class --- modnet/hyper_opt/fit_genetic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modnet/hyper_opt/fit_genetic.py b/modnet/hyper_opt/fit_genetic.py index 798940b7..29dd6444 100644 --- a/modnet/hyper_opt/fit_genetic.py +++ b/modnet/hyper_opt/fit_genetic.py @@ -15,7 +15,7 @@ class Individual: """Class representing a set of hyperparameters for the genetic algorithm.""" -def __init__( + def __init__( self, max_feat: int, num_classes: dict,