从头实现萤火虫优化算法(python)

文摘   2024-07-11 16:33   辽宁  
点击上方“进修编程”,选择“星标公众号

超级无敌干货,第一时间送达!!!

萤火虫优化算法(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 npimport randomimport mathimport 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程序设计需求可找我详谈。

—  —


进修编程
提升编程技能,学习编程技巧