关于遗传算法的优化(一二三)
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 深度学习+数据流监控会擦出什么火花呢?
以上是关于关于遗传算法的优化(一二三)的主要内容,如果未能解决你的问题,请参考以下文章