遗传算法简单介绍与MATLAB实现(一)

遗传算法简单介绍与MATLAB实现(一)

一点前奏

第一次听说遗传算法是在高三晚上放学回家的路上,同行的小伙伴问我:你知道遗传算法么?我自然没听说过,于是追问细节。

“听说遗传算法能够自我迭代,让他本身系统内的东西进行优胜劣汰的自然选择,把好的保留下来,次一点的东西就排除掉。是不是特别像人工智能的那种感觉?”

这么高端的么?那时候我就对这个算法产生了一点兴趣,毕竟一个算法是如何做到自我判断什么是好什么是坏。

因为如此,在我接触到编程以后,我终于有能力去深入研究一下遗传算法了。最后觉得,其实这个算法也没有当初想得那么玄乎。

当初年轻不懂事时,对未知的事物有着天然的好奇,自然会把遗传算法想的无限大,甚至认为可以自我淘汰不好的代码,学习优秀的代码等。

其实现在再看过来,遗传算法的本质始终没变,依旧是优胜劣汰,选出最优秀的个体。只不过它的作用被我规划成了“求一个系统/模型的最优解”。

遗传算法简介

顾名思义,学过高中生物的都应该可以理解“遗传”是什么,染色体变异、染色体交叉等术语应该也能够大概知道是什么意思。其实遗传算法主要就是模拟这一个过程。

不过我也不是专业搞生物的,高中的知识细节部分我早都忘光了,因此抛开其他的,接下来我用我的理解来定义一下遗传算法的过程。

遗传算法四个基础概念

遗传算法中,一个基本单位为“个体”,一个种群(系统)中拥有好多个体。每个个体携带两个内容:染色体与适应度。

为了形象起见,我们可以把一个个体比喻成一头羊,一堆羊聚集在一起就成了一个种群。每一只羊长的(肥瘦程度)都不同,有的很肥,有的很瘦。我们作为一个牧场的牧场主,最终目的是养出最肥的羊。而我们的羊比较奇葩,每天都会产仔,并且产完仔就会死去,令我们牧场羊的数量保持在一个确定的数量上。

为了逼迫羊们越来越肥,我们每天杀死最瘦的羊,然后越肥的羊就越有几率交配生孩子,生出的孩子有可能变肥,也有可能变瘦。这样长此以往下去,我们羊群的羊将会越来越肥,而我们也达到了我们的目的。

所以简单的总结一下,上面每一头羊都是一个“个体”,整个牧场就是一个种群。每一头羊有“决定肥瘦程度的染色体”与“肥瘦程度”。这个肥瘦程度就是我们要说的遗传算法的“适应度”。每一天我们将其称之为迭代一次,也就是换一批新羊。

或者用生物上的话来说,每一头羊都有染色体,染色体决定了他们表现出来的性状是怎样的。所以说,染色体决定了每一头羊的肥瘦程度。

因此我们建立以下对应关系:

  • 整个牧场 -> 一个种群
  • 一头羊->一个个体
  • 某头羊决定肥瘦程度的染色体->该个体的染色体
  • 肥瘦程度->适应度

明确了上面四个基础概念以后,我们就可以引出他们之间的相互关系。

种群中包含了若干个个体,每个个体都拥有两个属性:染色体与适应度。每一次迭代中,种群中的个体数量不变。

染色体

其实需要细讲的主要还是染色体。

染色体是遗传算法与“被求最优解模型”直接相关之处。通常来说一个模型想要求最优解,那么就肯定会存在变量,通过控制变量的值让模型的最终值达到最优。

所以在这里,模型中所有变量就构成了一条染色体。其中每一个变量称之为染色体上的一个基因。

比如说我们这里有一个多元函数 f=f(x,y) ,这个函数拥有最大值 fmax ,但是对应的最大值点 (xmax,ymax) 我们并不知道,用通常方法也十分难求出来,所以我们可以利用遗传算法来简单求解一下。所以就将染色体设定为两个节点(基因),第一个节点为 x ,第二个节点为 y

