优化Python中的复杂函数 - 错误
我正在尝试最小化一个有三个变量的函数,这个函数是非线性的,而且非常复杂。它在Matlab中运行得很好,但我想转到Python上(因为这是一个学习的机会,而且能让我有更多的自由)。总之,使用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到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 个回答
2
我们无法调试,除非你给我们提供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.
所以,在搜索空间的某个点计算出的目标函数值似乎因为某种原因无法转换为浮点数(这似乎是个类型错误)。
我也能遇到类似的错误(实际上是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返回的结果是否一致。