SciPy 中的并行优化
Posted
技术标签:
【中文标题】SciPy 中的并行优化【英文标题】:Parallel optimizations in SciPy 【发布时间】:2012-10-04 04:41:03 【问题描述】:我有一个简单的功能
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 方工具?
【问题讨论】:
我不明白您要优化什么:您的函数返回两个值。顺便说一句,第一个是抛物线,最小值为零,第二个没有最小值 查看docs,特别注意jac = True
的含义。该函数返回“成本”和梯度。
澄清一下:您是在为这个特定的简单功能或任何简单功能寻找解决方案吗?
为任何给定的函数寻找这个问题的解决方案。这个例子只是一个简单的说明。我真正的问题是尝试实现多类分类算法。我目前正在遍历每个班级并最小化每个班级一次的成本函数。但是我的成本函数可以轻松返回成本向量和梯度向量,但我正在尝试找出如何将其提供给 scipy.optimize。
【参考方案1】:
这是另一个尝试,基于 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)
【讨论】:
【参考方案2】:我参加聚会有点晚了。但这对于希望通过并行计算减少最小化时间的人来说可能很有趣:
我们在 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 秒)的目标函数的优化时间。以下是可能的并行缩放的说明:
【讨论】:
你在哪里指定处理器的数量? @andy 查看parallel
参数的描述。【参考方案3】:
如果我理解您的意图,您可以为 x
和 a
传递 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
【讨论】:
我想这对我来说太直观了。将尝试解决我的真正问题,并让您知道它是如何进行的。谢谢! 你使用的是什么版本的 scipy?我实际上得到一个 ValueError 试图运行该代码:ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
对不起@ludaavics,我使用的是旧版本的 scipy (0.10) 和外推,我不应该这样做。我已经用 scipy 0.11 测试了上面的内容,它可以工作。不同之处在于“成本”值必须是标量。我使用的版本似乎通过将 square
返回的成本向量相加来隐式执行此操作。
好的,所以这种方法不适用于我的目的,是吗?我想我举的例子有点过于简单了——如果你将成本函数更改为(x+a)**2
,那么不同的参数给出不同的最小值位置,对成本向量求和就变得毫无意义(我猜这就是为什么在 0.11 中它们强制你返回一个标量来说明)
好吧,也许我完全误解了你的意图。我是否正确,您试图找到标量值x
,它在给定标量输入a
的情况下最小化square()
的输出,但每个方程都独立于其他方程?以上是关于SciPy 中的并行优化的主要内容,如果未能解决你的问题,请参考以下文章
线程(c++ 中的并行计算)是不是与优化级别(gcc)不兼容?
并行编程双笙子佯谬 - 高性能并行编程与优化 - 视频教程目录