遗传算法(Genetic Algorithm)_遗传算法csdn-程序员宅基地

技术标签: 数学建模  

现代优化算法:禁忌搜索、模拟退火、遗传算法、人工神经网络

1. 遗传算法简介

遗传算法(Genetic Algorithm, GA)起源于对生物系统所进行的计算机模拟研究。它是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法,借鉴了达尔文的进化论和孟德尔的遗传学说。其本质是一种高效、并行、全局搜索的方法,能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最佳解。

在这里插入图片描述

在这里插入图片描述

2. 遗传算法相关术语

  • 基因型(genotype):性状染色体的内部表现;

在这里插入图片描述

  • 表现型(phenotype):染色体决定的性状的外部表现,或者说,根据基因型形成的个体的外部表现

  • 进化(evolution):种群逐渐适应生存环境,品质不断得到改良。生物的进化是以种群的形式进行的。

  • 适应度(fitness):度量某个物种对于生存环境的适应程度

适应度得分更高的个体代表了更好的解,其更有可能被选择繁殖并且其性状会在下一代中得到表现。
随着遗传算法的进行,解的质量会提高,适应度会增加,一旦找到具有令人满意的适应度值的解,终止遗传算法。

  • 选择(selection):以一定的概率从种群中选择若干个个体。一般,选择过程是一种基于适应度的优胜劣汰的过程。

  • 复制(reproduction):细胞分裂时,遗传物质DNA通过复制而转移到新产生的细胞中,新细胞就继承了旧细胞的基因。

  • 交叉(crossover):两个染色体的某一相同位置处DNA被切断,前后两串分别交叉组合形成两个新的染色体。也称基因重组或杂交;
    在这里插入图片描述

  • 变异(mutation):复制时可能(很小的概率)产生某些复制差错,变异产生新的染色体,表现出新的性状。
    在这里插入图片描述

  • 编码(coding):DNA中遗传信息在一个长链上按一定的模式排列。遗传编码可看作从表现型到基因型的映射。

  • 解码(decoding):基因型到表现型的映射。

  • 个体(individual):指染色体带有特征的实体;

  • 种群(population):个体的集合,该集合内个体数称为种群的大小。
    在这里插入图片描述
    在这里插入图片描述

3. 以示例出发

遗传算法的有趣应用很多,诸如

  1. 寻路问题;
  2. 8数码问题;
  3. 囚犯困境;
  4. 动作控制;
  5. 找圆心问题(在一个不规则的多边形中,寻找一个包含在该多边形内的最大圆圈的圆心);
  6. TSP问题;
  7. 生产调度问题;
  8. 人工生命模拟等。

下面我以袋鼠为例子讲讲遗传算法。

在这里插入图片描述
在这里插入图片描述

遗传算法中每一条染色体,对应着遗传算法的一个解决方案,一般我们用适应性函数(fitness function)来衡量这个解决方案的优劣。
所以从一个基因组到其解的适应度形成一个映射。可以把遗传算法的过程看作是一个在多元函数里面求最优解的过程。
可以这样想象,这个多维曲面里面有数不清的“山峰”,而这些山峰所对应的就是局部最优解。而其中也会有一个“山峰”的海拔最高的,那么这个就是全局最优解。而遗传算法的任务就是尽量爬到最高峰,而不是陷落在一些小山峰。(另外,值得注意的是遗传算法不一定要找“最高的山峰”,如果问题的适应度评价越小越好的话,那么全局最优解就是函数的最小值,对应的,遗传算法所要找的就是“最深的谷底”)
在这里插入图片描述

3.1 问题的提出与解决方案

现在要求在既定的区间内找出函数的最大值

f ( x ) = x sin ⁡ ( 10 π x ) + 2 x ∈ [ − 1 , 2 ] \begin{align} f(x) &=x\sin(10\pi x)+2\\ x &\in [-1,2] \end{align} f(x)x=xsin(10πx)+2[1,2]

在这里插入图片描述

“袋鼠跳”问题
既然我们把函数曲线理解成一个一个山峰和山谷组成的山脉。那么我们可以设想所得到的每一个解就是一只袋鼠,我们希望它们不断的向着更高处跳去,直到跳到最高的山峰(尽管袋鼠本身不见得愿意那么做)。所以求最大值的过程就转化成一个“袋鼠跳”的过程。

在这里插入图片描述

3.2 方法对比

