首页 >> 数学 >> 生物 >> 计算机科学 >> 文章

100个透明三角形拼成的Firefox

这是个真实的故事。

从前在海岸边有一群扇贝在悠哉游哉地生活繁衍着。它们自然是衣食不愁,连房子也有了着落。它们担忧的只有一件事:每隔一段时间,总有一个人来挖走它们之中的一部分。当然啦,挖回去干什么这大家都知道。但扇贝们不知道的是,这人的家族图腾是Firefox的图标,所以他总是选择那些贝壳花纹长得比较不像Firefox图标的扇贝。

这种状况持续了好几十万代。大家应该也猜到扇贝们身上发生什么事情了:它们的贝壳上都印着很像Firefox图标的图案。

可能有些读者会说:你这不是糊弄我们么,Firefox才有多少年历史,你就搞了个几十万代的扇贝?

确有其事,但是这些扇贝不是真实的,它们在我电脑的内存里边生活。它们是一个遗传算法程序的一部分,这个程序的目的就是用100个半透明三角形把Firefox的图标尽可能像地画出来。

什么是遗传算法呢?

简单地说,遗传算法是一种解决问题的方法。它模拟大自然中种群在选择压力下的演化,从而得到问题的一个近似解。

在二十世纪五十年代,生物学家已经知道基因在自然演化过程中的作用了,而他们也希望能在新出现的计算机上模拟这个过程,用以尝试定量研究基因与进化之间的关系。这就是遗传算法的滥觞。后来,有人将其用于解决优化问题,于是就产生了遗传算法。

那么,具体来说,在计算机里边是怎么模拟进化过程的呢?

我们还是以开头提到的程序为例。

首先,我们知道,生物个体长什么样子很大程度上是由染色体上的基因决定的。同样,如果我们把100个半透明三角形组成的东西看成一个生物个体的话(为了说话方便,称为扇贝吧),我们也可以说它的样子是由这些三角形的具体位置和颜色决定的。所以,我们可以把一个一个的半透明三角形看作是这些扇贝的“基因”。而组成扇贝的这100个基因就组成了每个扇贝个体的“染色体”(chromosome)。

从下面的图可以大约看出来这些基因是怎么决定扇贝的样子的(为了观看方便,我们只画出其中五个三角形):

基因组成的个体

然后,扇贝们除了生活,当然还要繁衍后代。生物界中的繁衍无非就是父母的基因组合产生新的个体,而在这个程序里边我们当然也这么办:选择两个原有的扇贝,然后从这两个扇贝的染色体中随机选取一共100个基因组成新个体的染色体。如图所示:(仍然是将扇贝看成是五个三角形组成的)

为了产生新的基因,使基因的种类更多样化,在组合的时候,新的扇贝的基因有一定的概率发生变异。也就是说,其中的一个透明三角形的位置或者颜色会随机改变,如图(仍然是五个三角形……我偷工减料……):

扇贝基因的变异

其次,为了使扇贝的样子向Firefox图标靠近,我们要给它们加上一点选择压力,就是文章开头故事中提到的那个人的行动:在每一代把最不像Firefox的扇贝淘汰出去,同时也给新的个体留下生存的空间。怎么评价这个扇贝像不像Firefox呢?最直接的方法就是一个一个像素比较,颜色相差得越多就越不像。这个评价的函数叫做“适应函数”,它负责评价一个个体到底有多适应我们的要求。

在淘汰的过程中,为了便于编程,我们通常会在淘汰旧个体和产生新个体的数目上进行适当的调整,使种群的大小保持不变。淘汰的作用就是使适应我们要求的个体存在的时间更长,从而达到选择的目的。

最后,在自然界中,种群的演化是一个无休止的过程,但程序总要停下来给出一个结果。那么,什么时候终止演化输出结果呢?这就要订立一个终止条件,满足这个条件的话程序就输出当前最好的结果并停止。最简单的终止条件就是,如果种群经过了很多代(这里的“很多”是一个需要设定的参数)之后仍然没有显著改变适应性的变异的话,我们就停止并输出结果。我们就用这个终止条件。

好了,现在是万事俱备只欠东风了。定义好基因,写好繁衍、变异、评价适应性、淘汰和终止的代码之后,只需要随机产生一个适当大小的种群,然后让它这样一代代的繁衍、变异和淘汰下去,到最后终止我们就会获得一个惊喜的结果:(这回是完整的了,图片下的数字表示这个扇贝是第几代中最好的)

怎么样?虽说细节上很欠缺,但是也算是不错了。要不,你来试试用100个透明三角形画一个更像的?就是这样的看上去很简单的模拟演化过程也能解决一些我们这些有智慧的人类也感到棘手的问题。

