关于遗传算法的优化(一二三)

Posted 'or 1 or 不正经の泡泡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于遗传算法的优化(一二三)相关的知识,希望对你有一定的参考价值。


theme: channing-cyan
highlight: androidstudio

文章目录

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

前言

今天是大年初三,是时候回归主题了,那么今天也是简单地说一说关于GA算法的优化,以及当前比较厉害的地方。不得不说我先前对于python领域的探索真的是太片面了,高中玩到大学玩了两三年愣是把自己圈在了curd,爬虫,安全的领域没出来。尽管正真落地使用是C++ or Java or Other Static language or other business scenario deployment languages。

今天也是做一个小的说明,不涉及代码。

“父辈优化”

我们先前介绍了我们的遗传算法。最简单的模型结构,但是这些个地方其实都是有很多优化的点的。首先就是我们对于后代选择变异的这一个部分。

其实在这一步只是简单地去直接把孩子去代替父辈,这里说过,交叉和变异可能会出现不好的地方,不一定是往好的地方去发展,例如两高智商父母生出“傻孩子”。所以我们其实还需要对其进行简单的筛选过滤。如果我们发现新生成的个体不如父辈那么显然我们不需要替换。

那么在我们的代码里面(在前面的例子里面就是可以先计算一下适应值,然后确定是否替换)

def CrossOver(Parent,PopSpace):
    '''
    交叉DNA,我们直接在种群里面选择一个交配
    然后就生出孩子了
    :param parent:
    :param PopSpace:
    :return:
    '''
    if(np.random.rand()) < Cross_Rate:

        cross_place = np.random.randint(0, 2, size=Dna_Size).astype(np.bool)
        cross_one = np.random.randint(0, Population_Size, size=1) #选择一位男/女士交配
        Parent[cross_place] = PopSpace[cross_one,cross_place]
        '''
            设置临时变量存储 
            kid = Parent.copy()
            kid = PopSpace[cross_one,cross_place]
            之后翻译 Kid 与 Parent 计算适应值
            对比之后确定是否代替
        '''
    return Parent

具体代码我就不写了,很简单,而且篇幅有限。

同样地在我们的变异里面也能这样做,这样就能确保总体往好的方向跑,避免出现“孬种”,当然这只是其中一种思路,实际上如果出现不合格的后代,我们也可以选择让父辈再生几个然后看看,直到生出比父辈好的后代,至于时间空间复杂度这个看着办吧…

那么这个也是一个算法的思路微生物遗传算法

维度问题

我们当前的算法是先使用二进制编码来表示一个变量X,但如果我们是一个高维度优化怎么办,也将一个变量划分为一个DNA使用二进制表示,每一组(如干个因变量组成)为一组?这样如果使用二进制编码的话首先在转码的过程当中就会消耗算力,同时,由于是使用二进制编码然后压缩范围在一定程度上会有精度损失。

例如我们现在有这么一个优化

这个是我当初简单地把一个三层神经网络给“拿了出来” 然后做的优化。

这个时候还是用二进制编码显然就不太被合适了,那么作为一组DNA的表示形式应该就是这样的
[X1,X2,X3,X4,X…]

那么问题来了,同样我们也需要交叉变异,交叉好办,和先前一样,那么如何变异?

变异优化

这个时候我们首先要思考一个问题,先前我们为什么要把一个十进制的数字变成二进制?
显然对于一个二进制而言,直接进行变异的话,只需要把0 变成 1 反之即可。那么对于一个十进制的数字怎么变异?那么这里就涉及到一些数学方面的内容,我们利用正态分布来生成这样的一些数字。

这样一来为了实现这个过程,我们DNA需要携带两个内容,一个是我们的数字,还有一个是我们的方差,我们把数字当中均值,这样构造一个正态分布,生成一个数据。同时携带的方差信息也可以进行交叉变异操作,从而实现物种变异多样性

那么同样这个叫做:evolutionary algorithms*** 也就是EA*

时间复杂度优化

接下来我们发现我们在做这类运算的时候,我们往往进行了大量的迭代运算,因为我们的种群数量嘛,但是我们其实可以发现在足够量的计算的前提之下,通过每一代的优化,净化,最终可以发现这些点最后应该在某一个小区域内移动,或者直接在一个点上。所以这里发现其实在某些情况下我们更本不需要使用那么多的个体,事实上我们可能只需要一个个体即可。

我们通过一个个体去生成孩子,然后进入循环,之后孩子变成父辈再生成子代。这样就实现了我们的一个操作,同样地这样操作之后,显然我们不能像先前那样去交叉,变异。

此时我们只有一个个体了。

新的优化

这个时候我们不太需要去变化,实际上我们只需要去在原来的基础上面加减一些数字,让这个点去不断地跳跃即可。

这个是 莫范python给出的一个代码的截图。我们直接这样操作即可,同样这个算法叫做
ES 也就是进化策略

进化策略

关于这个玩意,我们只需要关注一个东西

那就是如何净化,看前面的代码截图,有个东西MUT_SURENGTH
就是这个东西,我们如何定义,这里有个公式,也是ES 的提出者提出的,· 1/5的成功法则 (1/5 successful rule)

然后在代码里面是这样的。

直接进入循环完成~

梯度下降优化

这里面使用的很多资料参考莫烦python,感兴趣的朋友可以去看看,后期我会自行实现,并对其代码进行升级等等(主要是后面作为pytorch党,我得去把TensorFlow党的内容翻译翻译)

这个可能又需要一点关于神经网络或者pytorch TensorFlow的一些基础了,当然在我们这里的优化原理很简单。就是使用梯度去干预净化,让净化往更好的方向进行净化,优胜劣汰
这个原则去进行筛选的,其中的变异,交叉的方向我们是无法控制的,那么引入梯度,我们就可以在一定程度上改变 X 的值,从而对X交叉,变异的方向进行适当控制。

这里我们主要是在原来的基础上,定义 损失函数,使用优化器。这个由于那边给的是TensorFlow的代码,我需要翻译翻译使用pytorch重写。但是原理对于有基础的朋友来说,真的很简单。

同样的,在这里我们也可以使用进化算法优化我们的神经网络。
神经网络的本质其实就是优化每一个连接层,激活函数的一些参数的偏置和参数权重优化。使用梯度下降让损失函数最小,所以我们把损失函数想象成待优化函数会是什么效果?由于我们的进化算法或者说GA的全局性很好,所以可以避免局部最优的问题,在机器学习里面,强化学习里面文章很大。研究研究搞不好本科毕业论文有着落了~至于毕设,那简单分布式往死里怼,或者也是围绕CNN or NLP 做个好玩的东西出来 or 深度学习+数据流监控会擦出什么火花呢?

以上是关于关于遗传算法的优化(一二三)的主要内容,如果未能解决你的问题,请参考以下文章

遗传算法的运算过程

遗传算法能否解决同时包含整数约束和等式约束的优化问题?

差分进化算法优化集成参数

遗传算法之函数优化

数学建模系列:遗传算法

matlab simulink 遗传算法优化模糊pid参数