使用ipython并行运行scipy.optimize来最小化函数

4
我发现有很多关于类似问题的疑问(例如这个问题),在处理iPython.Parallel时,pickle闭包的问题似乎无处不在,但是我无法解决这个特定的问题。所以我的问题如下:
我想使用ipcluster解决一个函数f(a,b)在多个b值上的零点。f本身是一个复杂的函数。让我们用一个愚蠢的例子来说明:
import scipy.optimize

def f(a,b):
     return (a+b)**2 + numpy.sin(a*b)

bs = range( 20 )

for b in bs:
     g = lambda a : f(a,b)
     root = scipy.optimize.fsolve( g, 0.0 )
     print root

这是我所做的工作的一般概念。问题是,如果我尝试创建一个返回根的函数,它将不得不创建一个闭包并将其传递给scipy.optimize.fsolve(我想)。例如,我尝试过:

 def root( b ):
      g = lambda a : f( a, b )
      return scipy.optimize.fsolve( g, 0.0 )

但是如果您使用的map,它将无法pickle闭包。我想不出任何解决方法,您能想到吗?


我猜重现错误的最小示例可能是:

import numpy
import scipy.optimize

from IPython.parallel import Client

def f( a,b):
    return (a+b)**2+numpy.cos(a*b)

def h( a,b=1.0):
    return (a+b)**2+numpy.cos(a*b)

def root_h( a ):#argument just for mapping, not used
    return scipy.optimize.fsolve( h, 0.0 )

def root(b):
    g = lambda a : f(a,b)
    return scipy.optimize.fsolve( g, 0.0 )

if __name__=='__main__':

    #first normally, this works
    print root( 1.0 )
    print root( 2.0 )

    #now parallely, doesn't work
    c = Client()
    dview = c[:]
    with dview.sync_imports():
        import numpy
        import scipy.optimize

    #this works
    dview.push({'h':h})
    res = dview.map( root_h, [1.0,2.0] )

    for i in res:
        print i

    #this doesn't
    dview.push({'f':f})
    res = dview.map( root, [1.0,2.0] )

    for i in res:
        print i

如果有人能想到解决方法,欢迎分享,对于我来说,它会抛出错误ValueError: Sorry, cannot pickle code objects with closures...

谢谢大家,SO真的很有帮助 :).

1个回答

3
如果你避免在root (b)中创建一个闭包会怎样?
我建议尝试。
def root(b):
    g = lambda a, b=b : f(a,b)
    return scipy.optimize.fsolve( g, 0.0 )

你的示例中,闭包会导致Pickle错误。改为手动指定变量b(lambda函数可以有多个参数或关键字参数),即可避免闭包问题,得到预期结果。

那是我的最初策略,但它最终以某种方式创建了一个闭包。我会再试一次。我们会看到的。 - Alex S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接