我正在尝试使用 Scipy.Optimise Curve_fit 在简单示例 here 之后对某些数据进行指数拟合。
脚本运行时没有错误,但是拟合很糟糕。当我在 curve_fit 的每一步查看 popt 的输出时,它似乎并没有很好地从初始参数跳转到一系列 1.0 的迭代,尽管它似乎使第三个参数回到了一个有点不错的值:
92.0 0.01 28.0
1.0 1.0 1.0
1.0 1.0 1.0
1.0 1.0 1.0
1.00012207031 1.0 1.0
1.0 1.00012207031 1.0
1.0 1.0 1.00012207031
1.0 1.0 44.3112882656
1.00012207031 1.0 44.3112882656
1.0 1.00012207031 44.3112882656
1.0 1.0 44.3166973584
1.0 1.0 44.3112896048
1.0 1.0 44.3112882656
我不确定是什么导致了这种情况,除了模型可能不太适合数据,尽管我强烈怀疑它应该(物理就是物理)。有人有任何想法吗?我在下面发布了我的(非常简单的)脚本。谢谢。
#!/usr/bin/python
import matplotlib.pyplot as plt
import os
import numpy as np
from scipy.optimize import curve_fit
from matplotlib.ticker import*
from glob import glob
from matplotlib.backends.backend_pdf import PdfPages
import fileinput
path_src=os.getcwd()
dirlist= glob(path_src + '/Gel_Temp_Res.txt')
dirlist.sort()
plots_file='Temp_Curve.pdf'
plots= PdfPages(path_src+'/'+plots_file)
time=[]
temp=[]
for row in fileinput.input(path_src + '/Gel_Temp_Res.txt'):
time.append(row.split()[0])
temp.append(row.split()[1])
nptime=np.array(time, dtype='f')
nptemp=np.array(temp, dtype='f')
del time[:]
del temp[:]
# Newton cooling law fitting
def TEMP_FIT(t, T0, k, Troom):
print T0, k, Troom
return T0 * np.exp(-k*t) + Troom
y = TEMP_FIT(nptime[41:], nptemp[41]-nptemp[0], 1e-2, nptemp[0])
yn = y + 0.2*np.random.normal(size=len(nptime[41:]))
popt, pcov = curve_fit(TEMP_FIT, nptime[41:], yn)
# Plotting
ax1 = plt.subplot2grid((1,1),(0, 0))
ax1.set_position([0.1,0.1,0.6,0.8])
plt.plot(nptime[41:], nptemp[41:], 'bo--',label='Heater off', alpha=0.5)
plt.plot(nptime[41:], TEMP_FIT(nptime[41:], *popt), label='Newton Cooling Law Fit')
plt.xlim(-25, 250)
plt.xlabel('Time (min)')
plt.ylabel('Temperature ($^\circ$C)')
ax1.grid(True, which='both', axis='both')
plt.legend(numpoints=1, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.savefig(plots, format='pdf',orientation='landscape')
plt.close()
plots.close()
另外,这是我试图拟合的数据:
100 124
130 120
135 112
140 105
145 99
150 92
155 82
160 75
165 70
170 65
175 60
180 56
185 55
190 52
195 49
200 45
205 44
210 40
215 39
220 37
225 35
最佳答案
大的负指数 使指数函数接近于零,从而使最小二乘算法 对您的拟合参数 不敏感。
因此,在根据时间戳使用指数拟合指数函数时,最好是通过排除第一个数据点 的时间来调整时间指数 ,将其更改为:f = exp(-x*t)
至:t0 = t[0] # place this outside loops
f = exp(-x*(t - t0))
将此概念应用于您的代码会导致:import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
time, temp = np.loadtxt('test.txt', unpack=True)
t0 = time[0]
# Newton cooling law fitting
def TEMP_FIT(t, T0, k, Troom):
print(T0, k, Troom)
return T0 * np.exp(-k*(t - t0)) + Troom
popt, pcov = curve_fit(TEMP_FIT, time, temp)
# Plotting
plt.figure()
plt.plot(time, temp, 'bo--',label='Heater off', alpha=0.5)
plt.plot(time, TEMP_FIT(time, *popt), label='Newton Cooling Law Fit')
plt.xlim(-25, 250)
plt.xlabel('Time (min)')
plt.ylabel('Temperature ($^\circ$C)')
ax = plt.gca()
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.legend(fontsize=8)
plt.savefig('test.png', bbox_inches='tight')
结果是:
删除样本的第一点:
关于python - 使用 Scipy.Optimise Curve_fit 进行指数拟合不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23081913/