1. 萤火虫算法简介
(以下描述,均不是学术用语,仅供大家快乐的阅读)
萤火虫算法(Firefly Algorithm,FA)是一种模仿萤火虫之间信息交流,相互吸引集合,警戒危险。算法的原理简单,但实现过程较为复杂,而且算法的提出时间不长,算法的改进、优化处于初级阶段,国内外相应的应用研究已经有了一定的成果。
萤火虫算法中,每个萤火虫的位置代表了一个待求问题的可行解,而萤火虫的亮度表示该萤火虫位置的适应度,亮度越高的萤火虫个体在解空间内的位置越好。萤火虫个体之间,高亮度的萤火虫会吸引低亮度的萤火虫。在解空间内,每个萤火虫会像着亮度比自己高萤火虫飞行来搜寻更优的位置。亮度越大对其他的萤火虫的吸引度越大。同时,萤火虫之间光的传播介质会吸收光,降低光的亮度,影响光的传播,所以萤火虫之间的吸引度会随着空间距离成反比,即两只萤火虫之间的吸引度会随着这两只萤火虫之间距离的增大而减小
2. 算法流程
这次我们的主角就是它了。(顺便吐槽一下,萤火虫发光原理是荧光素氧化发光,那为什么萤火虫的位置会影响它的亮度呢,难道是不同位置的氧气浓度不一样?假装就是这样吧)。
一句话简述萤火虫算法流程:每只萤火虫都向着看上去比自己更亮的萤火虫飞行。
在D维解空间内每个萤火虫的位置为 。
萤火虫之间的相对吸引度由以下公式(1)
式(1)中为其初始吸引度,即两只萤火虫之间距离为0时的吸引度,r为两只萤火虫之间的距离。
算法运行过程中,每只萤火虫将会朝着所有亮度比自己高的所有萤火虫移动,其移动距离由以下公式(2)计算得出:
其中表示一个比第i个个体亮度更高的萤火虫的位置,r表示第i个萤火虫与第j个萤火虫之间的距离。rand()为一个随机扰动,为扰动的步长因子。一般rand()取值为[-0.5,0.5]范围内的均匀分布或者U(0,1)的标准正态分布a取值为[0,1]之间。
基本流程如下:
(1)初始化,设定萤火虫的种群为N,介质对光的吸收系数为 ,初始步长 a=0.97 ,初始吸引度 ,其中 ,其吸引度公式如(3):
式(3)以保证任何两个萤火虫之间的最小吸引度为0.2,最大的吸引度为1.0。
(2)根据萤火虫的位置计算出每个萤火虫的适应度值,适应度值越优的萤火虫亮度越高。
(3)每个萤火虫将根据式(2)向所有比自己亮度高的萤火虫飞行其中第t代时萤火虫飞行的步长公式如 (4):
式(4)计算出的萤火虫飞行步长将随时间递减。
由于所有个体只会向比自己亮度高的个体飞行,那么群体中亮度最高的个体将不会更新其位置。本文中群体中亮度最大的个体将按照以下公式(5)来更新自己的位置。
(4)计算在萤火虫向所有比自己亮度高的其它个体飞行后所到的新位置的适应度值,若该位置优于飞行之前的位置,则该萤火虫将飞行到新的位置,否则萤火虫将停留在原处。
(5)若算法到达最大迭代次数则将搜索到的最优的萤火虫的位置作为解输出,否则将跳到步骤(2)。
(又想吐槽了,该算法的论文中的描述与实际算法实现相差较大,我的实现是根据作者提供的代码反推得出,若按照原文实现,得到的算法性能极差。该算法作者提出的其他算法亦如此)
3. 实验
实验一:标准萤火虫算法
适应度函数还是
参数 | 值 |
---|---|
问题维度(维度) | 2 |
萤火虫数量(种群数) | 20 |
飞行次数(最大迭代次数) | 50 |
初始吸引度 | 1 |
吸引度范围 | (0.2,1.0) |
介质吸收系数 | 1 |
扰动步长因子 | 0.97 |
扰动方式 | 正态分布 |
取值范围 | (-100,100) |
实验次数 | 10 |
从搜索图像上看,标准萤火虫算法的搜索行为挺不错的,可以看出最亮的个体在自身周围小幅度的搜索,而其他个体则几乎是围绕着最优个体搜索的同时也在慢慢向其靠近。我们先看看实验的结果。
值 | |
---|---|
最优值 | 0.008157162631779914 |
最差值 | 3.1035842131176095 |
平均值 | 0.35455247525429945 |
从结果中我们可以看出,上面看似良好的搜索行为得出的结果却不是很稳定,一个最差值拉低了整个实验的平均值。
为什么会这样呢?
前面我们说过,萤火虫算法的核心行为就是每只萤火虫都向着看上去比自己更亮的萤火虫飞行,这必然会导致群体迅速收敛。群体全都集中于一个位置时,算法的搜索能力会迅速下降且无法跳出局部最优。
如何改变现状呢?
方案1.随机挑选数个个体,选择这些个体中比自己亮的萤火虫作为目标飞行。
方案2.将萤火虫群体分为数个组,每个个体向组内比自己更亮的萤火虫飞行。(当年师兄的创新点)
**实验二**.方案1,随机挑选10个个体
参数 | 值 |
---|---|
问题维度(维度) | 2 |
萤火虫数量(种群数) | 20 |
飞行次数(最大迭代次数) | 50 |
初始吸引度 | 1 |
吸引度范围 | (0.2,1.0) |
(介质吸收系数) | 1 |
扰动步长因子 | 0.97 |
扰动方式 | 正态分布 |
目标个体 | 10 |
取值范围 | (-100,100) |
实验次数 | 10 |
看图像好像与标准萤火虫算法的结果没有什么别,看看实验结果。
值 | |
---|---|
最优值 | 2.4611221154186236E-4 |
最差值 | 0.6282110775105908 |
平均值 | 0.13701600336856032 |
可以看出方案1的结果比标准萤火虫算法更好,不过仍在误差范围内(有可能是这几次运气好使结果较好),但是算法的稳定性提升了不少。
实验三.方案2,将萤火虫随机分组,组数为,其中N为萤火虫总数
参数 | 值 |
---|---|
问题维度(维度) | 2 |
萤火虫数量(种群数) | 20 |
飞行次数(最大迭代次数) | 50 |
初始吸引度 | 1 |
吸引度范围 | (0.2,1.0) |
(介质吸收系数) | 1 |
扰动步长因子 | 0.97 |
扰动方式 | 正态分布 |
分组数 | 4 |
取值范围 | (-100,100) |
实验次数 | 10 |
图像依然没有太大的变化。
值 | |
---|---|
最优值 | 0.009197087309433645 |
最差值 | 0.6407287765162609 |
平均值 | 0.09772547993102201 |
与方案1相比,虽然最优值没有方案1好,但是平均值更加好,算法的稳定性更高。
上面的两种方案给出的都是萤火虫算法群聚方式的改进,但是我们从图像中可以看出,按照理论,萤火虫们应该会快速收敛到一起,而实际图像却是在整个空间内飞行。导致这样的原因是步长扰动因子计算的方式。
我们可以看看y=0.97^x的曲线图像
可以看出到200代左右时,其值已经非常接近0了,故我们可以推测标准萤火虫算法会在200代时收敛,在200代之后即失去了全局搜索能力。
对于优化算法来说,这不是一个好的设计,因为问题的难易程度不同,但是算法的收敛时间却很固。对于简单的问题,其他算法可能用不了200代就得出结果,而萤火虫算法却还未收敛,对于复杂的问题,可能200代还未能接近正确结果却已经收敛,陷入局部最优。
如何改进这个问题呢?我们需要找一个与最大迭代次数相关的函数来计算步长扰动因子,即最大迭代次数为100时和最大迭代次数为1000时,其曲线不会有太大的区别。
方案3.步长扰动计算公式为
可以看出当最大迭代次数为100、1000时,曲线的图像没有太大的区别,为什么要取400呢,因为,即有接近一半的迭代周期内可以全局搜索,另一半的迭代周期可以局部搜索。
实验四.方案3
参数 | 值 |
---|---|
问题维度(维度) | 2 |
萤火虫数量(种群数) | 20 |
飞行次数(最大迭代次数) | 50 |
初始吸引度 | 1 |
吸引度范围 | (0.2,1.0) |
(介质吸收系数) | 1 |
扰动步长因子 | 0.97^(400*i/iter) |
扰动方式 | 正态分布 |
取值范围 | (-100,100) |
实验次数 | 10 |
图像表现的与理论上一致接近20代时萤火虫结束全局搜索并收敛于一点,开始局部搜索。在看看最终结果。
值 | |
---|---|
最优值 | 3.614101894633592E-9 |
最差值 | 4.5271253657421557E-7 |
平均值 | 6.55382970718115E-8 |
可以看出结果明显好于上面的所有实验结果,而且也相对稳定,说明上述改进方案改进了算法的收敛速度并提升了算法的性能。
4. 总结
萤火虫算法的探究到此也到了尾声,萤火虫算法的思想相对比较简单,但是实际的实现仍然有点复杂,尤其是论文与实现之间的区别让人头疼。
相对标准萤火虫算法,给出了3种改进方案,都对算法的性能有一定的提升。由于改进点各不相同,因此这3种方案可以两两混合产生新的方案,此处不再赘述
以下指标纯属个人yy,仅供参考
指标 | 星数 |
---|---|
复杂度 | ★★★★☆☆☆☆☆☆ |
收敛速度 | ★★★★★★★☆☆☆ |
全局搜索 | ★★★★★☆☆☆☆☆ |
局部搜索 | ★★★★★★☆☆☆☆ |
优化性能 | ★★★★★☆☆☆☆☆ |
跳出局部最优 | ☆☆☆☆☆☆☆☆☆☆ |
改进点 | ★★★★★☆☆☆☆☆ |