布谷鸟是比较新的启发式最优化算法,但其与传统的遗传算法,退火算法等相比,被证明收敛速度更快,计算效率更高!
本文诞生的缘由
由于布谷鸟算法比较新,所以国内外的网上对于该算法的介绍都比较少,虽然算法整体的思想看起来简单,但真正落实到实践时往往发现有些细节还是不甚清楚。令人尴尬的是,我搜索了国内外对于布谷鸟算法的教程,这些教程恰恰点到算法思想上就止住了,并且给出的代码千篇一律地还是Xin-She Yang(布谷鸟算法提出者之一)给出的matlab代码1,对初学者很不友好,于是我就打算写一篇教程,通过详细地举一个例子来带大家入门布谷鸟算法,并且我写了份python代码(可直接运行),需要者可在下面的github链接中自取。
布谷鸟算法思想简介
布谷鸟算法的启发当然来自于布谷鸟,因为布谷鸟这种鸟很有意思,生出来的孩子自己不养,直接被扔到其他鸟的鸟巢中去了,但有时候,这些布谷鸟蛋会被被寄宿的那些鸟妈妈发现,然后就被抛弃,有时候,这些宿主会直接放弃整个鸟巢寻找新住处。然而道高一尺魔高一丈,有些品种的布谷鸟生下来的布谷鸟蛋的颜色能和去寄宿的鸟的鸟蛋颜色很相似,并且布谷鸟的破壳时间往往比那些宿主的鸟蛋早,这样,一旦小布谷鸟破壳,它就会将一些鸟蛋扔出鸟巢去以求获得更多的食物,并且,小布谷鸟能模拟宿主鸟孩子的叫声来骗取更多的食物!简单来说,就是如何更高效地去骗吃骗喝。
![](https://img.xiehestudio.com/2019/10/30/a89e8ef1165cb.png)
这时,心急的朋友可能会问,这和最优化有啥蛋关系呢?如果光让我看到这种自然现象我也很难和最优化联系起来,但有些细心的人做到了。我们现在来简单概括一下他们是咋联系起来的。
- 他们假设最初在可行域内随机生成一组点(布谷鸟)
- 计算这些点的适应值(鸟的健康程度),并记录下最健康鸟的位置及其适应值
- 然后通过某种方式更新这些点的位置(布谷鸟找其他鸟的鸟巢下蛋)
- 这些寄宿到其他鸟的布谷鸟蛋有一定几率被抛弃,这时布谷鸟需要找新的位置来下新的布谷鸟蛋,没被发现的布谷鸟蛋就保持原样(也就是保持每次迭代的点的总数不变)
- 这些布谷鸟蛋成功被孵化然后长大,原有的布谷鸟则会死去,现在评估新的这些点的适应值(新长大的布谷鸟的健康程度),若比原有记录下最好适应值要好则更新最好适应值
- 新的这批布谷鸟从第3步继续迭代,直至满足迭代次数或精度要求
一头雾水?别怕,后面一个例子就懂了!
更新位置的方式
细心的朋友在看上面算法步骤时可能会问,以某种方式更新位置,是啥子方式呢?更新位置的算法同样很重要,它也会关系到最后算法的收敛速度,在上述的算法步骤中,我们在第3步和第4步都需要更新点的位置,现在就来解答这个问题。其实这些更新点的方式说的直白些其实很简单,就是让这些点乱走,当然它有个洋气的名字(random walk),乱走的方式也很简单粗暴,随机生成一个方向和长度,叠加到原有点上就成了新的点,但是需要指出的是,这个随机生成的方向和长度都是有讲究的,有研究发现通过莱维飞行(Levy Flight)的方式能比较有效地去寻找全局最优解而不至于陷入局部最优解中,并且它和布谷鸟算法配合达到了相当不错的效果,接下来就是解答什么是莱维飞行了。
莱维飞行
在介绍莱维飞行相关公式之前,我们先来简单说一下它背后的思想,莱维飞行是由较长时间的短步长和较短时间的长步长组成,说起来很拗口,我们先来看一下它的演示图吧:
![](https://img.xiehestudio.com/2019/10/30/fd96edc62080d.gif)
从上面的动画中我们可以看到,点大多数时间都只有小距离移动,偶尔会有大距离移动的情况。这和自然界中大多数动物觅食方式方式类似,也就是找到一块区域后细致的查找猎物,如果没找到,就换一片区域找。
那么,该如何实现这种移动方式呢?我们现在假设我们就是捕食者,需要捕猎去了,但尚不清楚猎物在哪,那好,我们先随机选个方向(服从均匀分布,因为在不知道任何信息前提下,对于我们来说各个方向存在猎物的可能性相等),接下来就得确定要走多远了,根据上面的思想,Levy分布要求大概率落在值比较小的地方,而小概率落在值比较大的地方,Mantegna就提出了近似满足这种分布的计算公式(levy分布很难满足,有兴趣的小伙伴可以查阅相关资料):
s = u ∣ v ∣ 1 β s=\frac{u}{\left | v \right |^{\frac{1}{\beta }}} s=∣v∣β1u
(说明:u服从 N ( 0 , σ u ) N(0,\sigma _{u}) N(0,σu)正态分布,v服从 N ( 0 , σ v ) N(0,\sigma _{v}) N(0,σv)正态分布,而 σ u = { Γ ( 1 + β ) sin ( π β 2 ) Γ [ ( 1 + β ) 2 β ⋅ 2 ( β − 1 ) 2 ] } 1 β \sigma _{u} = \left \{ \frac{\Gamma (1+\beta )\sin (\frac{\pi\beta }{2})}{\Gamma \left [ \frac{(1+\beta )}{2}\beta \cdot2^{\frac{(\beta -1)}{2}} \right ]}\right \}^{\frac{1}{\beta }} σu=⎩⎨⎧