scipy.minimize似乎没有遵守约束。 这是一个简单的例子,其中约束用于防止对数中的负参数,但最小化函数不符合:
import math
from scipy.optimize import minimize
def obj(x,b):
print "obj x",x
return math.log(x-b)
def constr(x,b):
print "constr x",x
return x-b
x=3.1
b=3
a=minimize(obj,x,args=(b),constraints={'type': 'ineq', 'fun':constr,'args':[b]})
输出是:
constr x [ 3.1]
obj x [ 3.1]
constr x [ 3.1]
obj x [ 3.1]
obj x [ 3.10000001]
constr x [ 3.1]
constr x [ 3.10000001]
obj x [ 3.]
Traceback (most recent call last):
File "scipy_minimize_constraints.py", line 19, in
a=minimize(obj,x,args=(b),constraints={'type': 'ineq', 'fun':constr,'args':[b]})
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/_minimize.py", line 495, in minimize
constraints, callback=callback, **options)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/slsqp.py", line 378, in _minimize_slsqp
fx = func(x)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/optimize.py", line 292, in function_wrapper
return function(*(wrapper_args + args))
File "scipy_minimize_constraints.py", line 9, in obj
return math.log(x-b)
ValueError: math domain error
python2.7 Scipy版本1.0.0
我做错了吗?
答案 0 :(得分:2)
约束
SELECT c.table_name, c.column_name
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.column_name IN ('W','X','Y','Z')
ORDER BY c.table_name ASC, c.column_name ASC
结果为def constr(x,b):
return x-b
(非负),但允许x-b >= 0
。如果x-b = 0
,则log(x-b)
未定义。你需要引入一些epsilon,如:
x-b = 0
不会抛出你的错误。
但可能存在一个更重要的问题:我真的不认为求解器(这里的SLSQP)保证它的迭代是可行的!可能会出现问题。在您的简单示例中,要采用的方法是将约束转换为边界。这当然不那么具有表现力(并不总是可行;但对于你的小例子而言),但这些界限在迭代中得到尊重!
eps = 1e-12
def constr(x,b):
return x-b-eps
(当然:不要使用最小化进行单维优化。最小化数量。)
答案 1 :(得分:-1)
我不知道scipy的最小化是如何起作用的,但我认为你没有遵循约束条件是正确的。
如果在obj(x,b)中,我尝试打印x - b,那么当它抛出错误时,我会得到最后一个循环的负输出。
但这并不奇怪。你最小化的函数基本上是log(z),约束为z> 0.这不会很慢收敛......:p编辑:将关键字参数“tol”(误差容差)设置为大约0.1,以便最小化器消除错误(如minimize(..., tol=0.1)
中所示)。我仍然不知道为什么它首先如此重要。