遗传算法代码

全局搜索最优算法(1)——遗传算法

这里以github上的遗传算法开源库为例子:
首先我们安装GA(官方说依赖库好像只支持Python 3,但是我好像python2也安装成功了。。。)

pip3 install pygad

在这里我们讨论一个简单的全局优化过程,讨论 ( x − 2 ) 2 + ( y − 4 ) 2 (x-2)^2+(y-4)^2 (x2)2+(y4)2 x ⊂ ( 1 , 5 ) , y ⊂ ( 6 , 9 ) x\subset(1,5),y\subset(6,9) x(1,5),y(6,9)的最大值。
源码如下:

import numpy as np
import pygad

#the most important part in GA
def fitness_func(solution, solution_idx):
    # solution[i] represeent the value of the (i+1)th parameter in solution
    fitness =pow((solution[0]-2),2)+pow((solution[1]-4),2)
    return fitness

num_generations = 500 # Number of generations.
num_parents_mating = 5 # Number of solutions to be selected as parents in the mating pool.

# To prepare the initial population, there are 2 ways:
# 1) Prepare it yourself and pass it to the initial_population parameter. This way is useful when the user wants to start the genetic algorithm with a custom initial population.
# 2) Assign valid integer values to the sol_per_pop and num_genes parameters. If the initial_population parameter exists, then the sol_per_pop and num_genes parameters are useless.
sol_per_pop = 10 # Number of solutions in the population.


parent_selection_type = "sss" # Type of parent selection.

crossover_type = "single_point" # Type of the crossover operator.

# Parameters of the mutation operation.
mutation_type = "random" # Type of the mutation operator.

last_fitness = 0
def callback_generation(ga_instance):
    global last_fitness
    print("Generation = {generation}".format(generation=ga_instance.generations_completed))
    print("Fitness    = {fitness}".format(fitness=ga_instance.best_solution()[1]))
    print("Change     = {change}".format(change=ga_instance.best_solution()[1] - last_fitness))
    last_fitness = ga_instance.best_solution()[1]

# Creating an instance of the GA class inside the ga module. Some parameters are initialized within the constructor.
ga_instance = pygad.GA(
                       #Number of generations(iterations).
                       num_generations=50,
                       num_parents_mating=num_parents_mating,
                       fitness_func=fitness_func,
                       sol_per_pop=sol_per_pop,
                       #the Number of parameters(the number of genes)
                       num_genes=2,
                      # It is used to specify the possible values for each gene 
                      # in case the user wants to restrict the gene values. 
                      # It is useful if the gene space is restricted to 
                      # a certain range or to discrete values. 
                      # It accepts a list, tuple, or range. 
                      # When all genes have the same global space, 
                     # specify their values as a list/tuple/range. 
                     # For example, gene_space = [0.3, 5.2, -4, 8] 
                      # restricts the gene values to the 4 specified values. 
                     # If each gene has its own space, then the gene_space
                     # parameter can be nested like [[0.4, -5], [0.5, -3.2, 8.2, -9], ...] 
                     #  where the first sublist determines the values for 
                     # the first gene,the second sublist for the second gene, and so on.
                       gene_space=[np.arange(1, 5.01,0.01).tolist(),np.arange(6, 9.01,0.01).tolist()],
                       parent_selection_type=parent_selection_type,
                       # Number of parents to keep in the next population.
                       # -1 means keep all parents
                      # and 0 means keep nothing.
                       keep_parents=1,
                       crossover_type=crossover_type,
                       mutation_type=mutation_type,
                       # Percentage of genes to mutate. This parameter has no action
                       # if the parameter mutation_num_genes exists.
                       mutation_percent_genes=50,
                       callback_generation=callback_generation)

# Running the GA to optimize the parameters of the function.
ga_instance.run()

# After the generations complete, some plots are showed that summarize the how the outputs/fitenss values evolve over generations.
ga_instance.plot_result()

# Returning the details of the best solution.
solution, solution_fitness, solution_idx = ga_instance.best_solution()
print("Parameters of the best solution : {solution}".format(solution=solution))
print("Fitness value of the best solution = {solution_fitness}".format(solution_fitness=solution_fitness))
#print("Index of the best solution : {solution_idx}".format(solution_idx=solution_idx))

if ga_instance.best_solution_generation != -1:
    print("Best fitness value reached after {best_solution_generation} generations.".format(best_solution_generation=ga_instance.best_solution_generation))

# Saving the GA instance.
filename = 'genetic' # The filename to which the instance is saved. The name is without extension.
ga_instance.save(filename=filename)
# Loading the saved GA instance.
loaded_ga_instance = pygad.load(filename=filename)
loaded_ga_instance.plot_result()

结果如下所示:
Parameters of the best solution : [5. 9.]
Fitness value of the best solution = 33.99999999999938
Best fitness value reached after 26 generations.

迭代的图片如下:
GA迭代次数图尤其注意的是,gene_space这个参数,这一段话我给翻译一下,原文链接在这,它用于指定每个基因(参数)的可能值,用户可以自定义基因(参数)的取值或者取值范围。可以取离散值或者连续值。它接受列表(list)、元组(Tuple)或范围(Range)。
但是python的range其实也是离散值,我就很迷惑了。但是numpy可以实现这个功能,最终还是要转为list。
有两种情况

  1. 所有参数有一个范围或取值,如gene_space=[1,5,6],则表示所有参数只能取1,5,6中的一个值。
  2. 每个参数有不同取值,如gene_space=[[1,6],[4,5,8]],则表示第一个参数取值为1或者6,第二个参数取值为4,5或者8。

需要注意的是适应度函数应该返回的最优解对应的值,通过淘汰适应度低的物种,物竞天择,适者生存,最终返回全局最优解,这就是GA的整体流程。

猜你喜欢

转载自blog.csdn.net/sinat_38079265/article/details/108449614