当时给小姐姐讲的故事是这样的:

遗传算法基于达尔文的进化论,模拟“物竞天择,适者生存”的自然法则,通过若干代的遗传、交叉、变异、复制,得到最优解。本文将借助一个很直观的例子,给大家介绍遗传算法。

问题假设

在大草原上,有一个物种,为了生存下去,它们必须跑得比其它同类快,否则就会被天敌吃掉(被淘汰)。这个物种由三种元素组成:



并行遗传算法 多目标多约束整数规划 Python代码_遗传算法

•腿:即上图中的node,颜色越深,表示它和地面的摩擦力越大。•肌肉:用于连接任意两只腿,颜色越深,表示力量越大。•时钟:即右上角画的表的样子,它可以用来控制肌肉收缩时长和舒张时长。

肌肉的收缩舒张带动了腿的运动。每个物种可以有多条腿,腿的大小、肌肉的长短和力量、以及肌肉收缩舒张所用时长,都会影响到它跑动的快慢。

目标

“我们的目标是!” “没有蛀牙~~”。啊呸!我们的目标是,随着繁衍、竞争和淘汰,让这个种族的奔跑速度越来越快。

物种诞生

第一批生物,也就是这个种族的父辈们是怎么产生的呢?因为没有经历过筛选淘汰,我们也不知道什么样的腿和肌肉的组合会产生跑得最快的个体,因此可以随机初始化一些个体出来。这里随机初始化了1000个。



并行遗传算法 多目标多约束整数规划 Python代码_迭代_02

这些父辈中,有的个体只有三条腿,有的个体甚至达到了8条腿,肌肉的组合样式也不一样。我们先来看一下这些随便组合的个体的跑得快不快。

并行遗传算法 多目标多约束整数规划 Python代码_遗传算法_03

这里我们从视频中截取了一张图片,这个个体憋憋嘟嘟的,费了半天劲,差不多用了15秒前进了1米。这个还算好的了,有的个体只会原地摩擦,更有甚者,不前进也就算了,直接给你往回跑。

适者生存

落后就要被吃。我们对这1000个副本进行一轮筛选,根据它们在15秒内的前进距离进行淘汰。淘汰规则为,跑得越快越容易生存下来,跑得越慢,被淘汰的几率越高。这里有个有趣的细节需要讲一下,这里的淘汰讲的是根据几率而不是完全根据它们跑动的距离。也就是说,跑的慢的物种也有可能继续生存下来,而有些跑得快的个体竟然有可能被淘汰。这种现象在自然界里其实也很常见。毕竟跑得快的动物,如果新陈代谢功能配置不合理,有可能消耗过高的能量而不适合生存,某些跑得慢的动物,由于不怎么消耗能量,反而被大自然保留了下来(参考考拉)。第一代被kill掉一半(被黑色涂掉),剩下的一半有幸继续传播祖传染色体。



并行遗传算法 多目标多约束整数规划 Python代码_遗传算法_04

XXX产生后代

自然界有性繁殖的优势在于,可以组合不同个体的染色体。研究表明,父母双方的染色体差异越大,产出优秀后代的可能性更高(反例则是近亲结婚)。所以小伙伴们,远嫁远娶未必是坏事哦。在这个例子里,交叉可以继承父辈双方各一半的染色体进行组合,就有可能产生更加优秀的后代,例如父亲肌肉力量大,母亲腿长(当然腿长力量大不一定跑得快)。

变异

变异才是生物进化的原动力。在学习高中生物之前,我一直认为变异是个贬义词。但其实变异有好有坏(虽然绝大多数是坏)。如果某个个体的某个基因发生突变,从而让其拥有了超越同类的能力,那么这个基因就有很大概率继续传播下去,从而使得整个群体发生进化。同样的,我们在遗传算法中也使其有一定概率发生变异。在这个例子中,例如父亲三条腿,母亲五条腿,如果不发生变异,后代要么三条腿,要么五条腿,基因突变的话,后代有可能会产生四条腿(变成马了!)。

传宗接代--繁衍

姚明和叶莉的后代很大概率要比正常同龄人高;两个普通的凡人,也有可能生出高智商的孩子。这就是遗传的魅力。遗传算法通过父辈的交合以及一定概率的变异,产生后代,这些后代都或多或少保留了父辈的基因,也存在着一些新的基因,等待自然的选择。同样的,使用相同的标准,在15秒内根据其前进的距离进行优胜劣汰。

迭代

整个过程模拟了自然界的基本特性:生存和繁衍。要想活下去,就得跑得快,跑得快,才有资格传出自己的祖传染色体。经过n轮的淘汰和筛选,从宏观上,我们看到的是个体的选择,其本质是基因的选择。因为每一代我们都会杀掉一半跑得慢的个体,这样,那些造成个体跑得慢的基因以及基因组合就会被人为咔嚓掉。

并行遗传算法 多目标多约束整数规划 Python代码_机器学习_05

•到第10代的时候,最快的个体已经可以15秒跑3米左右。•到了第30代,跑得最快的个体已经可以15秒跑6米,且整个群体的平均水平也接近3米,整个群体都在进化。



并行遗传算法 多目标多约束整数规划 Python代码_迭代_06

•上图展示的是随着迭代轮数,最快个体的成绩(最上面的黑线)和中位数个体的成绩(红线)。到了65代左右,最快的个体是一条4条腿的家伙(真的和生物界类似了?),整个群体中,4条腿的最多,其它数目腿的个体都逐步被淘汰掉了。•到了300代的时候,整个群体的进步程度变得非常缓慢,可以停止迭代了。

机器学习上的运用

那么遗传算法怎么用到我们的机器学习上呢?我们构造的每一个特征其实都是一个基因,我们需要对这些基因进行组合、保留、淘汰、突变,当模型的最终指标不再变化时,我们就认为模型已经进化到了一个最高的水平。这里我们为大家介绍一个python的开源工具包tpot,它是一个自动机器学习的工具包,里面也整合了遗传算法。

from tpot import TPOTRegressorX_train, X_test, y_train, y_test = train_test_split(tpot_train, target, train_size= 0.75, test_size= 0.25)tpot = TPOTRegressor(generations= 5, population_size= 50, verbosity= 2)tpot.fit(X_train, y_train)print(tpot.score(X_test, y_test))tpot_pred = tpot.predict(tpot_test)tpot.export( 'tpot_boston_pipeline.py')

tpot_train就是我们构造的初始特征,在TPOTRegressor方法中,generations是种群迭代轮数,即繁衍多少代,population_size表示的是种群数,即表示有多少个个体。随着繁衍轮数或者种群规模的增大,模型运行时间也会极度变大。小编尝试了一下,迭代个10轮差不多要10个小时(和初始特征数也有关)。从结果来看,遗传算法基本可以达到我的水平上限。毕竟机器学习最重要的是特征,特征决定了模型的上限,遗传算法可以尽可能的触摸到这个上限。

总结

遗传算法的思想十分有趣,且十分有效,遗传算法已被人们广泛地应用于组合优化、机器学习、信号处理、自适应控制和人工生命等领域。然而从实际操作来看,在机器学习中时间消耗太大,用Lgb模型10分钟跑完,我们就可以继续构造特征验证想法,而遗传算法可能需要让你等上一天。但不得不说,这个算法的思想很值得我们去学习和思考。