作为对比下面简单介绍“袋鼠跳”的几种方式。

  1. 爬山法(最速上升爬山法)
    从搜索空间中随机产生邻近的点,从中选择对应解最优的个体,替换原来的个体,不断重复上述过程。因为爬山法只对“邻近”的点作比较,所以目光比较“短浅”,常常只能收敛到离开初始位置比较近的局部最优解上面。对于存在很多局部最优点的问题,通过一个简单的迭代找出全局最优解的机会非常渺茫。

在爬山法中,袋鼠最有希望到达最靠近它出发点的山顶,但不能保证该山顶是珠穆朗玛峰,或者是一个非常高的山峰。因为一路上它只顾上坡,没有下坡。

  1. 模拟退火
    这个方法来自金属热加工过程的启发。在金属热加工过程中,当金属的温度超过它的熔点(Melting Point)时,原子就会激烈地随机运动。与所有的其它的物理系统相类似,原子的这种运动趋向于寻找其能量的极小状态。在这个能量的变迁过程中,开始时,温度非常高, 使得原子具有很高的能量。随着温度不断降低,金属逐渐冷却,金属中的原子的能量就越来越小,最后达到所有可能的最低点。利用模拟退火的时候,让算法从较大的跳跃开始,使到它有足够的“能量”逃离可能“路过”的局部最优解而不至于限制在其中,当它停在全局最优解附近的时候,逐渐的减小跳跃量,以便使其“落脚 ”到全局最优解上。

在模拟退火中,袋鼠喝醉了,而且随机地大跳跃了很长时间。运气好的话,它从一个山峰跳过山谷,到了另外一个更高的山峰上。但最后,它渐渐清醒了并朝着它所在的峰顶跳去。

  1. 遗传算法
    模拟物竞天择的生物进化过程,通过维护一个潜在解的群体执行了多方向的搜索,并支持这些方向上的信息构成和交换。是以面为单位的搜索,比以点为单位的搜索,更能发现全局最优解。(在遗传算法中,有很多袋鼠,它们降落到喜玛拉雅山脉的任意地方。这些袋鼠并不知道它们的任务是寻找珠穆朗玛峰。但每过几年,就在一些海拔高度较低的地方射杀一些袋鼠,并希望存活下来的袋鼠是多产的,在它们所处的地方生儿育女。)

从前,有一大群袋鼠,它们被莫名其妙的零散地遗弃于喜马拉雅山脉。于是只好在那里艰苦的生活。海拔低的地方弥漫着一种无色无味的毒气,海拔越高毒气越稀薄。可是可怜的袋鼠们对此全然不觉,还是习惯于活蹦乱跳。于是,不断有袋鼠死于海拔较低的地方,而越是在海拔高的袋鼠越是能活得更久,也越有机会生儿育女。就这样经过许多年,这些袋鼠们竟然都不自觉地聚拢到了一个个的山峰上,可是在所有的袋鼠中,只有聚拢到珠穆朗玛峰的袋鼠被带回了美丽的澳洲。

在这里插入图片描述

3.3 遗传算法的实现过程

  • 遗传算法的实现过程实际上就像自然界的进化过程那样。首先寻找一种对问题潜在解进行“数字化”编码的方案。(建立表现型和基因型的映射关系)

  • 随机数初始化一个种群(那么第一批袋鼠就被随意地分散在山脉上),种群里面的个体就是这些数字化的编码

  • 通过适当的解码过程之后(得到袋鼠的位置坐标),用适应性函数对每一个基因个体作一次适应度评估(袋鼠爬得越高,越是受我们的喜爱,所以适应度相应越高)。

  • 选择函数按照某种规定择优选择。(我们要每隔一段时间,在山上射杀一些所在海拔较低的袋鼠,以保证袋鼠总体数目持平。)

  • 让个体基因变异(让袋鼠随机地跳一跳)。然后产生子代(希望存活下来的袋鼠是多产的,并在那里生儿育女)。

在这里插入图片描述

遗传算法并不保证你能获得问题的最优解,但是使用遗传算法的最大优点在于你不必去了解和操心如何去“找”最优解。(你不必去指导袋鼠向那边跳,跳多远。)而只要简单的“否定”一些表现不好的个体就行了。(把那些总是爱走下坡路的袋鼠射杀,这就是遗传算法的精粹!)

3.4 遗传算法的一般步骤

