Scipy.Optimize - 多重处理并在 Python 中的最后一次迭代中恢复

Scipy.Optimize - multiprocessing and resuming on last iteration in Python

Scipy.Optimize 可以选择通过将 "workers" 参数更改为 > 1(或 -1)来启用多处理。但是,如果我希望能够从上一次迭代中恢复优化,同时仍然使用多处理功能,这似乎是不可能的。

我可以通过使用 DifferentialEvolutionSolver 恢复操作(根据 https://github.com/scipy/scipy/issues/6517),但是在 DifferentialEvolutionSolver 中 "workers" > 1 使我无法 pickle 对象以保持会话之间的持久性。

import pickle
from scipy.optimize._differentialevolution import DifferentialEvolutionSolver  

bounds = [(-1, 1)]
bounds = bounds * 66

if __name__ == '__main__':

    solver = DifferentialEvolutionSolver(converter, bounds, disp=True, seed=9, workers=-1, 
    maxiter=1)
    for i in range(100):
            best_x, best_cost = next(solver)
            print(solver.population_energies.min())
            with open('solver_%d.pkl' % i, 'wb') as f:
                 pickle.dump(solver, f)

此代码在尝试 pickle 其第一个 运行 时会生成以下错误:

NotImplementedError: pool objects cannot be passed between processes or pickled

但是,如果我使用 "workers=1",代码工作正常,但显然要慢得多。

有没有办法同时获得多处理和保存每次迭代的能力?

请记住,DifferentialEvolutionSolver 不是 SciPy 的 public API 的一部分,它可能会更改.提高性能需要更改的能力,或 re-engineering。向后兼容的 public 面向函数是 differential_evolution。 如果您准备好应对这种情况,那么您可以使用以下方法:

import pickle
from multiprocessing import Pool

from scipy.optimize import rosen
from scipy.optimize._differentialevolution import DifferentialEvolutionSolver  

bounds = [(-2, 2), (-2, 2)]

with Pool(2) as p:
    # make sure that `updating='deferred'`, as this is required for
    # parallelisation
    solver = DifferentialEvolutionSolver(
        rosen,
        bounds,
        seed=9,
        workers=1,
        updating='deferred',
    )

    for i in range(100):
        # the _mapwrapper attribute needs to be a map-like
        solver._mapwrapper = p.map
        best_x, best_cost = next(solver)
        print(solver.population_energies.min())
        solver._mapwrapper = map
        with open(f"solver_{i}.pkl", 'wb') as f:
             pickle.dump(solver, f)