我正在scipy.optimize.leastsq
与模拟器一起使用。leastsq
调用用户定义的目标函数并将输入向量传递给它。反过来,目标函数返回一个误差向量。leastsq
以最小化误差向量的平方和的方式优化输入向量。
在我的例子中,目标函数每次被调用时都会运行一个完整的模拟。使用的模拟器是单线程的,每次运行都需要几分钟。因此,我想一次运行模拟器的多个实例。但是,对目标函数的调用是连续执行的。
如何leastsq
一次对目标函数执行多次调用?
我正在scipy.optimize.leastsq
与模拟器一起使用。leastsq
调用用户定义的目标函数并将输入向量传递给它。反过来,目标函数返回一个误差向量。leastsq
以最小化误差向量的平方和的方式优化输入向量。
在我的例子中,目标函数每次被调用时都会运行一个完整的模拟。使用的模拟器是单线程的,每次运行都需要几分钟。因此,我想一次运行模拟器的多个实例。但是,对目标函数的调用是连续执行的。
如何leastsq
一次对目标函数执行多次调用?
leastsq
如果您有多个参数,则可以通过提供自己的函数来计算导数(Dfun
参数)来加快速度。如果未提供此函数,则leastsq
每次迭代每个参数以计算导数,这很耗时。这似乎花费了拟合的大部分时间。
您可以使用自己的Dfun
函数来计算每个参数的导数,使用 amultiprocessing.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)
使用的算法leastsq
,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
,例如使用多处理模块。像这样的东西:(未经测试)
def objective_f(params):
r = np.zeros([200], float)
def parameters():
for j in range(200):
yield j, params
pool = multiprocessing.Pool()
r[:] = pool.map(run_simulation, parameters())
return r
如果您必须拟合多个数据集,则会出现另一个并行化机会 --- 这是一个(令人尴尬的)并行问题,并且可以并行拟合不同的数据集。
如果这没有帮助,您可以查看文献中关于 LM 算法并行化的讨论。例如:http ://dl.acm.org/citation.cfm?id=1542338 本文建议的主要优化似乎是雅可比行列式数值计算的并行化。您可以通过将自己的并行雅可比函数提供给leastsq
. 论文的其余建议,推测性地并行化 Levenberg-Marquardt 搜索步骤,但是更难以实现,并且需要更改 LM 算法。
我不知道 Python(或其他语言)库实现了针对并行计算的优化算法,尽管可能有一些。如果您设法实施/找到其中之一,请在 Scipy 用户邮件列表上做广告 --- 肯定对其中之一感兴趣!
这有帮助吗? http://docs.python.org/library/multiprocessing.html
我一直发现 Pool 是使用 python 进行多进程最简单的方法。
NumPy/SciPy 的函数通常针对多线程进行优化。您是否查看了 CPU 利用率以确认在运行模拟时只使用了一个内核?否则,您无法从运行多个实例中获得任何收益。
如果它实际上是单线程的,那么您最好的选择是使用该multiprocessing
模块。它运行多个 Python 解释器实例,因此您可以同时调用多个 SciPy。
您是否使用过 scipy.least_squares,这是一个更好的选择,当我使用它来优化函数时,它会使用所有可用线程。因此,正是你问的