使用曲线拟合的Scipy奇怪的结果

时间:2014-05-16 15:36:13

标签: python scipy mathematical-optimization curve-fitting

当我尝试拟合我的数据时,结果有点奇怪,我不明白为什么?获得的拟合是平坦的,并且第一个输入e = 0。似乎在某处产生了分裂错误。 唯一的工作案例是我修改e [0] = 1.0e-9

结果如下: enter image description here

从示例here来看,我的例子似乎与我所读的内容相差不多,但我仍然陷入困境,所以你能帮我解决一下我的案件出了什么问题吗?

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

src_s = np.array((45.59,50.66664,59.74871,65.71018,72.76012,79.06256,84.13755,90.39944,
                  96.33653,101.65667,106.27968,110.76301,114.41808,117.21922,120.51836))
src_e = np.array((0.0,0.00126,0.00503,0.00804,0.01228,0.01685,0.02127,0.02846,0.03666,
                  0.04581,0.05620,0.06882,0.08005,0.09031,0.10327))
# plot source data
plt.plot(src_e, src_s, 'o')
# fitting function
def sigma(e, k ,n): return k*(e**n)
# find parameters curve fitting
param, var = curve_fit(sigma, src_e, src_s)
new_e = np.linspace(src_e.min(), src_e.max(), 50)
plt.plot(new_e, sigma(new_e, *param))

# modify first input
src_e[0]=1.0e-9
# relaunch parameters curve fitting
param, var = curve_fit(sigma, src_e, src_s)
new_e = np.linspace(src_e.min(), src_e.max(), 50)
plt.plot(new_e, sigma(new_e, *param))

plt.show()

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

问题的根源是参数的初始猜测错误(实际上没有为curve_fit提供启动参数)。

目标函数可以很容易地线性化。让我们这样做,然后进行线性回归以获得curve_fit的一组良好的初始猜测参数(通过p0=传递给它)。得到的拟合更好(具有更少的残留)并且不需要将第一个值替换为1e-9

In [38]:

src_e[0]=1.0e-9
# relaunch parameters curve fitting
param, var = curve_fit(sigma, src_e, src_s)
new_e = np.linspace(src_e.min(), src_e.max(), 50)
src_e[0]=0
plt.plot(new_e, sigma(new_e, *param))
plt.plot(src_e, src_s, 'ro')
plt.savefig('1.png')
print 'Residue is:', ((sigma(src_e, *param)-src_s)**2).sum()
Residue is: 2168.65307587

enter image description here

In [39]:

import scipy.stats as ss
src_e[0]=0
V=ss.linregress(np.log(src_e)[1:], np.log(src_s)[1:]) #avoid log(0)
param, var = curve_fit(sigma, src_e, src_s, p0=(np.exp(V[1]), V[0]))
new_e = np.linspace(src_e.min(), src_e.max(), 50)
plt.plot(new_e, sigma(new_e, *param))
plt.plot(src_e, src_s, 'ro')
plt.savefig('1.png')
print 'Residue is:', ((sigma(src_e, *param)-src_s)**2).sum()
Residue is: 2128.85364181

enter image description here

答案 1 :(得分:0)

第一个点不在曲线上,因此您需要更改曲线公式:

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

src_s = np.array((45.59,50.66664,59.74871,65.71018,72.76012,79.06256,84.13755,90.39944,
                  96.33653,101.65667,106.27968,110.76301,114.41808,117.21922,120.51836))
src_e = np.array((0.0,0.00126,0.00503,0.00804,0.01228,0.01685,0.02127,0.02846,0.03666,
                  0.04581,0.05620,0.06882,0.08005,0.09031,0.10327))
# plot source data
plt.plot(src_e, src_s, 'o')

def sigma(e, k ,n, offset): return k*((e+offset)**n)
# find parameters curve fitting
param, var = curve_fit(sigma, src_e, src_s)
new_e = np.linspace(src_e.min(), src_e.max(), 50)
plt.plot(new_e, sigma(new_e, *param))

这是输出:

enter image description here