开始循环直至找到满意的解。

  1. 评估每条染色体所对应个体的适应度。
  2. 遵照适应度越高,选择概率越大的原则,从种群中选择两个个体作为父方和母方。
  3. 抽取父母双方的染色体,进行交叉,产生子代。
  4. 对子代的染色体进行变异。
  5. 重复2,3,4步骤,直到新种群的产生。
    结束循环。
    在这里插入图片描述

在这里插入图片描述

3.5 遗传算法的一般应用

接下来,我们将详细地剖析遗传算法过程的每一个细节。

3.5.1 编制袋鼠的染色体——基因的编码方式

假设目前只有“0”,“1”两种碱基,我们也用一条链条把他们有序的串连在一起,因为每一个单位都能表现出 1 bit的信息量,所以一条足够长的染色体就能为我们勾勒出一个个体的所有特征。这就是二进制编码法,染色体大致如下:010010011011011110111110

上面编码方式简单直观,但个体特征复杂时,需要大量的编码才能精确描述,为改善遗传算法的计算复杂性、提高运算效率,提出了浮点数编码。染色体大致如下:1.2 –3.3 – 2.0 –5.4 – 2.7 – 4.3(注:还有一种编码方式叫符号编码)

我们就能做两件必须去做的事情:

  • 通过查阅喜玛拉雅山脉的地图来得知袋鼠所在的海拔高度(通过自变量求适应函数的值。)以判断我们有没必要把它射杀。
  • 知道袋鼠跳一跳(交叉和变异)后去到哪个新位置。

“个体特征”是必要的——问题相关
既然确定了袋鼠的位置作为个体特征,具体来说位置就是横坐标。那么接下来,我们就要建立表现型到基因型的映射关系。就是说如何用编码来表现出袋鼠所在的横坐标。由于横坐标是一个实数,所以说透了我们就是要对这个实数编码。用浮点数编码——需要一个浮点数。而下面则介绍如何建立二进制编码到一个实数的映射。
编码过程:
一定长度的二进制编码序列,只能表示一定精度的浮点数。譬如我们要求解精确到六位小数,区间长度为 2 – ( – 1 ) = 3 2 – (–1) = 3 2–(–1)=3 ,为了保证精度要求,至少把区间 [ − 1 , 2 ] [-1,2] [1,2]分为 3 × 1 0 6 3 × 10^6 3×106等份。又因为

2097152 = 2 21 < 3 × 1 0 6 < 2 22 = 4194304 \begin{align} 2097152=2^{21}<3×10^6<2^{22}=4194304 \end{align} 2097152=221<3×106<222=4194304

所以编码的二进制串至少需要22位。
把一个二进制串 ( b 0 , b 1 , . . . . b n ) (b_0,b_1,....b_n) (b0,b1,....bn)转化位区间里面对应的实数值通过下面两个步骤。
(1) 将一个二进制串代表的二进制数转化为10进制数:
( b 0 b 1 . . . . b n ) 2 = ( ∑ i = 0 21 b i 2 i ) 10 = x t \begin{align} (b_0b_1....b_n)_2={ {(\sum\limits_{i=0}^{21}{ { {b}_{i}}{ {2}^{i}}})}_{10}}={ {x}^{t}} \end{align} (b0b1....bn)2=(i=021bi2i)10=xt

(2) 对应区间内的实数:

x = − 1 + x t × ( 2 − ( − 1 ) ) 2 22 − 1 \begin{align} x=-1+{ {x}^{t}} ×\frac{(2-(-1))}{ { {2}^{22}}-1} \end{align} x=1+xt×2221(2(1))
在这里插入图片描述
例如一个二进制串<1000101110110101000111>表示实数值0.637197。

x t = ( 1000101110110101000111 ) 2 = 2288967 \begin{align} x^t =(1000101110110101000111)_2 = 2288967 \end{align} xt=(1000101110110101000111)2=2288967

x = − 1 + 2288967 × ( 2 − ( − 1 ) ) 2 22 − 1 = 0.637197 \begin{align} x=-1+{2288967} ×\frac{(2-(-1))}{ { {2}^{22}}-1}=0.637197 \end{align} x=1+2288967×2221(2(1))=0.637197

二进制串<000000000000000000>和<1111111111111111>则分别表示区间的两个端点值-1和2。

在这里插入图片描述
能够将十进制的数编码为二进制即可,至于这个映射是什么,其实可以怀必关心。将个体(可能解)编码后的二进制串叫做染色体,染色体(或者有人叫DNA)就是个体(可能解)的二进制编码表示。为什么可以不必关心映射 f ( x ) f(x) f(x)呢?因为其实我们在程序中操纵的都是二进制串,而二进制串生成时可以随机生成,如:

#pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目,DNA_ SIZE为编码长度
pop = np. random.randint(2, size=(POP_SIZE, DNA_ SIZE*2)) #matrix (POP_ SIZE, DNA_ SIZE*2)

实际上是没有需求需要将一个十进制数转化为一个二进制数,而在最后我们肯定要将编码后的二进制串转换为我们理解的十进制串,所以我们需要的是 y = f ( x ) y = f(x) y=f(x)的逆映射,也就是将二进制转化为十进制, 这个过程叫做解码,理解了解码编码还难吗?先看具体的解码过程如下。

首先我们限制二进制串的长度为10 (长度自己指定即可,越长精度越高),例如我们有一个二进制串(在程序中用数组存储即可)

[ 0 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 0 , 1 ] \begin{align} [0,1,0,1,1,1,0,1,0,1] \end{align} [0,1,0,1,1,1,0,1,0,1]

这个二进制串如何转化为实数呢?不要忘记我们的 x , y ∈ [ − 3 , 3 ] x,y∈[- 3, 3] x,y[3,3]这个限制,我们目标是求一个逆映射将这个二进制串映射到 x , y ∈ [ − 3 , 3 ] x,y∈[-3, 3] x,y[3,3]即可,为为更一般化我们将 x x x, y y y的取值范围用一个变量表示,在程序中可以用python语言写到:

X_ BOUND = [-33] #x取值范围
Y_ BOUND = [-3, 3] #y取值范围

为将二进制串映射到指定范围,首先先将进制串按权展开,将二进制数转化为十进制数,我们有 0 ∗ 29 + 1 ∗ 28 + 0 ∗ 27 + . . . + 0 ∗ 20 + 1 ∗ 20 = 373 0*29+1*28+0*27 +...+0*20+1*20= 373 029+128+027+...+020+120=373, 然后将转换后的实数压缩到 [ 0 , 1 ] [0, 1] [0,1]之间的一个小数, 373 / ( 210 − 1 ) ≈ 0.36461388074 373/ (210- 1)≈0.36461388074 373/(2101)0.36461388074,通过以上这些步骤所有二进制串表示都可以转换为 [ 0 , 1 ] [0, 1] [0,1]之间的小数,现在只需要将 [ 0 , 1 ] [0, 1] [0,1]区间内的数映射到我们要的区间即可。假设区间 [ 0 , 1 ] [0, 1] [0,1]内的数称为num,转换在python语言中可以写成:

#X_ BOUND, Y_ BOUND是x, y的取值范围x BOUND = [-3, 3], Y_ BOUND = [-3, 3],
x_= num*(X_BOUND[1]-X_BOUND[0]) + X_BOUND[0] #映射为x范围内的数
y_= num*(Y_BOUND[1]-Y_BOUND[0]) + Y_BOUND[0] #映射为y范围内的数

通过以上这些标记为蓝色的步骤我们完成了将一个二进制串映射到指定范围内的任务(解码) 。

在这里插入图片描述

3.5.2 解析袋鼠的染色体——基因的解码方式

不难看出上面我们的DNA (二进制串)长为10,10位二进制可以表示 2 10 2^{10} 210种不同的状态,可以看成是将最后要转化为的十进制区间 x , y ∈ [ − 3 , 3 ] x,y∈[- 3, 3] x,y[3,3] (下面讨论都时转化到这个区间)切分成 2 10 2^{10} 210份,显而易见,如果我们增加二进制串的长度,那么我们对区间的切分可以更加精细,转化后的十进制解也更加精确。

十位二进制全1按权展开为 1023 1023 1023,最后映射到 [ − 3 , 3 ] [-3, 3] [3,3]区间时为3,而 1111111110 1111111110 1111111110按权展开为 1022 1022 1022
1022 / ( 2 10 − 1 ) ≈ 0.999022 0.999022 ∗ ( 3 − ( − 3 ) ) + ( − 3 ) ≈ 2.994134 \begin{align} &1022/(2^{10} - 1)≈0.999022\\ &0.999022*(3- (-3))+(-3)≈2.994134 \end{align} 1022/(2101)0.9990220.999022(3(3))+(3)2.994134

