Python:使用sigma = 0的scipy.optimize.curve_fit进行数据拟合

时间:2017-01-16 17:38:28

标签: python-2.7 optimization scipy curve-fitting nonlinear-optimization

我试图使用scipy.optimize.curve_fit来拟合曲线,到目前为止它的效果非常好,除非我的sigma数组中的值为零。我知道算法无法解决这个问题,因为在这种情况下我除以零。从scipy文档:

sigma :无或M长度序列,可选 如果不是None,则是ydata数组中的不确定性。这些在最小二乘问题中用作权重,即最小化np.sum(((f(xdata,* popt) - ydata)/ sigma)** 2)如果为None,则假设不确定性为1.

这是我的代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

x = [0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875, 2.125, 2.375, 2.625, 2.875, 3.125, 3.375, 3.625, 3.875, 4.125, 4.375]
y_para = [0, 0, 0.0414, 0.2164, 0.2616, 0.4254, 0.5698, 0.5921, 0.6286, 0.6452, 0.5879, 0.6032, 0.6667, 0.6325, 0.7629, 0.7164, 0.7091, 0.7887]
err = [0, 0, 0.0391, 0.0331, 0.0943, 0.0631, 0.1219, 0.1063, 0.0912, 0.0516, 0.0365, 0.0327, 0.0227, 0.103, 0.1344, 0.0697, 0.0114, 0.0465]   

def logistic_growth(x, A1, A2, x_0, p):
    return A2 + (A1-A2)/(1+(x/x_0)**p)

x_plot = np.linspace(0, 4.5, 100)

bounds_para = ([0.,0,-np.inf,-np.inf],[0.0000000001, 1,np.inf,np.inf])

paras, paras_cov = curve_fit(logistic_growth, x, y_para, bounds = bounds_para, sigma = err, absolute_sigma=True)
para_curve = logistic_growth(x_plot, *paras)

plt.figure()
plt.errorbar(x,y_para, err, color = 'b', fmt = 'o', label = "Data")
plt.plot(x_plot, para_curve, color = 'b', label = "Fit")    
plt.show()

在curve_fit中没有sigma-option的情况下执行此工作正常,但包含它会引发:

ValueError: Residuals are not finite in the initial point.

,它来自err-array中的零。 有没有人知道解决这个问题的方法?

2 个答案:

答案 0 :(得分:1)

为什么不放弃变量?如果它的方差为零,则无法以任何有意义的方式为您的分析做出贡献。

答案 1 :(得分:1)

这是 scipy doc关于 curve_fit sigma 参数的说法:'这些用作最小二乘问题中的权重。 ..然后,在我看来,他们应该与错误相反。这就是我的建议。

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

x = [0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875, 2.125, 2.375, 2.625, 2.875, 3.125, 3.375, 3.625, 3.875, 4.125, 4.375]
y_para = [0, 0, 0.0414, 0.2164, 0.2616, 0.4254, 0.5698, 0.5921, 0.6286, 0.6452, 0.5879, 0.6032, 0.6667, 0.6325, 0.7629, 0.7164, 0.7091, 0.7887]
err = [0, 0, 0.0391, 0.0331, 0.0943, 0.0631, 0.1219, 0.1063, 0.0912, 0.0516, 0.0365, 0.0327, 0.0227, 0.103, 0.1344, 0.0697, 0.0114, 0.0465]   

weights = [1/max(_,0.001) for _ in err]
print (weights)

def logistic_growth(x, A1, A2, x_0, p):
    return A2 + (A1-A2)/(1+(x/x_0)**p)

x_plot = np.linspace(0, 4.5, 100)

bounds_para = ([0.,0,-np.inf,-np.inf],[0.0000000001, 1,np.inf,np.inf])

paras, paras_cov = curve_fit(logistic_growth, x, y_para, bounds = bounds_para, 
    absolute_sigma=True,
    sigma = weights)
para_curve = logistic_growth(x_plot, *paras)

plt.figure()
plt.errorbar(x,y_para, err, color = 'b', fmt = 'o', label = "Data")
plt.plot(x_plot, para_curve, color = 'b', label = "Fit")    
plt.show()

这导致下图,其中这些初始数据点非常接近拟合线。

resulting plot