在python中优化令人讨厌的函数 - 错误

时间:2014-03-15 01:40:12

标签: python python-2.7 scipy minimize

我试图最小化三个变量的函数,非线性,非常大和讨厌。它在Matlab中工作得很好,但我试图转移到python(作为学习经验和更多自由)。无论如何,它确实适用于最小化功能Nelder-Mead'但它给了我一个没有意义的输出,所以我试图添加到我的变量的边界。

以下是代码:

bnds = ((0, 1), (0, 1), (0, 1))
x0 = [0.004, 0.1, 0.1]
res = minimize(myObjFun, x0, method='L-BFGS-B', bounds=bnds)
print(res)

Matlab的输出给了我最小化函数的三个值:[0.2182,0.0684,0.0048],而python中的Nelder-Mead给出了一些完全不同的东西,超出了我想要的范围(应该在0和0之间) 1)。

这是错误:

File "****/fixedpoints.py", line 45, in <module>
    res = minimize(myObjFun, x0, method='L-BFGS-B', bounds=bnds)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/_minimize.py", line 380, in minimize
callback=callback, **options)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/lbfgsb.py", line 304, in _minimize_lbfgsb
isave, dsave)
TypeError: _lbfgsb.setulb() 6th argument (f) can't be converted to double

1 个答案:

答案 0 :(得分:1)

我们无法调试,除非您提供myObjFun或类似的功能(基于更简单或伪造的数据)在优化期间具有类似行为。更具体地说,您的代码将适用于表现良好的myObjFun;如,

>>> import scipy.optimize
>>> def myObjFun(x):
        return (x[0]-.2182)**4 + (x[1]-.0684)**2 + 5*(x[2]-.0048)**2 + 3.2
>>> print scipy.optimize.minimize(myObjFun, [0.004,0.1,0.1], method='L-BFGS-B', bounds=((0,1),(0,1),(0,1)))
  status: 0
 success: True
    nfev: 18
     fun: 3.200000001787815
       x: array([ 0.21213686,  0.06837957,  0.00480194])
 message: 'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'
     jac: array([ -8.88178420e-07,  -4.08562073e-05,   1.94511074e-05])
     nit: 17

现在,setulb的参数f包含目标函数的当前值,因为正在评估函数[1]

   f is a double precision variable.
 On first entry f is unspecified.
 On final exit f is the value of the function at x.

因此,在搜索空间的某个点上计算的目标函数的值似乎无意中因某种原因而不可转换(这似乎是一个TypeError)。

我可以得到一个类似的错误(但实际上是一个OverflowError)说这个目标函数,它通常表现良好,但只要x[1] < 0.0685(应该在找到最小值之前发生)就会爆炸:

>>> def myObjFun(x):                                                                                       
        return (x[0]-.2182)**4 + (x[1]-.0684)**2 + 5*(x[2]-.0048)**2 + 3.2 if x[1] > 0.0684 else 10**999
   ....: 

>>> print scipy.optimize.minimize(myObjFun, [0.004,0.1,0.1], method='L-BFGS-B', bounds=((0,1),(0,1),(0,1)))
---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
<ipython-input-44-9204b704b51a> in <module>()
----> 1 print scipy.optimize.minimize(myObjFun, [0.004,0.1,0.1], method='L-BFGS-B', bounds=((0,1),(0,1),(0,1)))

lib/python2.7/site-packages/scipy/optimize/_minimize.pyc in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
    376     elif meth == 'l-bfgs-b':
    377         return _minimize_lbfgsb(fun, x0, args, jac, bounds,
--> 378                                 callback=callback, **options)
    379     elif meth == 'tnc':
    380         return _minimize_tnc(fun, x0, args, jac, bounds, callback=callback,

lib/python2.7/site-packages/scipy/optimize/lbfgsb.pyc in _minimize_lbfgsb(fun, x0, args, jac, bounds, disp, maxcor, ftol, gtol, eps, maxfun, maxiter, iprint, callback, **unknown_options)
    302         _lbfgsb.setulb(m, x, low_bnd, upper_bnd, nbd, f, g, factr,
    303                        pgtol, wa, iwa, task, iprint, csave, lsave,
--> 304                        isave, dsave)
    305         task_str = task.tostring()
    306         if task_str.startswith(b'FG'):

OverflowError: _lbfgsb.setulb() 6th argument (f) can't be converted to double

所以我仔细检查你的myObjFun并在搜索域中的许多点手动评估它,看看返回的值是否合理且类型正确,并匹配matlab返回的内容。