如果我们将实数编码为12位二进制, 111111111111 111111111111 111111111111最后转化为3,而 111111111110 111111111110 111111111110按权展开为 4094 4094 4094,
4094 / ( 2 12 − 1 = 4095 ) ≈ 0.999756 0.999755 ∗ ( 3 − ( − 3 ) ) + ( − 3 ) ≈ 2.998534 \begin{align} &4094/(2^{12}- 1 = 4095)≈0.999756\\ &0.999755* (3-(- 3))+(-3)≈2.998534 \end{align} 4094/(2121=4095)0.9997560.999755(3(3))+(3)2.998534

3 − 2.994134 = 0.005866 3 − 2.998534 = 0.001466 \begin{align} &3 - 2.994134 = 0.005866\\ &3 - 2.998534 = 0.001466 \end{align} 32.994134=0.00586632.998534=0.001466

可以看出用10位二进制编码划分区间后,每个二进制状态改变对应的实数大约改变 0.005866 0.005866 0.005866,而用12位二进制编码这个数字下降到0.001466,所以DNA长度越长,解码为10进制的实数越精确。
以下为解码过程的python代码:

#这里我设置DNA_ SIZE=24 (一个实数DNA长度) 
#两个实数$x, y$共用48位二进制编码
#我同时将x和y编码到同一个48位的二进制串里
#每一个变量用24位表示,奇数24列为$x$的编码表示,偶数24列为y的编码表示。
def translateDNA(pop):#pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目
	x_pop = pop[:,1::2]#奇数列表示X
	y_pop = pop[:,::2] #偶数列表示y
    #pop:(POP_SIZE,DNA_SIZE)*(DNA_SIZE,1) --> (POP_SIZE,1)完成解码
    x = x_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(X_BOUND[1]-X_BOUND[0])+X_BOUND[0]	
    y = y_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Y_BOUND[1]-Y_BOUND[0])+Y_BOUND[0]
    return x,y

在这里插入图片描述

3.5.3 物竞天择——适应性评分与及选择函数

  1. 物竞――适应度函数(fitness function)
    这个衡量的标准比较容易制定:袋鼠所在的海拔高度。所以我们直接用袋鼠的海拔高度作为它们的适应性评分。即适应度函数直接返回函数值就行了。适应度函数为目标函数的线性组合。
  2. 天择――选择函数(selection)
    自然界中,越适应的个体就越有可能繁殖后代。但是也不能说适应度越高的就肯定后代越多,只能是从概率上来说更多。下面我们介绍一种常用的选择方法――轮盘赌(Roulette Wheel Selection)选择法

比如我们有5条染色体,他们所对应的适应度评分分别为:5,7,10,13,15。

所以累计总适应度为:

F = ∑ i = 1 n f i = 5 + 7 + 10 + 13 + 15 = 50 \begin{align} F={ {\sum\limits_{i=1}^{n}{ { {f}_{i}}}}}=5+7+10+13+15=50 \end{align} F=i=1nfi=5+7+10+13+15=50

所以各个个体被选中的概率的分别是:
P 1 = f 1 F × 100 % = 5 50 × 100 % = 10 % P 2 = f 2 F × 100 % = 7 50 × 100 % = 14 % P 3 = f 3 F × 100 % = 10 50 × 100 % = 20 % P 4 = f 4 F × 100 % = 13 50 × 100 % = 26 % P 5 = f 5 F × 100 % = 15 50 × 100 % = 30 % \begin{align} &P_1=\frac{f_1}{F}×100\%=\frac{5}{50}×100\%=10\%\\ &P_2=\frac{f_2}{F}×100\%=\frac{7}{50}×100\%=14\%\\ &P_3=\frac{f_3}{F}×100\%=\frac{10}{50}×100\%=20\%\\ &P_4=\frac{f_4}{F}×100\%=\frac{13}{50}×100\%=26\%\\ &P_5=\frac{f_5}{F}×100\%=\frac{15}{50}×100\%=30\%\\ \end{align} P1=Ff1×100%=505×100%=10%P2=Ff2×100%=507×100%=14%P3=Ff3×100%=5010×100%=20%P4=Ff4×100%=5013×100%=26%P5=Ff5×100%=5015×100%=30%

在这里插入图片描述

很明显,适应度评分越高的个体被选中的概率越大。如果求最小值,可以加负号或者取倒数。

在这里插入图片描述

3.5.4 遗传变异――基因重组(交叉)与基因突变

应该说这两个步骤就是使得子代不同于父代的根本原因。对于这两种遗传操作,二进制编码和浮点型编码在处理上有很大的差异。

3.5.4.1 遗传变异――基因重组(交叉)(recombination/crossover)

