多群粒子群优化的移动峰值基准

在这个例子中,我们展示了如何使用 MovingPeaks 基准测试。在这个基准测试上,一个流行的算法是多粒子群优化(MPSO)[Blackwell2004]_,它实现了很好的离线误差,并且能够同时跟踪多个峰值。

选择场景

移动峰值基准测试允许从 原始研究 中提出的3个原始场景中选择。这是通过检索 movingpeaks 模块中定义的常量之一来完成的。这里我们将使用场景2。

from deap.benchmarks import movingpeaks
scenario = movingpeaks.SCENARIO_2

一旦场景被检索到,我们需要设置一些更多的常量并实例化基准,这里包括问题的维度和问题的边界。

有关在 SENARIO_X 字典中定义的所有变量的列表,请参阅 MovingPeaks 类文档。

初始化

与每个DEAP示例一样,我们需要创建对象。移动峰值基准是一个最大化问题,因此我们需要一个最大化适应度。并且,我们像在 粒子群优化基础 示例中那样将该适应度与一个粒子关联。

creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Particle", list, fitness=creator.FitnessMax, speed=list, 
    best=None, bestfit=creator.FitnessMax)
creator.create("Swarm", list, best=None, bestfit=creator.FitnessMax)

然后,定义粒子生成器。它将粒子类对象 pclass 作为数据存储的对象。记住,creator.Particle,它将被赋予工具箱中的这个参数,继承自 list 并且可以用可迭代对象初始化。粒子的位置(列表的元素)和速度(属性)被设置为在给定边界之间随机生成的数字。

def generate(pclass, dim, pmin, pmax, smin, smax):
    part = pclass(random.uniform(pmin, pmax) for _ in range(dim)) 
    part.speed = [random.uniform(smin, smax) for _ in range(dim)]
    return part

下一个函数更新粒子位置和速度。

def updateParticle(part, best, chi, c):
    ce1 = (c * random.uniform(0, 1) for _ in range(len(part)))
    ce2 = (c * random.uniform(0, 1) for _ in range(len(part)))
    ce1_p = map(operator.mul, ce1, map(operator.sub, best, part))
    ce2_g = map(operator.mul, ce2, map(operator.sub, part.best, part))
    a = map(operator.sub,
                      map(operator.mul,
                                    itertools.repeat(chi),
                                    map(operator.add, ce1_p, ce2_g)),
                      map(operator.mul,
                                     itertools.repeat(1 - chi),
                                     part.speed))
    part.speed = list(map(operator.add, part.speed, a))
    part[:] = list(map(operator.add, part, part.speed))

此后,定义了一个将粒子转换为具有不同可能分布的量子粒子的函数。

def convertQuantum(swarm, rcloud, centre, dist):
    dim = len(swarm[0])
    for part in swarm:
        position = [random.gauss(0, 1) for _ in range(dim)]
        dist = math.sqrt(sum(x**2 for x in position))

        if dist == "gaussian":
            u = abs(random.gauss(0, 1.0/3.0))
            part[:] = [(rcloud * x * u**(1.0/dim) / dist) + c for x, c in zip(position, centre)]

        elif dist == "uvd":
            u = random.random()
            part[:] = [(rcloud * x * u**(1.0/dim) / dist) + c for x, c in zip(position, centre)]

        elif dist == "nuvd":
            u = abs(random.gauss(0, 1.0/3.0))
            part[:] = [(rcloud * x * u / dist) + c for x, c in zip(position, centre)]

        del part.fitness.values
        del part.bestfit.values
        part.best = None

    return swarm

最后,所有函数都被注册到工具箱中,以便在算法中进一步使用。

toolbox = base.Toolbox()
toolbox.register("particle", generate, creator.Particle, dim=NDIM,
    pmin=BOUNDS[0], pmax=BOUNDS[1], smin=-(BOUNDS[1] - BOUNDS[0])/2.0,
    smax=(BOUNDS[1] - BOUNDS[0])/2.0)
toolbox.register("swarm", tools.initRepeat, creator.Swarm, toolbox.particle)
toolbox.register("update", updateParticle, chi=0.729843788, c=2.05)
toolbox.register("convert", convertQuantum, dist="nuvd")
toolbox.register("evaluate", mpb)

移动的峰

工具箱中注册的评估函数直接引用 MovingPeaks 基准对象 mpb 的实例。调用 mpb() 会像其他评估函数一样评估给定的个体。

算法

该算法在文件 examples/pso/multiswarm 中有详细说明,它反映了 [Blackwell2004] 中描述的内容。

[Blackwell2004] (1,2)

Blackwell, T., & Branke, J. (2004). 动态环境中的多群优化。在 进化计算的应用 (第489-500页)。Springer Berlin Heidelberg.