为什么我不能重现介绍 Firefly 算法的原始论文中的实验?

人工智能 文件 优化 群体智能 元启发式 萤火虫算法
2021-10-21 04:28:14

我一直在尝试重现原作中所做的实验: Xin-She Yang 的Firefly Algorithm for multimodal optimization (2010),但到目前为止没有成功。目前,如果有人指出我正确的方向,我很好。

我用 C++ 编程语言编写了论文中指定的算法(我还从互联网上下载了其他几个实现以进行比较),并使用了与论文中指定的完全相同的参数(随机陡峭为 0.2,初始光强度为1.0,光衰系数为 1.0,种群规模为 40)。我使用给定的两个明亮的更新方程和德荣测试函数(例如)在 [-5.12, 5.12] 的搜索域中的 256 维数,如常见的优化文献和论文中所述。

在论文中,算法收敛得非常快,正如可以预料的那样,因为这是一个非常简单的测试函数。但是,我的实现和我下载的任何代码都没有与该参数融合。

我最后的问题是:

  1. 我是在实验方法上做错了什么,还是我使用了错误的参数设置(可能与原始论文不同)?

  2. 有谁知道我在哪里可以找到萤火虫算法的代码示例,我可以用它来重现上述论文的实验?

请注意,这个算法可能有很多变体可以产生更好的结果,但现在我只对重现所谓论文的实验感兴趣。

1个回答

我编写了一些 python 代码来重现本文声称的结果。我的代码非常有效地优化了像碗这样的简单平滑函数,但没有接近重现论文声称的更复杂函数的结果,包括作者报告的参数。我认为,由于@Jairo 和我都无法独立地从论文中的信息中重现结果,因此论文很可能有问题。

可以使用py_swarm之类的库重现论文声称的行为,但是论文使用的是萤火虫算法(已经是 PSO 的一种更罕见的形式),并且使用的是该算法的自制变体,所以我的猜测是正如我们俩一样,需要自己滚动。

此外,我发现这篇论文的说法不太可能。例如,在 4.1 节中,他们声称在 10 次迭代中收敛于具有许多局部最小值的函数的全局最小值。在我看来,大多数时候萤火虫会很快聚集在这个功能中的一个沟壑的底部,然后卡在那里。这也是我在复制中观察到的。我怀疑作者可能在没有报告的情况下从最佳运行中挑选了他们的结果,或者在论文中省略了一些关键细节。

这是我的复制代码,以防其他人想尝试复制:

from math import sin, pi, exp, sqrt
from random import random
from copy import deepcopy

def michalewiz_objective(x):
    result = 0
    for i, x_i in enumerate(x):
        result -= sin(x_i)*(sin(i*(x_i**2)/pi))**20
    return -result

def bowl_objective(x):
    return -sum([x_i**2 for x_i in x])

pop_size = 40
max_generations = 10
alpha = 0.2
gamma = 1
beta_0 = 1
d = 2
I = michalewiz_objective
#I = bowl_objective

def move(firefly, other_firefly):
    radius = sqrt(sum([(firefly[i] - other_firefly[i])**2 for i in range(0, len(firefly))]))
    for i, value in enumerate(firefly):
        firefly[i] += beta_0*exp(-gamma*radius**2)*(other_firefly[i] - firefly[i])
        firefly[i] += alpha * (random() - 0.5)

# Using 4*random() to match Figure 3's apparent spread.
fireflies = [[4*random() for i in range(0, d)] for j in range(0, pop_size)]

for generation in range(0, max_generations):
    new_fireflies = [deepcopy(firefly) for firefly in fireflies]
    for index, firefly in enumerate(fireflies):
        for other_firefly in fireflies:
            if I(other_firefly) > I(firefly):
                move(new_fireflies[index], other_firefly)
    fireflies = new_fireflies
    best = max([I(f) for f in fireflies])
    mean = [sum([f[0] for f in fireflies]), sum([f[1] for f in fireflies])]
    print(best)
    print(mean)