parallel/multithread python 中的差异进化

parallel/multithread differential evolution in python

我正在尝试模拟一个生化过程,我将我的问题构建为一个优化问题,我使用 scipy 中的 differential_evolution 解决了这个问题。
到目前为止,非常好,我对具有 15-19 个参数的简化模型的实现非常满意。
我扩展了模型,现在有 32 个参数,时间太长了。并非完全出乎意料,但仍然是一个问题,因此问题。

我看过:
- 一个几乎相同的问题 R Parallel differential evolution
- 以及关于主题

的 github 个问题 https://github.com/scipy/scipy/issues/4864

但它想留在 python 中(该模型在 python 管道中),并且拉取请求尚未导致正式接受的解决方案,尽管已经有一些选项建议。

此外,我无法在要优化的函数中并行化代码,因为这是一系列顺序计算,每个计算都需要上一步的结果。理想的选择是有一些东西可以并行评估一些人,然后 return 他们对人口进行评估。

总结:
- scipy 中是否有任何选项允许并行化我无意中忽略的 differential_evolution? (理想解)
- 是否有关于 scipy 中的替代算法的建议,该算法要么(方式)更快地串行化,要么可以并行化?
- 有没有其他好的包提供并行差分进化函数?或者其他适用的优化方法?
- 健全性检查:我是否用 32 个参数重载了 DE,我需要从根本上改变方法?

PS
我是一名生物学家,正式的 math/statistics 不是我的强项,任何公式到英文的翻译将不胜感激 :)

PPS
作为一个极端的选择,我可以尝试迁移到 R,但我不会编码 C/C++ 或其他语言。

我一直遇到完全相同的问题。或许,您可以尝试 pygmo,它支持不同的优化算法(包括 DE)并具有并行计算模型。但是,我发现社区并不像 scipy 那样大。他们的教程、文档和示例质量都很好,人们可以从中得到一些东西。

感谢@jp2011 指向 pygmo

首先,值得注意的是与 pygmo 1 的区别,因为 google 上的 link 仍然指向旧版本。

其次,Multiprocessing island 仅适用于 python 3.4+

第三,有效。当我第一次问这个问题时,我开始的过程仍然是 运行,而我写的时候,pygmo 群岛 运行 在不到 3 小时的时间内对 saDE 中存在的所有 18 种可能的 DE 变体进行了广泛的测试。此处建议的使用 Numba 的编译版本 https://esa.github.io/pagmo2/docs/python/tutorials/coding_udp_simple.html 可能会更早完成。起首。

我个人觉得它不如 scipy 版本直观,因为需要构建一个新的 class(相对于 scipy 中的 signle 函数)来定义问题但可能只是个人喜好。另外,mutation/crossing over参数定义不太清楚,对于第一次接触DE的人来说可能有点晦涩。
但是,由于 scipy 中的串行 DE 并没有削减它,欢迎使用 pygmo(2)。

此外,我发现了其他几个声称可以并行化 DE 的选项。我没有亲自测试它们,但可能对遇到这个问题的人有用。

Platypus,专注于多目标进化算法 https://github.com/Project-Platypus/Platypus

雅宝
https://github.com/pablormier/yabox

来自 Yabox 的创建者对 DE 的详细但恕我直言 crystal 清晰的解释 https://pablormier.github.io/2017/09/05/a-tutorial-on-differential-evolution-with-python/

Scipy differential_evolution 现在可以非常容易地并行使用,通过指定工作人员:

workers int or map-like callable, optional

If workers is an int the population is subdivided into workers sections and evaluated in parallel (uses multiprocessing.Pool). Supply -1 to use all available CPU cores. Alternatively supply a map-like callable, such as multiprocessing.Pool.map for evaluating the population in parallel. This evaluation is carried out as workers(func, iterable). This option will override the updating keyword to updating='deferred' if workers != 1. Requires that func be pickleable.

New in version 1.2.0.

scipy.optimize.differential_evolution documentation

我建议使用PyFDE的批处理模式。 https://pythonhosted.org/PyFDE/tutorial.html#batch-mode 在批处理模式下,每次迭代只会调用一次适应度函数来评估所有种群的适应度。

示例w/o批处理模式:

import pyfde
from math import cos, pi
import time
import numpy

t1=time.time()
def fitness(p):
    x, y = p[0], p[1]
    val = 20 + (x**2 - 10*cos(2*pi*x)) + (y**2 - 10*cos(2*pi*y))
    return -val
    
solver = pyfde.ClassicDE(fitness, n_dim=2, n_pop=40, limits=(-5.12, 5.12))
solver.cr, solver.f = 0.9, 0.45
best, fit = solver.run(n_it=150)
t2=time.time()
print("Estimates: ",best)
print("Normal mode elapsed time (s): ",t2-t1)

批处理模式示例:

t1=time.time()
def vec_fitness(p,fit):
    x, y = numpy.array(p[:,0]), numpy.array(p[:,1])
    val = 20 + (x**2 - 10*numpy.cos(2*pi*x)) + (y**2 - 10*numpy.cos(2*pi*y))
    fit[:] = -val
    
solver = pyfde.ClassicDE(vec_fitness, n_dim=2, n_pop=40, limits=(-5.12, 5.12), batch=True)
solver.cr, solver.f = 0.9, 0.45
best, fit = solver.run(n_it=150)
t2=time.time()
print("Estimates: ",best)
print("Batch mode elapsed time (s): ",t2-t1)

输出为:

估计:[1.31380987e-09 1.12832169e-09]
正常模式运行时间(秒):0.015959978103637695

估计:[2.01733383e-10 1.23826873e-10]
批处理模式运行时间(秒):0.006017446517944336

############################################# ###############

速度提高了 1.5 倍,但仅适用于简单的问题。对于复杂问题,您可以更快地查看 10 倍以上。 代码在单个 CPU 核心上运行(无多处理),性能提升来自矢量化和 MIMD(多指令、多数据)的使用。结合矢量化和 parallel/multi-processing 将带来双重改进。