实际上,在生活和生产中,很多时候并不需要得到一个完美的答案;而很多问题如果要得到完美的答案的话,需要很大量的计算。所以,因为遗传算法能在相对较短的时间内给出一个足够好能凑合的答案,它从问世伊始就越来越受到大家的重视,对它的研究也是方兴未艾。当然,它也有缺点,比如说早期的优势基因可能会很快通过交换基因的途径散播到整个种群中,这样有可能导致早熟(premature),也就是说整个种群的基因过早同一化,得不到足够好的结果。这个问题是难以完全避免的。

其实,通过微调参数和繁衍、变异、淘汰、终止的代码,我们有可能得到更有效的算法。遗传算法只是一个框架,里边具体内容可以根据实际问题进行调整,这也是它能在许多问题上派上用场的一个原因。像这样可以适应很多问题的算法还有模拟退火算法、粒子群算法、蚁群算法、禁忌搜索等等,统称为元启发式算法(Meta-heuristic algorithms)。

另外,基于自然演化过程的算法除了在这里说到的遗传算法以外,还有更广泛的群体遗传算法和遗传编程等,它们能解决很多棘手的问题。这也从一个侧面说明,我们不一定需要一个智能才能得到一个构造精巧的系统。

无论如何,如果我们要将遗传算法的发明归功于一个人的话,我会将它归功于达尔文,进化论的奠基人。如果我们不知道自然演化的过程,我们也不可能在电脑中模拟它,更不用说将它应用于实际了。

向达尔文致敬!

100个半透明三角形组成的达尔文肖像

