Python 对scipy.optimize.leastsq目标函数的多线程调用

Python 对scipy.optimize.leastsq目标函数的多线程调用,python,scipy,mathematical-optimization,Python,Scipy,Mathematical Optimization,我正在将scipy.optimize.leastsq与模拟器结合使用leastsq调用用户定义的目标函数,并向其传递输入向量。反过来,目标函数返回一个错误向量leastsq优化输入向量,使误差向量的平方和最小化 在我的例子中,每次调用目标函数时,它都会运行一个完整的模拟。所使用的模拟器是单线程的,每次运行需要几分钟。因此,我希望同时运行模拟器的多个实例。但是,对目标函数的调用是串行执行的 如何让leastsq一次执行对目标函数的多个调用?这有帮助吗? 我一直认为,使用python进行多进程处理

我正在将scipy.optimize.leastsq与模拟器结合使用
leastsq
调用用户定义的目标函数,并向其传递输入向量。反过来,目标函数返回一个错误向量
leastsq
优化输入向量,使误差向量的平方和最小化

在我的例子中,每次调用目标函数时,它都会运行一个完整的模拟。所使用的模拟器是单线程的,每次运行需要几分钟。因此,我希望同时运行模拟器的多个实例。但是,对目标函数的调用是串行执行的

如何让
leastsq
一次执行对目标函数的多个调用?

这有帮助吗?


我一直认为,使用python进行多进程处理时,池是最简单的

NumPy/SciPy的函数通常针对多线程进行优化。您是否查看了CPU利用率以确认在运行模拟时仅使用了一个内核?否则,您将无法从运行多个实例中获益


如果它实际上是单线程的,那么最好的选择是使用该模块。它运行Python解释器的多个实例,因此您可以同时调用SciPy。

Levenberg Marquardt使用的算法需要知道当前点的目标函数值,然后才能确定下一点。简而言之,没有直接的方法来并行化这样的串行算法

但是,在某些情况下,您可以并行化目标函数。可以这样做,如果其形式为:

def objective_f(params):
    r = np.zeros([200], float)
    for j in range(200):
        r[j] = run_simulation(j, params)
    return

def run_simulation(j, params):
    r1 = ... compute j-th entry of the result ...
    return r1
在这里,您可以清楚地跨
j
的循环进行并行化,例如使用多处理模块。类似这样的:(未经测试)

如果您必须拟合多个数据集,则会出现并行化的另一个机会——这是一个(令人尴尬的)并行问题,不同的数据集可以并行拟合

如果这没有帮助,您可以查看文献中关于LM算法并行化的讨论。例如:本文提出的主要优化似乎是雅可比矩阵数值计算的并行化。您可以通过向
leastsq
提供自己的并行雅可比函数来实现这一点。本文剩下的建议,推测性地并行化Levenberg-Marquardt搜索步骤,但是更难实现,需要对LM算法进行更改


我不知道Python(或其他语言)库实现了针对并行计算的优化算法,尽管可能有一些。如果您设法实现/找到了其中一个,请在Scipy用户邮件列表上公布这一点——肯定有人对其中一个感兴趣

如果您有多个参数,您可以通过提供自己的函数来计算导数(
Dfun
参数),从而加速
leastsq
。如果未提供此函数,
leastsq
每次迭代每个参数以计算导数,这非常耗时。这似乎占用了配件中的大部分时间

您可以使用自己的
Dfun
函数,该函数使用
多处理.Pool
来计算每个参数的导数。这些导数可以独立计算,并且应该简单地并行化

下面是一个粗略的示例,展示了如何做到这一点:

import numpy as np
import multiprocessing
import scipy.optimize

def calcmod(params):
    """Return the model."""
    return func(params)

def delta(params):
    """Difference between model and data."""
    return calcmod(params) - y

pool = multiprocessing.Pool(4)

def Dfun(params):
    """Calculate derivatives for each parameter using pool."""
    zeropred = calcmod(params)

    derivparams = []
    delta = 1e-4
    for i in range(len(params)):
        copy = np.array(params)
        copy[i] += delta
        derivparams.append(copy)

    results = pool.map(calcmod, derivparams)
    derivs = [ (r - zeropred)/delta for r in results ]
    return derivs

retn = scipy.optimize.leastsq(leastfuncall, inputparams, gtol=0.01,
                              Dfun=Dfun, col_deriv=1)
如果您使用过,它是一个更好的选择,当我使用它来优化函数时,它会使用所有可用的线程。因此,这正是你所要求的

import numpy as np
import multiprocessing
import scipy.optimize

def calcmod(params):
    """Return the model."""
    return func(params)

def delta(params):
    """Difference between model and data."""
    return calcmod(params) - y

pool = multiprocessing.Pool(4)

def Dfun(params):
    """Calculate derivatives for each parameter using pool."""
    zeropred = calcmod(params)

    derivparams = []
    delta = 1e-4
    for i in range(len(params)):
        copy = np.array(params)
        copy[i] += delta
        derivparams.append(copy)

    results = pool.map(calcmod, derivparams)
    derivs = [ (r - zeropred)/delta for r in results ]
    return derivs

retn = scipy.optimize.leastsq(leastfuncall, inputparams, gtol=0.01,
                              Dfun=Dfun, col_deriv=1)