出于某种目的,在我的部分代码中,我想猜测5度的多项式,最适合我的数据并且在某些点上不会减少。
示例代码为:
import numpy as np
import scipy.optimize as optimize
def make_const(points):
constr = []
for point in points:
c = {'type' : 'ineq', 'fun' : der, 'args' : (point,)}
constr.append(c)
return constr
def der(args_pol, bod):
a, b, c, d, e, f = args_pol
return (5*a*bod**4 + 4*b*bod**3 + 3*c*bod**2 + 2*d*bod + e)
def squares(args_pol, x, y):
a, b, c, d, e, f = args_pol
return ((y-(a*x**5 + b*x**4 + c*x**3 + d*x**2 + e*x + f))**2).sum()
def ecdf(arr):
arr = np.array(arr)
F = [len(arr[arr<=t]) / len(arr) for t in arr]
return np.array(F)
pH = np.array([8,8,8,7,7,7,7,7,7,7,7,6,3,2,2,2,1])
pH = np.sort(pH)
e = ecdf(pH)
ppoints = [ 1., 2.75, 4.5, 6.25, 8. ]
constraints1 = make_const(ppoints)
p1 = optimize.minimize(squares, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
method = 'SLSQP', args = (pH, e), constraints = constraints1)
p2 = optimize.minimize(squares, [-1.0, -1.0, -1.0, -1.0, -1.0, -1.0],
method = 'SLSQP', args = (pH, e), constraints = constraints1)
此处p1
无法优化,p2
成功终止。另外,如果我没有约束,那么ppoints = []
,p1
白蚁在p2
失败时成功。优化失败的消息始终是:
'Inequality constraints incompatible'
问题显然在initial guess
的{{1}}中。我认为那个猜测的参数必须符合我的约束。但在这里,初步猜测optimize.minimize
符合我的同意。任何人都可以解释一下,问题在哪里?
答案 0 :(得分:3)
是的,您的初始点满足约束条件。但是SLSQP使用线性化约束,并且正在寻找与所有线性化(described here)兼容的搜索方向。这些可能最终会导致不兼容或兼容性差,因为只有极小范围的方向符合条件,搜索无法找到它们。
起点[1,1,1,1,1,1]不是好的。考虑到在x = 8时,前导系数1对多项式的贡献是8**5
,并且因为它在目标函数中得到平方,所以得到8**10
。这使得低阶系数的贡献相形见绌,这对于满足接近0的点处的约束是重要的。因此当初始点是全1时,该算法呈现出严重缩放的问题。
使用np.zeros((6, ))
作为起点是一个更好的主意;搜索从那里成功。将初始点缩放为[7**(d-5) for d in range(6)]
也可以,但只是勉强(用6或8代替7会产生另一种错误,“linesearch的正方向导数”)。
所以摘要是:优化问题缩放不良,使搜索变得困难;并且错误信息不是很清楚实际出错的地方。
除了改变初始点之外,你可以尝试提供目标函数和约束的雅可比行列式(两者都很重要,因为该方法适用于拉格朗日算法)。