点击上方“进修编程”,选择“星标”公众号
超级无敌干货,第一时间送达!!!
萤火虫优化算法(Firefly Algorithm, FA)灵感主要来源自萤火虫的闪光行为,并将闪光作为一个信用系统,以吸引其他萤火虫。
算法(以下称为FA)就像PSO、GA、ABC等等演算法,是模仿自然界中动物所设计的演算法。其优点是参数少、易理解和容易实现,缺点是容易陷入局部最佳解,最好解决更高维度的多维度问题时更容易
本文除了针对FA本身进行参数、步长的说明外,也会以Rastrigin函数最佳化问题为例,使用FA进行演示。针对FA易陷入局部最佳化 (Local Optimum)的问题,网上有其他文章说明FA的优化或是混合型算法等可解决其问题,而本文最后只会针对参数的改进和加入敏捷因子等方法进行说明,其他部分也不会多做介绍。
在本文你将学习以下技巧:
1.培养分析问题的能力。
3.用python实现简单萤火虫算法。
4.透过萤火虫算法解决最优化问题。
优化问题
此次求解最佳化问题为Rastrigin函数,为最佳化常用的测试函数,其最佳解为f(0,0,…,0) = 0,公式如下:
萤火虫算法的三大假设
昆虫不分性别。在不考虑寻求偶遇的情况下,可假扮任何人接触昆虫都可以其他昆虫所接触,并可吸引其他昆虫的注意。
吸引力与火灾的轮廓成正比。以两点暗示,轮廓差异的火灾会被吸引移动到更亮的一个火灾。但轮廓会随着距离的增加而减少。
随机移动。如果没有比一个给定的萤火虫更亮(吸引力更大)的萤火虫,该萤火虫就会随机移动。
算法逻辑
以下说明及伪代码是维基百科的内容,针对FA的假设置及流程已表达得非常清楚,所以请记住辅助说明即可。
参数定义及介紹
N:初始 人口的大小,此变化量决定初始群集内昆虫的数量。
D: Dimension 尺寸大小,欲求解惑问题之变量。
max_iter:欲进行迭代之次数。
β:吸引力最大吸引力,通常愿意成为吸引力常数。
γ:为光吸收系数。
αt:为重要的因子。
任两个萤火虫的位置更新公式为:
其中:
β exp[-γr² ](Xj-Xi ):指的是两个干扰因素的吸引力。
r:为两个萤火虫之间的距。
∈t: 为一向量。
步骤说明
(1) 首先生成一个初始群体(Initial Population),其中包含 N 只昆虫,每只昆虫的维度为 D。
(2) 计算每一只萤火虫的适应度(fitness),任何一只萤火虫都会向亮度更高(适应度更低)的萤火虫移动。
(3) 所有的萤火虫都会与其他萤火虫进行比较,并更新自己的位置(position)和亮度(brightness)。位置更新公式如上文所述。
(4) 重复步骤 2 和 3,直到找到最优解。
总的来说,这就是一个基于萤火虫行为的优化算法的主要步骤。该算法通过模拟萤火虫互相吸引的行为,来不断优化和改进解决方案,最终找到问题的最优解。
Python 开发
初始种群
产出初始群集,并针对群集内每个参与者进行适应度的计算。
初始参数设置为,N(5)、D(10)、max_iter(20)、β(1.0)、γ(0.0001)、αt(0.97)。
最小值:38.6345
进入萤火虫算法 运算
将初始群集带入FA 中迭代,依序针对每个细微昆虫,其会与长度最亮(适应度最小)的昆虫进行位置和长度的更新,直到到达最终条件为止。
主要代码:
import numpy as np
import random
import math
import matplotlib.pyplot as plt
class FA:
def __init__(self, dimen, population, max_iter):
self.D = dimen # Dimension of problems
self.N = population # Population size
self.it = max_iter # Max iteration
self.Ub = 3*np.ones(dimen) # Upper bound
self.Lb = 0*np.ones(dimen) # Lower bound
self.A = 0.97 # Strength
self.B = 1 # Attractiveness constant
self.G = 0.0001 # Absorption coefficient
def fun(self, pop):
X = np.array(pop)
funsum = 0
for i in range(self.D):
x = X[:,i]
funsum += x**2 - 10*np.cos(2*np.pi*x)
funsum += 10*self.D
return list(funsum)
def main():
fa = FA(5,10,20)
pop=np.zeros((fa.N,fa.D))
for i in range(fa.N):
for j in range(fa.D):
pop[i,j] = np.random.uniform(-5,5)
fitness = fa.fun(pop)
best_list = []
best_para_list = []
best_list.append(min(fitness))
arr = fitness.index(min(fitness))
best_para = pop[arr]
best_para_list.append(best_para)
r_distance = 0
it = 1
while it < fa.it:
for i in range(fa.N):
for j in range(fa.D):
steps = fa.A*(random.uniform(0,1)-0.5)*abs(fa.Ub[0]-fa.Lb[0])
for k in range(fa.N):
if fitness[i] > fitness[k]:
r_distance += (pop[i][j] - pop[k][j])**2
Beta = fa.B*math.e**(-(fa.G*r_distance))
xnew = pop[i][j] + Beta*(pop[k][j] - pop[i][j]) + steps
if xnew > fa.Ub[0]:
xnew = fa.Ub[0]
elif xnew < fa.Lb[0]:
xnew = fa.Lb[0]
pop[i][j] = xnew
fitness = fa.fun(pop)
best_ = min(fitness)
arr_ = fitness.index(best_)
best_para_ = pop[arr_]
best_list.append(best_)
best_para_list.append(best_para_)
it+=1
plt.figure(figsize=(15,8))
plt.xlabel("GENERATIONS", fontsize=20)
plt.ylabel("VALUE", fontsize=20)
plt.plot(best_list,linewidth=2,label = "Best value so far ",color="g")
if __name__ == '__main__':
main()
经过20次的迭代后,将更新后的群集和适应度列表如下:
最佳解为[ 0, 0, 0, 0, 0 ],其适应度为0。
图表显示 10 个热门火虫已有 5 个已达到最佳解,事实上萤火虫聚集再一起;如果将问题降至最低,在平面上表示则为重点在一起。
将结果视觉化如下,绿线为祖先迭代最好解:
透过迭代结果可知,设定Dimension为5下的结果可达到最佳fitness 0,且大约在第7次就结束啦。
上述情况为正常情况,解决疑问问题产出的最好结果;在下次定期报告中对局部最佳做法进行介绍。
局部最佳解问题
针对文章一开始就介绍了FA易陷入局部最佳解 (Local Optimum)的情形,以和上述结果相同的参数进行演算,并同上述迭代20后的结果,在多次试验的情况下出现此情形:
最佳解为[ 0, 0, 3, 0, 0 ],其适应度为9。
请注意,0 和 3 是由于初始参数设置时,上界设置值为 3、下界设置值为 0 的担忧。
除了第六个萤火虫外,其他萤火虫之最佳解均为9,明显就是落入局部最佳的一个情况。
历代最佳作品结出显著成绩,首次试运行于第2次就落入局部最佳作品,并持续到结束。
FA演算法的优化
如果您想防止结果陷入局部最优状态,请阅读以下方法继续调整:
增加一个百分点常数给αt,使其每次更新时,位置都会有些微变化。例如:给予一个百分点常数0.97,在每次更新时,αt都必须乘上这个一个百分点常数。
调整∈t,其实际进程码共享时,αt和∈t相乘时,有加入一随机因子激活因子,其介于[0~1];通过由此激活因子,使萤火虫于更新位置时,不会只固定于上下界的极值。
关于FA的优化、混合算法网上其他高级功能也都提供,感兴趣的读者可以自行查阅。
结语
萤火虫算法(Firefly Algorithm, FA)是一种简单有效的仿生算法。它模拟了萤火虫之间相互吸引的行为,在优化过程中容易呈现出动物行为的特点。对于初学者而言,萤火虫算法是一个不错的仿生算法入门选择。在熟悉了它的逻辑架构之后,也有利于进一步了解和理解其他类型的仿生算法。
最后,再次感谢各位读者抽出宝贵的时间阅读到这里。如有matlab、python程序设计需求可找我详谈。
— 完 —