首页 文章

Scipy的优化与Multiprocessing不兼容?

提问于
浏览
0

在尝试使用Scipy的优化算法来最小化在子过程中计算其值的函数时,我发现基于梯度的算法(到目前为止流域购物和L-BFGS-B)在optimize.py的第562行遇到以下错误:

grad [k] =(f(*((xk d,)args)) - f0)/ d [k]
TypeError:不支持的操作数类型 - :'NoneType'和'NoneType'

以下是生成此错误的代码的简单示例:

import multiprocessing as mp
from scipy.optimize import basinhopping

def runEnvironment(x):
    return x**2

def func(x):
    if __name__ == '__main__':
        print "x:",x
        pool = mp.Pool(processes=1)

        results=pool.apply(runEnvironment,(x,))
        pool.close()
        return results

x0=5    
ret=basinhopping(func, x0, niter=100, T=1.0, stepsize=0.1, minimizer_kwargs=None, take_step=None, accept_test=None, callback=None, interval=50, disp=False, niter_success=None)

请注意,如果删除了多处理组件,或者使用了基于非梯度的算法(如COBYLA),则此代码可以正常运行 . 任何人都可以想到这种情况发生的原因吗?

2 回答

  • 0

    你的 if __name__ == '__main__': 成语位置不正确 - 以这种方式重新排列:

    import multiprocessing as mp
    from scipy.optimize import basinhopping
    
    def runEnvironment(x):
        return x**2
    
    def func(x):
    
        print "x:",x
        pool = mp.Pool(processes=1)
    
        results=pool.apply(runEnvironment,(x,))
        pool.close()
        return results
    
    if __name__ == '__main__':
        x0=5
        ret=basinhopping(func, x0, niter=100, T=1.0, stepsize=0.1, minimizer_kwargs=None, take_step=None, accept_test=None, callback=None, interval=50, disp=False, niter_success=None)
    
  • 1

    仅使用一个工作进程创建许多小 mp.Pool 是低效的 . 每次调用 func 创建一个池也是低效的,因为多次调用 func .

    而是在程序开始时创建一个 Pool ,并将池传递给每次调用 func

    if __name__ == '__main__':
        pool = mp.Pool()
        x0=5    
        ret = optimize.basinhopping(
            func, x0, niter=100, T=1.0, stepsize=0.1,
            minimizer_kwargs=dict(args=pool), 
            take_step=None, accept_test=None, callback=None,
            interval=50, disp=False, niter_success=None)
        pool.close()
        print(ret)
    

    minimizer_kwargs=dict(args=pool) 告诉 optimize.basinhoppingpool 作为 func 的附加参数传递 .


    你也可以使用

    logger = mp.log_to_stderr(logging.INFO)
    

    获取日志语句,显示调用函数的过程 . 例如,

    import multiprocessing as mp
    from scipy import optimize
    import logging
    logger = mp.log_to_stderr(logging.INFO)
    
    def runEnvironment(x):
        logger.info('runEnvironment({}) called'.format(x))
        return x**2
    
    def func(x, pool):
        logger.info('func({}) called'.format(x))
        results = pool.apply(runEnvironment,(x,))
        return results
    
    if __name__ == '__main__':
        pool = mp.Pool()
        x0=5    
        ret = optimize.basinhopping(
            func, x0, niter=100, T=1.0, stepsize=0.1,
            minimizer_kwargs=dict(args=pool), 
            take_step=None, accept_test=None, callback=None,
            interval=50, disp=False, niter_success=None)
        pool.close()
        print(ret)
    

    版画

    [INFO/PoolWorker-1] child process calling self.run()
    [INFO/PoolWorker-2] child process calling self.run()
    [INFO/PoolWorker-3] child process calling self.run()
    [INFO/PoolWorker-4] child process calling self.run()
    [INFO/MainProcess] func([ 5.]) called
    [INFO/PoolWorker-1] runEnvironment([ 5.]) called
    [INFO/MainProcess] func([ 5.00000001]) called
    [INFO/PoolWorker-2] runEnvironment([ 5.00000001]) called
    [INFO/MainProcess] func([ 5.]) called
    [INFO/PoolWorker-3] runEnvironment([ 5.]) called
    [INFO/MainProcess] func([-5.]) called
    [INFO/PoolWorker-4] runEnvironment([-5.]) called
    

    这表明 func 总是由主进程调用,而 runEnvironment 由工作进程运行 .

    请注意,对 func 的调用是按顺序进行的 . 要从 pool 中获得任何好处,每次调用 func 时都需要运行更多处理器 .

相关问题