0.学习路径示意图
1.前言
Hello,各位小伙伴们,大家早上好呀,又是一个阳光洒满大地,朝气蓬勃的日子。不知道小伙伴们是否还记得博主上周介绍过的知识点,不记得也没关系,这里博主还是一如既往地给大家附上上期的链接。上期博主介绍了优化器(optimizer)的原理及使用,不可否认的是,即便是集动量(mv)与自适应学习率(adaptive learning rate)于一身的Adam优化器,也有可能在训练的过程中陷入局部最小值的旋涡,最终葬身于此。这期,博主来给大家讲个新东西----遗传算法,为的就是优雅地跳出局部最小值,得到最优解。
阿力阿哩哩,公众号:Python机器学习体系
相信各位小伙伴对遗传这个词已经不陌生了,我们人类文明发展至今离不开遗传与进化。不知道大家有没有一种感觉,现在的初中生已经比我们这群大学生高了,往宏观里想就是下一代已经比我们这一代在身高上已经优化了。博主还在混迹于各大黑网吧的初中年代,在广东是很少能见到有180+的小伙子浪荡于街头的,现在随便一个穿校服的小孩子均高都在180+。博主每次坐地铁都深感惭愧,但同时也感叹生命的力量,遗传让每一个弱小的生物在代际循环中获得了优化的力量,表现出越来越适应生存环境的能力,因为不适应环境的生命早在迭代的过程中逐渐消亡。为此,博主也验证了穷不过三代是对的,因为穷小子在第三代就找不到老婆了TAT。不过大家也不用妄自菲薄,每个小伙伴能来到这个世界上,说明大家的父辈的父辈的父辈们至少是个大户人家。
显然,博主能注意的小现象,很多年前肯定也有小伙伴会注意到,为此有些厉害的小伙伴就将遗传搬进了计算机,让计算机模仿遗传,赋予程序优化的力量。
好了,讲到这,博主现在就给小伙伴们讲一下遗传算法与上一期介绍的优化器(optimizer)有啥不一样。和我们之前所说的优化器不一样,遗传算法的整体搜索策略和优化搜索方法在计算时不依赖于梯度信息或其它辅助知识,只需要影响搜索方向的目标函数(Target Function)和相应的适应度函数(Fitness Function),所以遗传算法提供了一种求解复杂系统问题的通用框架,它不依赖于问题的具体领域,对问题的种类有很强的稳定性,所以广泛应用于许多科学。
翻译成人话就是遗传算法能够解决很多问题,机器学习只是一个方向,小伙伴们只要有想法,随时随地都能将遗传用在别的问题上,比如路径规划、旅行商(TSP)问题、车间设施布局优化问题。
博主这里选路径规划这个例子为切入点,给小伙伴们介绍一下遗传算法的精髓,到时候碰到某些场景就可以思考下怎么把它用起来。
1.原理
按照惯例,先给大家看看遗传算法的流程图。整个算法就分以下几步,下面的介绍可能会勾起小伙伴们当年学生物的回忆,因为博主的配图都是生物书本上的,嘻嘻。
交叉:可以理解为两个染色体交换一下基因片段,映射到人类的话,就是生宝宝。
变异:可以理解为染色体的一个片段以某种概率发生了突变,映射到人类的话,就是人类突然变成了绿巨人。
评价:评价函数可以理解为大自然,对我们程序优化有个指导作用。大自然会通过优胜劣汰的规则将弱者淘汰,评价函数同样的会将适应度低的种群个体给杀掉,保留强者。
所以,整个流程可以理解为有一个种群,他们不断地生小孩(交叉与变异),适应环境(评价函数)的小孩和大人会被保留,不适应的环境的大人和小孩会被杀掉,通过不断地迭代,最终得到的种群个体都是最适应环境的。
好了,小伙伴们已经了解整个算法流程了,这时候我们再往细里看。
生小孩也是要有规则的,那么怎么才能生出最强的宝宝,最好这个宝宝一生出来就是我们想要的爱因斯坦。
这里博主自己制定了一个生宝宝(每次生两个)规则,生宝宝规则小伙伴们也可以灵活设定,每个人都有自己的想法,博主只是觉得这种设置比较科学。
伪代码如下:
博主这里讲一下为什么会有交叉率和变异率,我们都用到了遗传算法了,当然一些参数也要和大自然相关。
变异率好理解,一个人要变成绿巨人是需要一定概率的,而且这个概率非常的小,所以在程序中小伙伴们要设置的小一点。
交叉率就是两个染色体交换片段的概率,小伙伴们可以理解为这两个染色体能交叉是因为喜欢对方,不交叉就是不喜欢对方。这个交叉率大家可以按照自己喜欢的来,怎么开心怎么设置。
可能还有些小伙伴会疑惑爬山算法,这是个小算法,大家可以把它理解为多次变异,每次变异概率都为100%,在设定次数的变异中,生成最优的宝宝,不过我们得到的一般都是局部最优,不过也算是比之前强了嘛。
3.代码实践
好了,讲到这,用一个实际的例子代入,小伙伴们会有更加深刻的理解。这里博主挑选了物流路径规划这个问题来给大家讲解。我们先看一下问题吧。
好了,要想对上面这个问题使用遗传算法,得确定4件事,因为下面这4件事必须得根据问题的本身进行设定。
1.个体基因和种群规模:
1.1因为是给23个客户送货,这里就可以设置每个客户就是一个基因,所以一个个体就有用23个基因,就是一条完整配送线路。
2.2种群规模小伙伴们可以自行设置,这里博主将它设置为20,也就是一开始就生成20个线路(个体)组成的种群。
2.交叉操作
交叉操作是根据个体基因来确定,不一样的基因,交叉操作手法也会有些许不一样,也就是说,小伙伴们在使用遗传算法的时候,交叉操作得自己构造,不过交叉的核心并没有改变,只是基因不一样,约束条件可能会有些许不同。
3.变异操作
变异操作也是一样的,不一样的基因,变异操作也不一样。
4.适应度函数
博主在伪代码中只是对适应度函数一带而过,主要原因还是这个函数必须是根据问题来设定的。比如现在我们的问题目标是让总路程distance最小,那么适应度函数就可以设定为
这样,总路程越短,我们的适应度也就越高,到这里我们就完成整个遗传算法的设定了。
接着,博主针对这个问题给小伙伴们来一份伪代码:
好了,讲了这么多,这时候是见证下遗传算法魔力的时刻了。这里博主给大家附上一个总路程随着迭代次数增多而变化的折线图。博主的迭代间隔(每次增加2000)选得比较大,所以画出的折线图会比较“尖”,耐心的小伙伴可以将迭代间隔缩小,得到的效果图会好很多。小伙伴们可以从结果图上看到,总路程的大小在震荡区间在(325, 335)之间,说明遗传算法已经无限接近最优值了,倘若我们的算力足够,是可以无穷逼近这个值的。
这也就是博主在前文所说的,遗传算法能够跳出局部最优,无限逼近全局最优值,不像之前我们所说的优化器(optimizer)一样,利用梯度寻找全局最优,对于非凸函数很容易陷入局部最优从而导致过早收敛。
Git代码
https://github.com/ChileWang0228/python_tutorial/blob/master/GA_hou_lian_pi.py
代码讲解小视频:
视频卡顿?bilibili值得拥有~(っ•̀ω•́)っ✎⁾⁾ 我爱学习
4.邂逅--神经网络与遗传
博主之前有提及,现在已经有一些厉害的小伙伴已经将遗传算法与进化策略融入了神经网络来获得更好的效果。博主的一位小伙伴曾经提及了这么一句话,对于一个问题,要么用老办法将它做到极致,要么换另一种方法在另一方面得以提升。是的,遗传和进化就是另一种方法。
这位小伙伴,已经将进化策略融入了CNN模型,并实现了程序自组网络,得到训练效果已经比我们人工组多层网络训练的效果要好了,训练时间也更短。这一方面的突破不仅在于省去了人工组网的过程,而且还缩短了训练时间,最后得到的效果还比原来的老办法(组多层网络)暴力蛮算来得好。
算法原理也仅仅用到了变异,在这里我们先确定前文所说的遗传算法的4大步骤。
这里给小伙伴们来个实验结果(左为人工自组网,右为进化+CNN)
看到这个结果,小伙伴是不是有点小惊讶?没想到遗传算法就单是一个小小的变异却能得到如此好的效果,那加上交叉呢?小伙伴们可以利用这节所学的知识,充分打开你的脑洞了。
5.总结
结尾来个点题吧,小伙伴们在这一节学会了遗传算法4个关键步骤,这当然是一个满心欢喜的结果。不过博主分享这篇文章的目的远不止于此,长期的神经网络学习让大家都太过依赖梯度下降这个工具了,导致我们无法跳出自身的思维局限,这次遗传算法的教程的撰写就是想让小伙伴们有一次思维的冲击,可以让大家多想想跨界知识能否引入自己的专业领域,多领域结合可能会得到不一样的收获。
最后,希望各位小伙伴们能在这期教程中学有所获。感谢大家的一直以来的关注与支持。
网友评论