使用 Scipy.Optimise Curve_fit 进行指数拟合不起作用

Dav*_*veB 4 python numpy curve-fitting scipy exponential

我正在尝试使用 Scipy.Optimise Curve_fit 按照此处的简单示例对某些数据进行指数拟合。

脚本运行时没有错误,但是拟合很糟糕。当我在 curve_fit 的每一步查看 popt 的输出时,从初始参数跳到一系列 1.0s 似乎并没有很好地迭代,尽管它似乎让第三个参数回到了一个有点像样的值:

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
Run Code Online (Sandbox Code Playgroud)

我不确定是什么导致了这种情况,除了模型可能不太适合数据,尽管我强烈怀疑它应该(物理就是物理)。有人有任何想法吗?我在下面发布了我的(非常简单的)脚本。谢谢。

#!/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()
Run Code Online (Sandbox Code Playgroud)

另外,这是我试图拟合的数据:

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
Run Code Online (Sandbox Code Playgroud)

Sau*_*tro 9

大的负指数使指数函数接近于零,从而使最小二乘算法对您的拟合参数不敏感

因此,在根据时间戳使用指数拟合指数函数时,最好通过排除第一个数据点的时间调整时间指数,将其更改为:

f = exp(-x*t)
Run Code Online (Sandbox Code Playgroud)

到:

t0 = t[0] # place this outside loops
f = exp(-x*(t - t0))
Run Code Online (Sandbox Code Playgroud)

将此概念应用于您的代码会导致:

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')
Run Code Online (Sandbox Code Playgroud)

结果是:

在此处输入图片说明

删除样本的第一点:

在此处输入图片说明