Bonus:如果你看明白了这篇文章,而且你懂英语的话,你自然明白下面这个冷笑话:(来自http://xkcd.com/534/

Just to make sure you don't have it maximize instead of minimize.

Just to make sure you don't have it maximize instead of minimize.

相关文章
  1. 毕业设计涉及到遗传算法,记忆虽不犹新但还是印象深刻。

  2. 文章写得真是深入浅出。

    类似算法说白了就是随机函数逼近,都可以用马尔可夫链来建模。
    不过这些随机算法好像还只能是研究人员的玩具而已,离应用差得还远得很。

    只是神经元网络和模拟退火好像被数学家研究地多一些。

    记得Kanatani曾解释过为何随机优化需要严格的数学分析。

    中国好多大学和研究所都把大好的时间、精力和经费浪费在这些假大空没有实效的研究上,可悲啊。

    • 不能这么说啊,非欧几何刚研究出来有什么用处?相对论刚研究出来能有什么用?搞科学研究,功利性还真不能太强了。

      • 非欧几何可是真正严格的数学。
        可是这些人工智能算法除了一些拍拍脑子灵机一动的“诡计”和耗费计算能力的仿真之外,还有什么呢(Vapunik除外)?

        绝大多数研究结果都是继续的拍脑袋和大量仿真,拿参数来说事,具体的意义啥都没有。

        在最用得到人工智能的计算机视觉上,反倒是这些人工智能算法几乎没有应用价值,讽刺啊。

        • 应用还是有的,这些算是“没有办法的办法”,如果是NP而且只需要近似解的优化问题的话,还是可以一用的。

          • 对FF图标的逼近,应该就是一个伪问题,我想在适应函数里应该用到了该问题的真解,也就是FF图标。

            有没有真的应用例子,也就是适应函数里没有真解的问题呢?

            • 有的,比如说可以应用到TSP问题中。
              而且严格来说这也不算“真解”,因为我们这里要求的是用100个透明三角形拼起来的图案,而Firefox的图标显然不能只用100个透明三角形组成。

  3. 举手,难道说这个“适应函数”在前10代中的筛选能力已经超过人类了?我绝对没有自信在这一堆斑驳的杂色中选出哪个更像火狐。
    另,上次那个火狐星云,也是正在进行这种进化吧。

    • 适应函数是一个一个像素比较得出的~~~所以人类比较难选出来也是很正常的~~~

      火狐星云跟这个不是一回事……

      • 人类输了,T_T。要当好选择压也是一件不容易的事情啊!

        把火狐星云扯到话题中来显然是在开玩笑啊! XD

  4. 好奇妙的描述……
    关于遗传算法的表述,前不久才在山本弘的SF小说《神并不沉默(神は沈黙せず)》中看到,当时很费了点力气才能理解,不过很显然这边的解说更加明晰。

  5. 提到遗传算法,应该提到John Holland,他是遗传算法的发现者。

  6. 太有意思了。我一直梦想将来能设计一个模拟接近真实社会的经济模型,这个还挺有启发性的

  7. Pingback: 阳阳猪的del.icio.us » Blog Archive » links for 2009-03-03

  8. 好看!小鹿同学你的那个适应函数想必会很难搞。。。
    笑话很强大,不过还需知道skynet是啥。哈哈哈

  9. 今天在和同学讨论的遗传算法的时候发现,最难的就是评价函数的选取,通常来说我们有很多问题都是得不到评价函数的。还有一个问题就是遗传算法对于离散程度很高的问题是否有办法,例如魔方,数独,九宫格,积木方块等智力难题似乎就不适合了。

    • 我觉得这些问题都不怎么适合用遗传算法~~~因为要改造成优化问题的话比较麻烦~~~
      魔方可以用A*,数独可以用Dancing Link,另外两个智力难题不知道是啥……

  10. 相当有趣,不过那个笑话到底啥意思还是不是很清楚,让那个SKYNET演化N代。。。那是什么?

  11. 达尔文的理论缺陷很大,很难解释生物的进化历程,精密的器官不是自然选择可以形成的

    • 但是你看,我简单的代码竟然可以生成如此接近Firefox的图形,那么为什么自然的演化过程就不能生成精密的器官呢?

  12. 这演化的基础是有其明确目的。
    而生物进化有目的吗?
    ……

  13. hi,我想写一个你这个程序。能告诉我怎么把多个半透明颜色混合吗?

    因为我发现,当有多个三角形叠加的时候,在前面的三角形在混合颜色中占的权重比较大。

    另外一点是:你是怎么交换三角形的呢?不能随即交换几个吧,肯定会越来越乱。是不是交换那些空间位置相近的呢?

    • 我是对于每一个像素取覆盖这些像素的三角形颜色的平均值的~~~
      对于三角形的交换的确是完全随机的~~~

  14. 真实世界进化是完全依赖外界刺激反馈的。与这个例子中的简单实现当然有不同,但原理还是相通的。如果在适应性判断写成对外界刺激的反馈,还是可以无目的进化的。说是无目的,其实生存就是目的,在算法里会有大量的危险因素,得以生存或者说生存得好的,就是最优的。可反过来说,描述外界的刺激总是受认知局限性的限制而无法全面描述的。
    个人认为目前这个算法对于确定范围内的进化还是非常有效的。

  15. 很喜欢这篇文章,请允许我先转到空间了,如果不便请告知,我即时删除,谢谢!

  16. 不错不错,这样子讲非常通俗易懂呀~~~前几天算法课上还有同学讲遗传算法呢,都没太听懂~

  17. 自然果然能够用简单的方法构造复杂的精细结构,呵呵,受教了,想起一句话,好的制度能把坏人变好了,坏的制度能把好人变坏人

  18. 如果我没理解错的话,那个笑话是说这个算法永远不可能变成天网,因为每次计算都取最小值,而最小的是重算一次,这个算法将会无限进行下去,一直不停的重算。更深入一点的说,这个笑话是想说人工智能不会变成天网,因为变成天网需要的花费太大了,没有足够的动力的话一个算法是不会变成天网的。

  19. 好文章,比教科书生动许多。谢谢作者!

  20. 好多人没看懂最后的笑话啊……
    其实是这样,代码里的cost是人为添加的,目的是导引进化方向。那一行的意思是,假如演化出天网,则令其cost为99999999,也即防止它真的出来天网……因为真出来的话就玩完了……鉴于演化算法最后出来结果很不确定,为防万一,一定要加一句(只要别忘了要令代价最小化-_-b)
    PS:P大的图书馆居然把一本遗传算法的书放到了生物架子上……伤心啊……

    • 这个笑话我所理解是:基因算法是优化算法的一种,我们需要知道我们是要找最大点,还是最小点 (包括高维的)。当我们要的是最小化的结果时,你的fitness function给的是针对最大值的优化就惨了。

      换句话说,人类是为了物质为目标的优化,还是针对道德的优化,还是同时优化? :-)

  21. fwjmath您好,我最近也对遗传算法很感兴趣,找了一些资料基本的步骤意义了解了一些,可是我不知道具体怎么实现。看了您的文章觉得写得很好,尤其是您自己写的程序我很感兴趣。如果方便的话您能给我一份程序代码看看么?保证不会用于商业用途。我只是想研究一些。这方面的代码实在不好找。万分感谢,麻烦您了
    我的邮箱是:leslie@iamgod.in

  22. fwjmath您好,我最近也在有关遗传算法的一些研究,觉得您做的那个例子特别有意思,不知道能不能看看您的源代码。谢谢。
    我的邮箱是:buptliuwei@gmail.com

  23. 我想学习一下,可是不知道从哪里入手,能不能发给我你的源码?