拟合分段线性函数时的曲线拟合优化误差

时间:2017-07-13 21:59:35

标签: python scipy curve-fitting piecewise

我在两个数组中有一些数据,似乎有一个中断。我希望我的代码在scipy中使用分段来确定中断的位置。这就是我所拥有的:

from scipy import optimize
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

x = np.array([7228,7620,7730,7901,8139,8370,8448,8737,8824,9089,9233,9321,9509,9568,9642,9756,9915,10601,10942], dtype=np.float)
y= np.array([.874,.893,.8905,.8916,.9095,.9142,.9109,.9185,.9169,.9251,.9290,.9304,.9467,.9378,0.9464,0.9508,0.9583,0.9857,0.9975],dtype=np.float)

def piecewise_linear(x, x0, y0, k1, k2):
    return np.piecewise(x, [x < x0], [lambda x:k1*x + y0-k1*x0, lambda x:k2*x + y0-k2*x0])

p , e = optimize.curve_fit(piecewise_linear, x, y)
perr = np.sqrt(np.diag(e))
xd = np.linspace(7228, 11000, 3000)
plt.plot(x, y, "o")
plt.plot(xd, piecewise_linear(xd, *p))

我的问题是,如果我运行此操作,我会收到错误,&#34; OptimizeWarning:无法估计参数的协方差   类别= OptimizeWarning)&#34 ;.不知道怎么解决这个问题?有没有办法将初始参数输入到此函数中以帮助它收敛或类似?

注意,我确实意识到我可以通过插值和查找数据的二阶导数来实现其他方法。我已经完成了这项工作,但由于我的数据间距不均匀/ y轴数据有误差,我有兴趣让它以这种方式工作以用于统计目的。所以,要清楚,我想要的是两条线的参数(斜率/截距)和拐点。 (理想情况下,我也希望在这些方面也能得到错误,但不确定这种方法是否可行。)提前感谢!

2 个答案:

答案 0 :(得分:2)

代码完全正常,只有初始值导致问题。

默认情况下,curve_fit以所有参数设置为1开头。因此,x0开始超出数据中x的范围,优化程序无法计算合理的渐变。 这个小修改将解决问题:

# make sure initial x0 and y0 are in range of the data
p0 = [np.mean(x), np.mean(y), 1, 1]

p , e = optimize.curve_fit(piecewise_linear, x, y, p0)  # set initial parameter estimates
perr = np.sqrt(np.diag(e))
xd = np.linspace(7228, 11000, 3000)
plt.plot(x, y, "o")
plt.plot(xd, piecewise_linear(xd, *p))

print(p)  # [  9.32099947e+03   9.32965835e-01   2.58225121e-05   4.05400820e-05]
print(np.diag(e))  # [  4.56978067e+04   5.52060368e-05   3.88418404e-12   7.05010755e-12]

enter image description here

答案 1 :(得分:0)

可能您的软件使用从初始猜测开始的迭代方法。通常,最初的猜测是这些方法的弱点。

如果您想克服这种困难,请使用不需要初始猜测的非迭代方法。如果非迭代方法的拟合标准对您不方便,那么首先使用非迭代方法来获得第一解。然后使用经典的迭代方法,从首先找到的解决方案开始。

例如,由于非常简单的算法(不是迭代,没有初始猜测)而得到了下一个结果,该文件在论文中给出了第12-13页:https://fr.scribd.com/document/380941024/Regression-par-morceaux-Piecewise-Regression-pdf

enter image description here