这是对于一个个体来说的,也就是对于单个个体,他的染色体值我可以写成一个向量为

chrom=[x,y]

适应度

那么得到了染色体,模型的最优解如何评价呢?就是利用适应度来寻找最优解。

每个个体的适应度就相当于这个模型在“这个染色体的变量的值下的解”。也就是说这个个体的染色体值为 chrom=[x1,y1] ,所以我们把 (x1,y1) 带入到之前的多元函数中,可以得到这个函数的一个解为 f1=f(x1,y1) ,解 f1 就是这一条染色体(个体)的适应度。

寻找最优解

对于整个种群,我们假设有 N 个个体,所以对应的,也就有 N 条染色体, N 个适应度。因此可以写成以下形式

Chrom=x1x2xNy1y2xN

Fitness=[f1,f2,,fN]T

其中每一行都代表着一个个体。

我们在这里假设每个个体的染色体的值各不相同,因此适应度(模型的解)也就各不相同。所以我们就可以从中挑出来最大的适应度,它就是在当前情况下的最优解,但不一定是真正的最大值 fmax

所以接下来的就是开始寻找真正的最大值(最优解)。

遗传算法流程

一次迭代包括以下几个过程:

  1. 染色体变异。即改变某个染色体的值;
  2. 染色体交叉。任意选择两个染色体交换部分基因;
  3. 计算适应度。计算每个染色体在当前迭代下对应的适应度。
  4. 优胜劣汰。选出最劣适应度的染色体,并将其用最优适应度染色体替换。
染色体变异

染色体变异作用于每一个个体,目的就是修改当前染色体,从而让其变得“更好”,也有可能变得“更坏”。

为了能够让已经就很优的个体不要贸然的跌下神坛,让不算特别好的个体突破阶级限制进入最优,我们可以做出以下规定:

  • 适应度越优的个体染色体变化范围越小;
  • 适应度越劣的个体染色体变化范围越大。

这样子就能够令整个种群的阶级随时保持流动。

假设某个个体的染色体的某个节点 x 要发生变异,我们现在必须已知:当前迭代下种群中的最优适应度 fbest ;当前个体的适应度 f

然后我们产生一个随机数 rand ,就是这个节点的变化值,所以通过公式

xnew=x[1±rand(1ffbest)2]

可以得到新的染色体节点值 xnew .其中,正负号随机决定,代表着当前染色体节点值应该变大还是变小。

这个式子代表着,当 f 越趋近于 fbest 时, (1ffbest)2 就趋近于0,说明对原 x 的改变越小(变化量几乎为0);当 f 远离 fbest 时, (1ffbest)2 越趋近于1,说明对原 x 的改变越大。

染色体交叉

染色体交叉比较容易,随机选择两个染色体,在随机选择一对节点,相互交换对应的值即可。

比如有两个个体的染色体为 chromm=[xm,ym],chromn=[xn,yn] ,我们选择将其第一个节点上的两个节点进行交叉互换,得到新的两个染色体值为 chromm=[xn,ym],chromn=[xm,yn]

计算适应度

计算适应度其实就是将每个个体的染色体带入到模型中进行计算,计算出来其对应的适应度。

优胜劣汰

为了让我们种群的适应度整体水平上升,我们必须杀死排名最后的那个个体。

杀死之后种群数量就变少了,所以就必须要让比较优良的个体多生点来把种群数量补回来。在这里我为了方便,直接把最劣的个体的染色体替换成了最优个体的染色体。

这样子就是优胜劣汰,略微的把整体适应度水平提升了一点。


小结

以上就是遗传算法的大概流程。因为遗传算法的实现方法较多,所以这是按照我个人习惯整合成的一个遗传算法。一般来说,遗传算法的染色体还可以由二进制表示,优胜劣汰的方法也有其他方法,在这里我们就不多赘述。

下一章将会引入MATLAB代码,引入实际模型来进行一个具体的计算。

猜你喜欢

转载自blog.csdn.net/hanpu_liang/article/details/78169525
今日推荐