How to Supply named parameters in PyGAD?

161 Views Asked by At

I've seen the tutorial on optimizing arbitrary functions with PyGAD. As a simple POC, I'd like to implement linear regression. I am not interested in integrating with Keras or PyTorch; I understand that the integration is supported, but that's more firepower than is necessary.

Here is the tutorial's simple illustrative function, where it converges on weights such that X[i] . W[i] = value:

def fitness_func(solution, solution_idx):
    output = numpy.sum(solution*function_inputs)
    fitness = 1.0 / numpy.abs(output - desired_output)
    return fitness

Here is my attempt at linear regression:

#  X,         Y
# [[1,3,5,7], [2,4,6,8]]
# slope = 1
# intercept = 1 

def fitness_function_factory(slope=0, intercept=0, function_inputs = numpy.array([[1,3,5,7], [2,4,6,8]]), desired_output = 0 ):

    def fitness_function(solution, solution_idx):
        pred = slope * function_inputs[0] + intercept
        error = numpy.sum(numpy.abs(pred - function_inputs[1]))
        fitness = 1/(error - desired_output)
        return fitness 

    return fitness_function

lr_ga = pygad.GA(num_generations=num_generations,
                      num_parents_mating=num_parents_mating,
                      fitness_func=fitness_function_factory(0,0),
                      sol_per_pop=sol_per_pop,
                      num_genes=num_genes,
                      init_range_low=init_range_low,
                      init_range_high=init_range_high,
                      parent_selection_type=parent_selection_type,
                      keep_parents=keep_parents,
                      crossover_type=crossover_type,
                      mutation_type=mutation_type,
                      mutation_percent_genes=mutation_percent_genes)

lr_ga.run()

And the corresponding error:

      7 def linear_regression(solution, solution_idx):
----> 8   pred = solution['slope'] * function_inputs[0] + solution['intercept']
      9   error = numpy.abs(pred - function_inputs[1])
     10   fitness = 1/(error - desired_output)

IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

Note: I took inspiration from this Q/A, using a factory function to wrap the fitness function.

How should I enabled named parameters such that slope and intercept can be retrieved?

1

There are 1 best solutions below

0
On
num_generations = 50
num_parents_mating = 4

sol_per_pop = 8
num_parameters = 2 

init_range_low = -2
init_range_high = 5

parent_selection_type = "sss"
keep_parents = 1

crossover_type = "single_point"

mutation_type = "random"
mutation_percent_genes = 10

def fitness_function_factory(X=numpy.array([1,3,5,7]), Y=numpy.array([2,4,6,8]), desired_output = 0 ):

    def fitness_function(solution, solution_idx):
        pred = solution[0] * X + solution[1]
        errors = numpy.abs(pred - Y)
        fitness = 1/(numpy.sum(errors) - desired_output)
        return fitness 

    return fitness_function

lr_ga = pygad.GA(num_generations=100,
                      num_parents_mating=num_parents_mating,
                      fitness_func=fitness_function_factory(),
                      sol_per_pop=sol_per_pop,
                      num_genes=num_parameters,
                      init_range_low=init_range_low,
                      init_range_high=init_range_high,
                      parent_selection_type=parent_selection_type,
                      keep_parents=keep_parents,
                      crossover_type=crossover_type,
                      mutation_type=mutation_type,
                      mutation_percent_genes=mutation_percent_genes)

lr_ga.run()

lr_ga.best_solution()[0]
>>>
array([0.98365965, 1.02723423]) # slope, intercept