多群粒子群优化的移动峰值基准¶
在这个例子中,我们展示了如何使用 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] 中描述的内容。