(1)二进制编码——二进制编码的基因交换过程非常类似高中生物中所讲的同源染色体的联会过程――随机把其中几个位于同一位置的编码进行交换,产生新的个体。(单点、俩点、多点、均匀交叉)

  1. 单点
    10010 || 10010——>10010 || 01010
    10101 || 01010——>10101 || 10010

  2. 俩点
    10010 || 10 || 10101——>10010 || 00 || 10101
    10001 || 00 || 11001——>10001 || 10 || 11001

(2)浮点数编码——如果一条基因中含有多个浮点数编码,那么也可以用跟上面类似的方法进行基因交叉,不同的是进行交叉的基本单位不是二进制码,而是浮点数。而如果对于单个浮点数的基因交叉,就有其它不同的重组方式了,比如中间重组:随机产生就能得到介于父代基因编码值和母代基因编码值之间的值作为子代基因编码的值。
5.5——>5.7
6.0——>5.6

在这里插入图片描述

3.5.4.2 遗传变异――基因突变(Mutation)

(1)二进制编码
基因突变过程:基因突变是染色体的某一个位点上基因的改变。基因突变使一个基因变成它的等位基因,并且通常会引起一定的表现型变化。正如上面所说,二进制编码的遗传操作过程和生物学中的过程非常相类似,基因串上的“ 0”或“ 1”有一定几率变成与之相反的“ 1”或“ 0”。
在这里插入图片描述
(2)浮点型编码
浮点型编码的基因突变过程一般是对原来的浮点数增加或者减少一个小随机数。比如原来的浮点数串如下:
1.2 3.4 5.1 6.0 4.5
1.3 3.1 4.9 6.3 4.4
当然,这个小随机数也有大小之分,我们一般管它叫“步长”。一般来说步长越大,开始时进化的速度会比较快,但是后来比较难收敛到精确的点上。而小步长却能较精确的收敛到一个点上。所以很多时候为了加快遗传算法的进化速度,而又能保证后期能够比较精确地收敛到最优解上面,会采取动态改变步长的方法。其实这个过程与前面介绍的模拟退火过程比较相类似。

在这里插入图片描述

到此为止,基因编码,基因适应度评估,基因选择,基因变异都一一实现了,剩下来的就是把这些遗传过程的“零件”装配起来了。下面是上例的运行结果:

3.5.5 遗传算法结果

在这里插入图片描述

在这里插入图片描述

4. 遗传算法的优缺点

4.1 遗传算法的优点

1. 全局最优

在许多情况下,优化问题具有局部最大值和最小值。这些值代表的解比周围的解要好,但并不是最佳的解。

大多数传统的搜索和优化算法,尤其是基于梯度的搜索和优化算法,很容易陷入局部最大值,而不是找到全局最大值。

遗传算法更有可能找到全局最大值。这是由于使用了一组候选解,而不是一个候选解,而且在许多情况下,交叉和变异操作将导致候选解与之前的解有所不同。只要设法维持种群的多样性并避免过早趋同(premature convergence),就可能产生全局最优解。

2. 处理复杂问题

由于遗传算法仅需要每个个体的适应度函数得分,而与适应度函数的其他方面(例如导数)无关,因此它们可用于解决具有复杂数学表示、难以或无法求导的函数问题。

3. 处理缺乏数学表达的问题

遗传算法可用于完全缺乏数学表示的问题。这是由于适应度是人为设计的。例如,想要找到最有吸引力颜色组合,可以尝试不同的颜色组合,并要求用户评估这些组合的吸引力。使用基于意见的得分作为适应度函数应用遗传算法搜索最佳得分组合。即使适应度函数缺乏数学表示,并且无法直接从给定的颜色组合计算分数,但仍可以运行遗传算法。

只要能够比较两个个体并确定其中哪个更好,遗传算法甚至可以处理无法获得每个个体适应度的情况。例如,利用机器学习算法在模拟比赛中驾驶汽车,然后利用基于遗传算法的搜索可以通过让机器学习算法的不同版本相互竞争来确定哪个版本更好,从而优化和调整机器学习算法。

4. 耐噪音

一些问题中可能存在噪声现象。这意味着,即使对于相似的输入值,每次得到的输出值也可能有所不同。例如,当从传感器产生异常数据时,或者在得分基于人的观点的情况下,就会发生这种情况。

尽管这种行为可以干扰许多传统的搜索算法,但是遗传算法通常对此具有鲁棒性,这要归功于反复交叉和重新评估个体的操作。

5. 并行性

