SciPy中的并行优化

问题描述 投票:12回答:3

我有一个简单的函数

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可以轻易做到的事情吗?或者任何其他第三方工具?

python optimization scipy
3个回答
15
投票

下面是另一个尝试,基于 我的原话 以及随后的讨论。

据我所知 scipy.optimization 模块适用于具有标量或矢量输入和标量输出(或称 "成本")的函数。

由于你把每个方程都看作是独立于其他方程的,我最好的想法是使用多处理模块来并行完成工作。 如果你要最小化的函数和你的问题中的函数一样简单,我想说这是不值得的。

如果函数比较复杂,而你又想分工合作,可以尝试一下这样的方法。

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)

3
投票

我来得有点晚了 但对于想通过并行计算来减少最小化时间的人来说,这可能会很有趣。

我们实现了一个并行版本的 scipy.optimize.minimize(method='L-BFGS-B') 包装内 最佳平行 可在PyPI上使用,它可以通过并行评估目标函数和(近似)梯度来加速优化。它可以通过并行评估目标函数和(近似)梯度来加快优化速度。下面是一个例子。

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


1
投票

如果我理解你的意图,你可以为两个目标函数传递numpy数组。xa因此,您可以优化您的所有 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
© www.soinside.com 2019 - 2024. All rights reserved.