本章详细讨论了人工智能的遗传算法。
什么是遗传算法?
遗传算法(GA)是基于自然选择和遗传概念的基于搜索的算法。GA是更大的计算分支的子集,称为进化计算。
GA由John Holland及其密歇根大学的学生和同事开发,最着名的是David E. Goldberg。从那以后,已经尝试了各种优化问题并取得了很大的成功。
在GA中,我们有一组可能的解决方案来解决给定的问题。然后这些溶液经历重组和突变(如在天然遗传学中),产生新的儿童,并且该过程重复多代。为每个个体(或候选解决方案)分配适合度值(基于其目标函数值),并且使得更健康的个体具有更高的交配和产生更健康的个体的机会。这符合达尔文适者生存理论。
因此,它不断发展更好的个人或解决方案,直到它达到停止标准。
遗传算法在本质上具有足够的随机性,但它们比随机局部搜索(我们只是尝试随机解决方案,跟踪迄今为止的最佳解决方案)表现得更好,因为它们也利用了历史信息。
如何使用GA进行优化问题?
优化是使设计,情境,资源和系统尽可能有效的行动。以下框图显示了优化过程 -
GA机制优化过程的阶段
以下是用于优化问题的GA机制的一系列步骤。
- 第1步 - 随机生成初始种群。
- 第2步 - 选择具有最佳适合度值的初始解决方案。
- 步骤3 - 使用突变和交叉算子重新组合所选解决方案。
- 第4步 - 将后代插入人口。
- 步骤5 - 现在,如果满足停止条件,则返回具有最佳适合度值的解决方案。否则转到第2步。
安装必要的软件包
为了通过Python中的遗传算法解决问题,我们将使用一个名为DEAP的功能强大的GA包。它是一个新的进化计算框架库,用于快速原型设计和思想测试。我们可以在命令提示符下使用以下命令安装此软件包 -
1
|
pip install deap |
如果您使用的是anaconda环境,则可以使用以下命令安装deap -
1
|
conda install - c conda - forge deap |
使用遗传算法实现解决方案
本节将介绍使用遗传算法实现解决方案的过程。
生成位模式
以下示例显示如何根据One Max问题生成包含15个字符串的位字符串。
如图所示导入必要的包 -
1
2
|
import random from deap import base, creator, tools |
定义评估功能。这是创建遗传算法的第一步。
1
2
3
|
def eval_func(individual): target_sum = 15 return len (individual) - abs ( sum (individual) - target_sum), |
现在,使用正确的参数创建工具箱 -
1
2
3
|
def create_toolbox(num_bits): creator.create( "FitnessMax" , base.Fitness, weights = ( 1.0 ,)) creator.create( "Individual" , list , fitness = creator.FitnessMax) |
初始化工具箱
1
2
3
4
5
|
toolbox = base.Toolbox() toolbox.register( "attr_bool" , random.randint, 0 , 1 ) toolbox.register( "individual" , tools.initRepeat, creator.Individual, toolbox.attr_bool, num_bits) toolbox.register( "population" , tools.initRepeat, list , toolbox.individual) |
注册评估运营商 -
1
|
toolbox.register( "evaluate" , eval_func) |
现在,注册交叉运算符 -
1
|
toolbox.register( "mate" , tools.cxTwoPoint) |
注册变异算子 -
1
|
toolbox.register( "mutate" , tools.mutFlipBit, indpb = 0.05 ) |
定义繁殖的运营商 -
1
2
3
4
5
6
7
8
9
10
|
toolbox.register( "select" , tools.selTournament, tournsize = 3 ) return toolbox if __name__ = = "__main__" : num_bits = 45 toolbox = create_toolbox(num_bits) random.seed( 7 ) population = toolbox.population(n = 500 ) probab_crossing, probab_mutating = 0.5 , 0.2 num_generations = 10 print ( '\nEvolution process starts' ) |
评估整个人口 -
1
2
3
4
|
fitnesses = list ( map (toolbox.evaluate, population)) for ind, fit in zip (population, fitnesses): ind.fitness.values = fit print ( '\nEvaluated' , len (population), 'individuals' ) |
创造和迭代几代人 -
1
2
|
for g in range (num_generations): print ( "\n- Generation" , g) |
选择下一代个人 -
1
|
offspring = toolbox.select(population, len (population)) |
现在,克隆选定的个人 -
1
|
offspring = list ( map (toolbox.clone, offspring)) |
在后代上应用交叉和变异 -
1
2
3
|
for child1, child2 in zip (offspring[:: 2 ], offspring[ 1 :: 2 ]): if random.random() < probab_crossing: toolbox.mate(child1, child2) |
删除孩子的健身价值
1
2
|
del child1.fitness.values del child2.fitness.values |
现在,应用变异 -
1
2
3
4
|
for mutant in offspring: if random.random() < probab_mutating: toolbox.mutate(mutant) del mutant.fitness.values |
评估健康状况不佳的人 -
1
2
3
4
5
|
invalid_ind = [ind for ind in offspring if not ind.fitness.valid] fitnesses = map (toolbox.evaluate, invalid_ind) for ind, fit in zip (invalid_ind, fitnesses): ind.fitness.values = fit print ( 'Evaluated' , len (invalid_ind), 'individuals' ) |
现在,用下一代个人取代人口 -
1
|
population[:] = offspring |
打印当前世代的统计数据 -
1
2
3
4
5
6
7
8
9
|
fits = [ind.fitness.values[ 0 ] for ind in population] length = len (population) mean = sum (fits) / length sum2 = sum (x * x for x in fits) std = abs (sum2 / length - mean * * 2 ) * * 0.5 print ( 'Min =' , min (fits), ', Max =' , max (fits)) print ( 'Average =' , round (mean, 2 ), ', Standard deviation =' , round (std, 2 )) print ( "\n- Evolution ends" ) |
打印最终输出 -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
best_ind = tools.selBest(population, 1 )[ 0 ] print ( '\nBest individual:\n' , best_ind) print ( '\nNumber of ones:' , sum (best_ind)) Following would be the output: Evolution process starts Evaluated 500 individuals - Generation 0 Evaluated 295 individuals Min = 32.0 , Max = 45.0 Average = 40.29 , Standard deviation = 2.61 - Generation 1 Evaluated 292 individuals Min = 34.0 , Max = 45.0 Average = 42.35 , Standard deviation = 1.91 - Generation 2 Evaluated 277 individuals Min = 37.0 , Max = 45.0 Average = 43.39 , Standard deviation = 1.46 … … … … - Generation 9 Evaluated 299 individuals Min = 40.0 , Max = 45.0 Average = 44.12 , Standard deviation = 1.11 - Evolution ends Best individual: [ 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 1 , 0 , 0 , 1 , 0 , 1 ] Number of ones: 15 |
符号回归问题
这是遗传编程中最着名的问题之一。所有符号回归问题都使用任意数据分布,并尝试使用符号公式拟合最准确的数据。通常,像RMSE(均方根误差)这样的度量用于衡量个体的适应度。这是一个经典的回归问题,在这里我们使用等式5x 3 -6x 2 + 8x = 1。我们需要遵循上面示例中的所有步骤,但主要部分是创建原始集,因为它们是个人的构建块,因此评估可以开始。在这里,我们将使用经典的基元集。
以下Python代码详细解释了这一点 -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
import operator import math import random import numpy as np from deap import algorithms, base, creator, tools, gp def division_operator(numerator, denominator): if denominator = = 0 : return 1 return numerator / denominator def eval_func(individual, points): func = toolbox. compile (expr = individual) return math.fsum(mse) / len (points), def create_toolbox(): pset = gp.PrimitiveSet( "MAIN" , 1 ) pset.addPrimitive(operator.add, 2 ) pset.addPrimitive(operator.sub, 2 ) pset.addPrimitive(operator.mul, 2 ) pset.addPrimitive(division_operator, 2 ) pset.addPrimitive(operator.neg, 1 ) pset.addPrimitive(math.cos, 1 ) pset.addPrimitive(math.sin, 1 ) pset.addEphemeralConstant( "rand101" , lambda : random.randint( - 1 , 1 )) pset.renameArguments(ARG0 = 'x' ) creator.create( "FitnessMin" , base.Fitness, weights = ( - 1.0 ,)) creator.create( "Individual" ,gp.PrimitiveTree,fitness = creator.FitnessMin) toolbox = base.Toolbox() toolbox.register( "expr" , gp.genHalfAndHalf, pset = pset, min_ = 1 , max_ = 2 ) toolbox.expr) toolbox.register( "population" ,tools.initRepeat, list , toolbox.individual) toolbox.register( "compile" , gp. compile , pset = pset) toolbox.register( "evaluate" , eval_func, points = [x / 10. for x in range ( - 10 , 10 )]) toolbox.register( "select" , tools.selTournament, tournsize = 3 ) toolbox.register( "mate" , gp.cxOnePoint) toolbox.register( "expr_mut" , gp.genFull, min_ = 0 , max_ = 2 ) toolbox.register( "mutate" , gp.mutUniform, expr = toolbox.expr_mut, pset = pset) toolbox.decorate( "mate" , gp.staticLimit(key = operator.attrgetter( "height" ), max_value = 17 )) toolbox.decorate( "mutate" , gp.staticLimit(key = operator.attrgetter( "height" ), max_value = 17 )) return toolbox if __name__ = = "__main__" : random.seed( 7 ) toolbox = create_toolbox() population = toolbox.population(n = 450 ) hall_of_fame = tools.HallOfFame( 1 ) stats_fit = tools.Statistics( lambda x: x.fitness.values) stats_size = tools.Statistics( len ) mstats = tools.MultiStatistics(fitness = stats_fit, size = stats_size) mstats.register( "avg" , np.mean) mstats.register( "std" , np.std) mstats.register( "min" , np. min ) mstats.register( "max" , np. max ) probab_crossover = 0.4 probab_mutate = 0.2 number_gen = 10 population, log = algorithms.eaSimple(population, toolbox, probab_crossover, probab_mutate, number_gen, stats = mstats, halloffame = hall_of_fame, verbose = True ) |
请注意,所有基本步骤与生成位模式时使用的步骤相同。该程序将在10代之后给出输出为min,max,std(标准偏差)。
以上就是AI与Python人工智能遗传算法的详细内容,更多关于AI Python遗传算法的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/weixin_42238387/article/details/89052833