遗传算法非常适合并行化和分布式处理。适应度是针对每个个体独立计算的,这意味着可以同时评估种群中的所有个体。

另外,选择、交叉和突变的操作可以分别在种群中的个体和个体对上同时进行。

6. 持续学习

进化永无止境,随着环境条件的变化,种群逐渐适应它们。遗传算法可以在不断变化的环境中连续运行,并且可以在任何时间点获取和使用当前最佳的解。但是需要环境的变化速度相对于遗传算法的搜索速度慢。
在这里插入图片描述

4.2 遗传算法的局限性

1. 需要特殊定义

将遗传算法应用于给定问题时,需要为它们创建合适的表示形式——定义适应度函数和染色体结构,以及适用于该问题的选择、交叉和变异算子。

2. 超参数调整

遗传算法的行为由一组超参数控制,例如种群大小和突变率等。将遗传算法应用于特定问题时,没有标准的超参数设定规则。

3. 计算密集

种群规模较大时可能需要大量计算,在达到良好结果之前会非常耗时。可以通过选择超参数、并行处理以及在某些情况下缓存中间结果来缓解这些问题。

4. 过早趋同

如果一个个体的适应能力比种群的其他个体的适应能力高得多,那么它的重复性可能足以覆盖整个种群。这可能导致遗传算法过早地陷入局部最大值,而不是找到全局最大值。为了防止这种情况的发生,需要保证物种的多样性。

5. 无法保证的解的质量

遗传算法的使用并不能保证找到当前问题的全局最大值(但几乎所有的搜索和优化算法都存在此类问题,除非它是针对特定类型问题的解析解)。通常,遗传算法在适当使用时可以在合理的时间内提供良好的解决方案。
在这里插入图片描述

5. 遗传算法应用场景

遗传算法的应用十分广泛,特别是对于以下问题遗传算法常常能表现出优异性能,但是当问题具有已知的和专业的解决方法时,使用现有的传统方法或分析方法可能是更有效的选择。

  1. 数学表示复杂的问题

由于遗传算法仅需要适应度函数的结果,因此它们可用于难以求导或无法求导的目标函数问题,大量参数问题以及参数混合问题类型。

  1. 没有数学表达式的问题

只要可以获得分数值或有一种方法可以比较两个解,遗传算法就不需要对问题进行数学表示。

  1. 涉及噪声数据问题

遗传算法可以应对数据可能不一致的问题,例如源自传感器输出或基于人类评分的数据。

  1. 随时间而变化的环境所涉及的问题

遗传算法可以通过不断创建适应变化的新一代来响应较为缓慢的环境变化。
在这里插入图片描述

6. 适应度函数的重要性

适应度函数的选取直接影响遗传算法的收敛速度以及能否找到最优解。

一般而言,适应度函数是由目标函数变换而成的。适应度函数设计不当有可能出现欺骗问题:
(1)进化初期,个别超常个体控制选择过程;
(2)进化末期,个体差异太小导致陷入局部极值。

选择的作用:优胜劣汰,适者生存;
交叉的作用:保证种群的稳定性,朝着最优解的方向进化;
变异的作用:保证种群的多样性,避免交叉可能产生的局部收敛。
在这里插入图片描述

7. 遗传算法的代码实现

  1. 干货 | 遗传算法(Genetic Algorithm) Java 详细代码及注释
  2. 遗传算法介绍并附上Matlab代码

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_46225503/article/details/132218908

智能推荐

Layui实现点击文字、缩略图查看图片功能_layui查看图片-程序员宅基地

文章浏览阅读4.3k次。刚完成一个客户需求,同一个页面上要有点击缩略图查看大图功能,也有点击图片名称查看原图的功能。点击缩略图查看大图的功能点击缩略图查看大图的功能实现用的是layui开发文档内的layer.photos-相册层。官方开发文档里photos支持传入json和直接读取页面图片两种方式。下面是官方开发文档的截图,官方开发文档链接:https://www.layui.com/doc/m..._layui查看图片

ueditor的配置和使用-程序员宅基地

文章浏览阅读89次。ueditor下载好之后直接复制到项目的WebContent目录下,并将ueditor\jsp\lib下的jar包复制或者剪切到项目的lib目录下。先看一下效果,如下:v1.文件的上传   首先在ueditor/jsp目录下找到config.json文件,就拿Image上传来说吧。  "imageUrlPrefix": "http:/..._ueditor json = new function("return " + result)();

