出于某种目的,在我的代码中,我想猜测五次多项式,它最适合我的数据,并且在某些点上是不减分的。在
示例代码为:
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
白蚁成功,而{
问题显然在initial guess
中的optimize.minimize
。我认为这个猜测的参数必须符合我的限制。但在这里,最初的猜测[1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
遇到了我的缺点。谁能解释一下,问题在哪里?在
是的,你的初始点满足约束条件。但是SLSQP使用线性化的约束,并且正在寻找一个与所有线性化(described here)兼容的搜索方向。它们可能最终要么不兼容,要么兼容性差,因为只有很小范围的方向符合条件,而搜索无法找到它们。在
起点[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的正方向导数”)。在所以总结是:优化问题的伸缩性很差,使得搜索变得困难;错误信息对于实际出错的地方并不是很明确。在
除了改变初始点,你可以尝试提供目标函数和约束的雅可比(两者都很重要,因为该方法使用拉格朗日函数)。在
相关问题 更多 >
编程相关推荐