我的目标是使用 PyGmo 执行参数估计(模型校准) .我的模型将是一个外部“black blox”模型(c 代码),输出要最小化的目标函数 J
(在这种情况下,J 将是“归一化均方根误差”(NRMSE)模型输出和测量数据。为了加快优化(校准),我想在多个内核/线程上并行运行我的模型/模拟。因此我想在 PyGMO 中使用批量适应性评估器(bfe)。我准备了一个使用简单问题类但使用纯 python(无外部模型)和 rosenbrock 问题的最小示例:
#!/usr/bin/env python
# coding: utf-8
import numpy as np
from fmpy import read_model_description, extract, simulate_fmu, freeLibrary
from fmpy.fmi2 import FMU2Slave
import pygmo as pg
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
import time
#-------------------------------------------------------
def main():
# Optimization
# Define problem
class my_problem:
def __init__(self, dim):
self.dim = dim
def fitness(self, x):
J = np.zeros((1,))
for i in range(len(x) - 1):
J[0] += 100.*(x[i + 1]-x[i]**2)**2+(1.-x[i])**2
return J
def get_bounds(self):
return (np.full((self.dim,),-5.),np.full((self.dim,),10.))
def get_name(self):
return "My implementation of the Rosenbrock problem"
def get_extra_info(self):
return "\nDimensions: " + str(self.dim)
def batch_fitness(self, dvs):
J = [123] * len(dvs)
return J
prob = pg.problem(my_problem(30))
print('\n----------------------------------------------')
print('\nProblem description: \n')
print(prob)
#-------------------------------------------------------
dvs = pg.batch_random_decision_vector(prob, 1)
print('\n----------------------------------------------')
print('\nBarch fitness evaluation:')
print('\ndvs length:' + str(len(dvs)))
print('\ndvs:')
print(dvs)
udbfe = pg.default_bfe()
b = pg.bfe(udbfe=udbfe)
print('\nudbfe:')
print(udbfe)
print('\nbfe:')
print(b)
fvs = b(prob, dvs)
print(fvs)
#-------------------------------------------------------
pop_size = 50
gen_size = 1000
algo = pg.algorithm(pg.sade(gen = gen_size)) # The algorithm (a self-adaptive form of Differential Evolution (sade - jDE variant)
algo.set_verbosity(int(gen_size/10)) # We set the verbosity to 100 (i.e. each 100 gen there will be a log line)
print('\n----------------------------------------------')
print('\nOptimization:')
start = time.time()
pop = pg.population(prob, size = pop_size) # The initial population
pop = algo.evolve(pop) # The actual optimization process
best_fitness = pop.get_f()[pop.best_idx()] # Getting the best individual in the population
print('\n----------------------------------------------')
print('\nResult:')
print('\nBest fitness: ', best_fitness) # Get the best parameter set
best_parameterset = pop.get_x()[pop.best_idx()]
print('\nBest parameter set: ',best_parameterset)
print('\nTime elapsed for optimization: ', time.time() - start, ' seconds\n')
if __name__ == '__main__':
main()
当我尝试运行此代码时,出现以下错误:
Exception has occurred: ValueError
function: bfe_check_output_fvs
where: C:\projects\pagmo2\src\detail\bfe_impl.cpp, 103
what: An invalid result was produced by a batch fitness evaluation: the number of produced fitness vectors, 30, differs from the number of input decision vectors, 1
通过删除或注释掉这两行:
fvs = b(prob, dvs)
print(fvs)
脚本可以正常运行。
我的问题:
- 如何使用批量适应度评估? (我知道这是一个新的 PyGMO 的能力,他们仍在研究 文档...)任何人都可以给出一个关于如何实现它的最小示例吗?
- 这是加快模型校准问题的正确方法吗?或者我应该使用岛屿和群岛?如果我没看错,群岛中的岛屿不会相互通信,对吧?所以如果一个人执行例如一个粒子群优化并希望同时(并行)评估多个目标函数调用,那么批量适应性评估器是正确的选择吗?
- 我需要关心这个例子中的群岛和岛屿吗?它们到底是做什么用的?是否值得运行多次优化但使用不同的初始 x(目标函数的输入)然后采用最佳解决方案?这是 GA 优化的常用方法吗?
我对优化和 PyGMO 领域非常了解,非常感谢您的帮助!
最佳答案
Is this the right way to go to speed up my model calibration problem? Or should I use islands and archipelagos? If I got it right, the islands in an archipelago are not communicating to eachother, right? So if one performs e.g. a Particle Swarm Optimization and wants to evaluate several objective function calls simultaneously (in parallel) then the batch fitness evaluator is the right choice?
pagmo 中有两种并行化模式,孤岛模型(即粗粒度并行化)和 BFE 机制(即细粒度并行化)。
孤岛模型适用于任何问题/算法组合,它基于这样的想法,即多个优化并行运行,同时交换信息以加速全局收敛到一个解决方案。
相反,BFE 机制并行化了一个单个 优化,它需要求解器的明确支持才能工作。目前在 pagmo 中只有少数求解器能够利用 BFE 机制。 BFE 机制也可用于并行化个体群体的初始化,这在您的适应度函数特别重量级时非常有用。
哪种并行化方法最适合您取决于您的问题的属性。根据我的经验,如果适应度函数非常重(例如,计算需要几分钟或更长时间),用户往往更喜欢 BFE 机制(细粒度并行化),因为在这种情况下,适应度评估的成本非常高,以至于为了利用岛屿模式的人将不得不等待太久。 BFE 在某种意义上也更容易理解,因为您不必深入研究群岛、拓扑等的细节。另一方面,BFE 仅适用于某些求解器(尽管我们正在尝试将 BFE 支持扩展到随着时间的推移其他求解器)。
How to use the batch fitness evaluation? (I know this is a new capability of PyGMO and they are still working on the documentation...) Can anybody give a minimal example on how to implement this?
使用 BFE 的一种方法是您在示例中所做的,即通过在您的问题中实现 batch_fitness()
方法。但是,我的建议是注释掉 batch_fitness()
方法并尝试使用 pagmo 提供的通用批处理适应性评估器之一。最简单的做法是默认构造 bfe
类的实例,然后将其传递给可以使用 BFE 机制的算法之一。一种这样的算法是 nspso:
https://esa.github.io/pygmo2/algorithms.html#pygmo.nspso
所以,像这样:
b = pg.bfe() # Construct a default BFE
uda = pg.nspso(gen = gen_size) # Construct the algorithm
uda.set_bfe(b) # Tell the UDA to use the BFE machinery
algo = pg.algorithm(uda) # Construct a pg.algorithm from the UDA
new_pop = algo.evolve(pop) # Evolve the population
这应该使用多个进程在 nspso 算法的循环中并行评估您的适应度函数。
如果您需要更多帮助,请到我们的公共(public)用户/开发者聊天室,您应该可以很快(通常)获得帮助:
关于python - PyGMO Batch 适应性评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60435885/