20、NanoDet训练、测试 以及使用ncnn部署Jetson Nano 进行目标检测和串口数据转发-程序员宅基地

文章浏览阅读6.5k次,点赞7次,收藏59次。基本思想:最近想尝试一下nano 上部署nanodet,于是记录一下训练过程,手中有一份labelme标注的数据集,于是开始了一波操作~首先将图片和json数据集转成xml (https://blog.csdn.net/sxj731533730/article/details/90046780),然后将xml数据集转成voc;import sysimport osimport jsonimport xml.etree.ElementTree as ETfrom PIL import Im_nanodet

code::blocks + wxWidgets 2.8 在ubuntu 10.04下的安装-程序员宅基地

文章浏览阅读930次。code::blocks + wxWidgets 2.8 在ubuntu 10.04下的安装p { margin-bottom: 0.21cm; }1、首先安装必要组件代码:安装编译器 sudo apt-get install build-essential

用java Swing做的小游戏&quot;像素鸟&quot;_java swing小游戏-程序员宅基地

文章浏览阅读4.4k次,点赞10次,收藏38次。最终效果 整个项目都是基于swing实现的。窗是口将图片加载到JPanel面板,然后将面板添加到到JFrame窗口实现显示。这个类是选择几只像素鸟的类,也是main函数里执行的方法,代码有详细的注释,这里就不废话了public class select extends JPanel { /** * */ private static final long serialVersio..._java swing小游戏

三分钟教你读懂支票是什么_支票的原理是什么-程序员宅基地

文章浏览阅读8.7k次。三分钟教你读懂支票是什么支票1、支票的概念及特点支票:出票人签发的,委托办理支票存款业务的银行或其他金融机构在见票时无条件支付确定金额给收款人或持票人的票据。支票必填项:支票字样、确定的金额、出票日期、无条件支付委托、付款人名称、出票人签章。支票选填项:付款地、出票地。支票结算特点:(1)简便,手续_支票的原理是什么

随便推点

P5738 【深基7.例4】歌唱比赛-程序员宅基地

文章浏览阅读311次。题目描述n(n\le 100)n(n≤100)名同学参加歌唱比赛,并接受m(m\le 20)m(m≤20)名评委的评分,评分范围是 0 到 10 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下m-2m−2个评分的平均数。请问得分最高的同学分数是多少?评分保留 2 位小数。输入格式无输出格式无输入输出样例输入 ..._【深基7.例4】歌唱比赛

Vue简明实用教程(04)——事件处理_vue html里面如何直接写事件函数-程序员宅基地

文章浏览阅读1.1k次,点赞4次,收藏5次。在Vue中可非常便利地进行事件处理,例如:点击事件、鼠标悬停事件等。_vue html里面如何直接写事件函数

南京邮电大学离散数学实验一(求主析取和主合取范式)-程序员宅基地

文章浏览阅读4.5k次,点赞15次,收藏67次。南京邮电大学离散数学实验一(求主析取和主合取范式)_离散数学实验

{spring.cloud.client.ipAddress}_spring.cloud.client.ip-address-程序员宅基地

文章浏览阅读1.5w次,点赞2次,收藏5次。1.在springcloud中服务的 Instance ID 默认值是:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}},也就是:主机名:应用名:应用端口。如图12.可以自定义:eureka.instance...._spring.cloud.client.ip-address

单目标跟踪OTB、VOT数据集介绍_otb数据集官网-程序员宅基地

文章浏览阅读2.1w次,点赞6次,收藏63次。OTB分为:OTB50和OTB100官方下载链接为:OTB官方数据集网站http://cvlab.hanyang.ac.kr/tracker_benchmark/datasets.html百度云链接:链接:https://pan.baidu.com/s/1Ck51d7OQ8w8BGcTL9UtopA提取码:jn0k复制这段内容后打开百度网盘手机App,操作更方便哦其中50和100,分别..._otb数据集官网

Xcode修改模拟器Simulator系统版本_xcode模拟器切换ios版本-程序员宅基地

文章浏览阅读5.1k次。从Xcode菜单栏里打开Xcode -&gt; Preferences -&gt; Components -&gt; Simulators,下载对应版本的模拟器。由于模拟器相关文件较大,下载时间较长,需要耐心等待,下载完成后,对应版本的模拟器前面的下载按钮就会变成下载完成的样式。点击Xcode菜单栏 Window -&gt; Devices,然后可以看到设备列表,然而在模拟器列表(..._xcode模拟器切换ios版本