17

我有一个简单的功能

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 可以轻松做到这一点吗?或任何其他 3rd 方工具?

4

3 回答 3

22

这是另一个尝试,基于我的原始答案和随后的讨论。

据我所知,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)
于 2012-10-15T23:33:14.573 回答
10

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

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

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 秒)的目标函数的优化时间。以下是可能的并行缩放的说明: 在此处输入图像描述

于 2020-06-02T22:47:12.970 回答
2

x如果我理解您的意图,您可以为and传递 numpy 数组a,这样您就可以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
于 2012-10-13T17:05:14.250 回答