SciPy中的并行优化

时间:2012-10-13 15:55:29

标签: python optimization scipy

我有一个简单的功能

def square(x, a=1):
    return [x**2 + a, 2*x]

对于多个参数x,我希望将其最小化a。我目前有循环,在精神上,做这样的事情:

In [89]: from scipy import optimize

In [90]: res = optimize.minimize(square, 25, method='BFGS', jac=True)

In [91]: [res.x, res.fun]
Out[91]: [array([ 0.]), 1.0]

In [92]: l = lambda x: square(x, 2)

In [93]: res = optimize.minimize(l, 25, method='BFGS', jac=True)

In [94]: [res.x, res.fun]
Out[94]: [array([ 0.]), 2.0]

现在,该功能已经过矢量化

In [98]: square(array([2,3]))
Out[98]: [array([ 5, 10]), array([4, 6])]

In [99]: square(array([2,3]), array([2,3]))
Out[99]: [array([ 6, 12]), array([4, 6])]

这意味着并行运行所有优化而不是循环可能要快得多。这是SciPy可以轻松实现的吗?或任何其他第三方工具?

3 个答案:

答案 0 :(得分:14)

这是另一次尝试,基于my original answer以及随后的讨论。

据我所知,scipy.optimize模块用于带标量或矢量输入和标量输出或“成本”的函数。

由于您将每个等式视为独立于其他等式,我最好的想法是使用多处理模块并行完成工作。如果您最小化的功能与问题中的功能一样简单,我会说这不值得付出努力。

如果功能更复杂,并且您想分工,请尝试以下方法:

import numpy as np
from scipy import optimize
from multiprocessing import Pool

def square(x, a=1):
    return [np.sum(x**2 + a), 2*x]

def minimize(args):
    f,x,a = args
    res = optimize.minimize(f, x, method = 'BFGS', jac = True, args = [a])
    return res.x

# your a values
a = np.arange(1,11)

# initial guess for all the x values
x = np.empty(len(a))
x[:] = 25

args = [(square,a[i],x[i]) for i in range(10)]
p = Pool(4)
print p.map(minimize,args)

答案 1 :(得分:4)

我参加聚会有点晚了。但这对于希望通过并行计算减少最小化时间的人可能很有趣:

我们在PyPI上可用的软件包 optimparallel 中实现了scipy.optimize.minimize(method='L-BFGS-B')的并行版本。通过并行评估目标函数和(近似)梯度,可以加快优化速度。这是一个示例:

from optimparallel import minimize_parallel
def my_square(x, a=1):
    return (x - a)**2
minimize_parallel(fun=my_square, x0=1, args=11)

请注意,并行实现只会以较长的评估时间(例如,大于0.1秒)减少目标函数的优化时间。这是可能的并行缩放的说明: enter image description here

答案 2 :(得分:1)

如果我了解您的意图,您可以为xa传递numpy数组,这样您就可以同时优化所有a参数。

尝试类似:

def square(x, a=1):
    return [np.sum(x**2 + a), 2*x]

# your a values
a = np.arange(1,11)

# initial guess for all the x values
x = np.empty(len(a))
x[:] = 25

# extra arguments to pass to the objective function, in this case, your a values
args = [a]

res = optimize.minimize(square, x, method = 'BFGS', jac = True, args = args)

这似乎得到了正确的结果。

>>> res.x
[ -8.88178420e-16  -8.88178420e-16  -8.88178420e-16  -8.88178420e-16
  -8.88178420e-16  -8.88178420e-16  -8.88178420e-16  -8.88178420e-16
  -8.88178420e-16  -8.88178420e-16]
>>> res.fun
55.0