matlab polyfit次数上限_初识遗传算法(MATLAB)

2cb2f24b49c3dd7487e95e9a6984c90f.png

在进行仿真时,模型中的很多参数总是不容易获取到的,所以我们经常会用一些优化算法来辨识这些参数,遗传算法(Genetic Algorithms)就是比较常见的一种。

其实我很早之前就接触过遗传算法,但可能当时需求不那么强烈,所以也只是简单地了解了一下,就没再深究。后来逐渐发现这是一座绕不过去的山,所以最近才又从头开始学习了。现在感觉自己也就是刚入门,只能够解决一些简单的问题,希望通过这篇文章记录下自己的所学,同时也巩固一下。

达尔文的生物进化论告诉我们,自然界中的生物都是在不断进化的,遵循“优胜劣汰,适者生存”的原则,遗传算法正是通过模拟生物的进化过程而将计算结果不断优化的一种生物智能算法。在编写代码之前,我们需要大概讲解一下遗传算法的原理,顺便介绍几个名词。我们假设在一个小岛上面有一群雌雄同体的生物,那么这一群生物就叫一个种群(pop),生物的个数就是种群大小(pop_size),我们假设有500只初代生物,为了计算方便,遗传算法在计算过程中要控制每一代的种群大小都是500。既然要进行优胜劣汰,那总是要有一个衡量标准的,这里我们选取身高作为衡量标准,即个子高的生存下来的概率就高,每个生物的身高即为适应度(fitness_value)。这里需要强调的是,个子高的生物只是生存的概率大,并不是就一定就会生存下来,这其实也更符合生物进化的实际情况。首先我们需要进行种群初始化,即假定500只初代生物的身高都是随机的。然后我们根据一定的挑选原则选择出500对父母(一些个体会被重复选择),这个过程叫选择,在后面的过程中再详细讲解。我们现在只需要知道在选择的过程中,适应度高的个体被选中的概率就高,基因被遗传下去的概率就高。选择出500对父母之后,我们就让它们繁衍后代,我们规定他们一定能且只能生下一个子代个体,这样500对父母就会生下500个子代,在整个遗传迭代过程中都保证了种群大小不变。子代生成的过程就是交叉变异。交叉就是在一定概率下(交叉概率,pc),父亲和母亲各取一部分基因染色体,组成子代的染色体,而交叉完成之后,染色体中某一个位点会有一定的概率发生变异(变异概率,pm),最终才得到500个子代。而子代诞生后,父亲和母亲那一代就完成了使命,驾鹤西去。而子代再继续进行选择,交叉和变异,再生成下一代。为了避免算法无限迭代下去,我们要设定在某一代就停止繁衍,即最大迭代次数(gen_max),然后我们就从这最后一代中寻找个子最高的个体。

了解完遗传算法的原理之后,我们就通过一个简单的例子来了解下遗传算法的优化求解过程:

算例:请求解函数f(x)=4*cos(6*x)+3*sin(5*x)在区间[-pi,pi]上的最小值,取到最小值时的x是多少?要求自变量的误差小于0.01。

这种函数形式是大家在展示优化算法时最常用的,因为函数曲线会有很多个波峰和波谷,如下图所示,如果算法有问题就很有可能会陷入到局部最优解中。通过观察曲线我们可以大概得出曲线的最小值约为-7,大约在x=-1.57处取到。

a995862232c5a4e0ddd3ded8334fc143.png
图1. 函数曲线图

下面我们就开始编写MATLAB代码,遗传算法的简易流程图如下:

bb17af94365db16fd4d1aeb5152a831f.png
图2. 遗传算法流程图

首先我们要进行编码操作,我们这里选择的是最常用的二进制编码。使用二进制编码时,需要确定编码长度,一般叫染色体长度chrom_length,它的取值与求解精度和自变量的取值范围有关,我们现在的计算精度eps=0.01,自变量取值范围为range=2*pi,这就需要我们一个二进制数所能表示的个数至少要大于range/eps个,即2^chromlength-1>range/eps,所以chrom_length>log2(range/eps+1)=9.299,而chrom_length是正整数,所以这里要取10。

clear

在计算每个个体的适应度之前,我们需要对种群解码,即将二进制变为十进制,这段代码我们放在单独的function文件中。

function

接下来我们要计算每个个体的适应度,一般来说我们可以直接在目标函数的基础上略加修改就可以得到适应度函数的表达式。需要注意的是,在选择过程中我们会用到某个个体的适应度占所有个体适应度之和的比例,所以我们在构造适应度函数时会保证适应度是一个非负实数。本例中适应度函数的构建方法可直接看下面的代码。

function

主函数部分:(这里我们先忽略迭代循环的代码,只关注这一次的代码,最后再在汇总代码中加上for循环)

%% 计算每个个体的适应度

本案例中我没有设置算法收敛准则,算法达到最大迭代次数后就会停止,所以接下来直接进行选择过程。选择的原则就是让适应度高的个体被选中的概率更高,但同时又不会完全剥夺适应度低的个体被选中的可能性,这里我采用的是轮盘赌选择法,即把每个个体的适应度( fitness_value(i) )占所有个体的适应度之和( sum_fitness )的比例p_fitness作为该个体被选中的概率。这里有一点点不好理解,我在这里卡了很久才理解清楚,我举一个简单的例子来说明一下这个计算过程。假设种群中有4个个体,每个个体对应的适应度分别为1,2,3,4。那么sum_fitness=10,每个个体的p_fitness就分别为0.1,0.2,0.3,0.4。接下来就是选择算法的重点,就是我们怎么样才能让每个个体被选中的概率也正好是0.1,0.2,0.3,0.4呢?这里我们可以给出介于0和1之间的一个随机数r,然后把[0,1)区间分成4份,占比分别对应p_fitness,那么这4份分别是[0, 0.1),[0.1, 0.3),[0.3, 0.6),[0.6, 1),只要判断下r落在哪个区间内,我们就选择相应区间对应的个体即可。选择算子的具体代码如下:

function

选择出优秀的父代和母代之后,接下来就要让父代和母代交换基因,首先我们生成一个介于0和1之间的一个随机数r,当r<pc时,随机生成基因交叉点cpoint,将父代的cpoint之前的基因和母代cpoint之后的基因相结合,作为下一代的基因。交叉算子的具体代码如下:

function

子代生成之后,子代会在一定的概率下发生变异,一般变异概率都比较小。首先我们生成一个介于0和1之间的一个随机数r,当r<pm时,将该点的基因由'0'变为'1'或'1'变为'0'。变异算子的具体代码如下:

function

最后找到最优解并输出即可,由于前面的选择,交叉和变异过程只给了每一块的代码,这里我再把主函数代码汇总给出,如下:

clear

最终运行结果如下:

str 

需要说明的是,前面的遗传算法并不能保证每次求出的最优解都是全局最优解,有时候也会陷入局部最优解,这也是我后面要学习和努力的方向。

那么这次的分享就结束了,接下来的一两周我会去学习一些在遗传算法的基础上修改的改进算法,到时候再分享出来。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值