Python 与 Scipy 的曲线拟合
Curve fitting in Python with Scipy
只是想说明一下,我是一个非常初级的 python 程序员。我的大部分知识都是我 use/learned 用于物理实验室的数据 analysis/plotting。
我基本上收集了作为温度函数的电容数据,我应该用函数拟合我绘制的数据以找到其最佳参数。
请注意,我输入了 运行dom 数字作为我的初始值,然后是 运行 代码。我的 POpt
函数给了我新的最佳参数,我用我的初始 运行dom numbers
替换了这些参数
fig, plot = plt.subplots(figsize=(40,40))
def cap(T, Cmax, K, TC, gamma): #this is the function I am fitting to my data
return Cmax/(1+K*(T-TC)**gamma)
CmaxInit = 5.16061523 #these are the optimal parameters it gave me
KInit = 3.87292298e-05
TCInit = 3.00020150e+01
gammaInit = 2.74812849
fmodel = np.linspace(0, 100, 1000)
plt.plot(fmodel, cap(fmodel, CmaxInit, KInit, TCInit, gammaInit), linewidth=8, label='Fitted model')
plot.errorbar(temperature, capacitance, linewidth=8, label='Data Points') #this is my data of temperature vs capacitance
pOpt, pCov = curve_fit(cap, temperature, capacitance, p0=[CmaxInit, KInit, TCInit, gammaInit], absolute_sigma=True) #this is what I use to curve-fit/get my optimal parameters
print("[CmaxOpt KOpt TCOpt gammaOpt] =", pOpt)
print()
print("pCov =") #This is a co-variant matrix function that calculates my error values
print(pCov)
plt.xticks(fontsize=60)
plt.yticks(fontsize=60)
plt.grid()
plt.legend(fontsize=80)
plt.show()
然而,在绘制我的拟合模型时,它给了我:
作为温度函数的电容
POpt
功能确实有点符合一般外观,但显然有很大差距。我不明白为什么,但我的猜测是我要优化的参数数量。
编辑:将初始参数更改为
CmaxInit = 6
KInit = 0.01
TCInit = 50
gammaInit = 2
生成了更准确的
但是现在在计算最优参数的时候出现了错误
[CmaxOpt KOpt TCOpt gammaOpt] = [nan nan nan nan]
编辑 2:砍掉我的数据后,我现在正试图适应
但是我仍然得到
[CmaxOpt KOpt TCOpt gammaOpt] = [nan nan nan nan]
指数函数似乎比我应该建模的方程更适合这个。也许这就是我没有获得最佳参数的原因?
拟合函数存在一些数值问题:
- 算法有指数(gamma)好像太难了
作为拟合参数。这似乎也适用于某些东西
exp(gamma)
- 我将拟合函数替换为
Cmax*np.exp(-K*(T-TC)**2) + c
。这取决于 x 范围
(data window) 拟合度如何。
- 出于数值原因,截距
c
可能更好。
- 将数据转换为拟合函数的 "an easy region" 通常是个好主意,这样峰值就在零附近,x 范围在 [-5..+5 附近].拟合后将结果转换回原始数据范围。
- 安装(数据)的日志(数据)有时也有帮助。
...
def cap(T, Cmax, K, TC, gamma):
return Cmax/(1+K*(T-TC)**gamma)
def func_1(T, Cmax, K, TC, c):
return Cmax*np.exp(-K*(T-TC)**2) + c
#--- generate data --------------------
CmaxInit = 5.0 # 5.16061523
KInit = 3.0e-3 # 3.87292298e-05
TCInit = 30.0 # 3.00020150e+01
gammaInit = 2.0 # 2.74812849
cInit = 0.0 # intercept
fmodel = np.linspace(20, 50, 280)
x0 = fmodel.copy()
y0 = cap (x0, CmaxInit, KInit, TCInit, gammaInit)
y1 = func_1(x0, CmaxInit, KInit, TCInit, cInit)
y_noise = 0.05 * np.random.normal(size=x0.size)
Y0 = y0 + y_noise
Y1 = y1 + y_noise
#--- fit the data by a function ------------
pOpt, pCov = curve_fit(func_1, x0, Y0, p0=[CmaxInit, KInit, TCInit, cInit], absolute_sigma=True)
Yfit = func_1(x0, *pOpt)
#--- print the results ---------------------------
print("CmaxInit, KInit, TCInit, c", CmaxInit, KInit, TCInit, c)
print("[CmaxOpt KOpt TCOpt cOpt] =", pOpt); print()
print("pCov ="); print(pCov)
#---- graphics --------------------------------------------
fig, plot = plt.subplots(figsize=(12, 12))
plt.plot(x0, Y0, linewidth=2, label='simulated data with CAP')
plt.plot(x0, Y1, ls=':', lw=1,label='simulated data with EXP')
plt.plot(x0, Yfit, label='Yfit: Cmax=%5.3f, K=%5.3f, TC=%5.3f, c=%5.3f' % tuple(pOpt))
plt.legend(); plt.savefig('pic3.jpg'); plt.show()
..
只是想说明一下,我是一个非常初级的 python 程序员。我的大部分知识都是我 use/learned 用于物理实验室的数据 analysis/plotting。
我基本上收集了作为温度函数的电容数据,我应该用函数拟合我绘制的数据以找到其最佳参数。
请注意,我输入了 运行dom 数字作为我的初始值,然后是 运行 代码。我的 POpt
函数给了我新的最佳参数,我用我的初始 运行dom numbers
fig, plot = plt.subplots(figsize=(40,40))
def cap(T, Cmax, K, TC, gamma): #this is the function I am fitting to my data
return Cmax/(1+K*(T-TC)**gamma)
CmaxInit = 5.16061523 #these are the optimal parameters it gave me
KInit = 3.87292298e-05
TCInit = 3.00020150e+01
gammaInit = 2.74812849
fmodel = np.linspace(0, 100, 1000)
plt.plot(fmodel, cap(fmodel, CmaxInit, KInit, TCInit, gammaInit), linewidth=8, label='Fitted model')
plot.errorbar(temperature, capacitance, linewidth=8, label='Data Points') #this is my data of temperature vs capacitance
pOpt, pCov = curve_fit(cap, temperature, capacitance, p0=[CmaxInit, KInit, TCInit, gammaInit], absolute_sigma=True) #this is what I use to curve-fit/get my optimal parameters
print("[CmaxOpt KOpt TCOpt gammaOpt] =", pOpt)
print()
print("pCov =") #This is a co-variant matrix function that calculates my error values
print(pCov)
plt.xticks(fontsize=60)
plt.yticks(fontsize=60)
plt.grid()
plt.legend(fontsize=80)
plt.show()
然而,在绘制我的拟合模型时,它给了我:
作为温度函数的电容
POpt
功能确实有点符合一般外观,但显然有很大差距。我不明白为什么,但我的猜测是我要优化的参数数量。
编辑:将初始参数更改为
CmaxInit = 6
KInit = 0.01
TCInit = 50
gammaInit = 2
生成了更准确的
但是现在在计算最优参数的时候出现了错误
[CmaxOpt KOpt TCOpt gammaOpt] = [nan nan nan nan]
编辑 2:砍掉我的数据后,我现在正试图适应
但是我仍然得到
[CmaxOpt KOpt TCOpt gammaOpt] = [nan nan nan nan]
指数函数似乎比我应该建模的方程更适合这个。也许这就是我没有获得最佳参数的原因?
拟合函数存在一些数值问题:
- 算法有指数(gamma)好像太难了
作为拟合参数。这似乎也适用于某些东西
exp(gamma)
- 我将拟合函数替换为
Cmax*np.exp(-K*(T-TC)**2) + c
。这取决于 x 范围 (data window) 拟合度如何。 - 出于数值原因,截距
c
可能更好。 - 将数据转换为拟合函数的 "an easy region" 通常是个好主意,这样峰值就在零附近,x 范围在 [-5..+5 附近].拟合后将结果转换回原始数据范围。
- 安装(数据)的日志(数据)有时也有帮助。
...
def cap(T, Cmax, K, TC, gamma):
return Cmax/(1+K*(T-TC)**gamma)
def func_1(T, Cmax, K, TC, c):
return Cmax*np.exp(-K*(T-TC)**2) + c
#--- generate data --------------------
CmaxInit = 5.0 # 5.16061523
KInit = 3.0e-3 # 3.87292298e-05
TCInit = 30.0 # 3.00020150e+01
gammaInit = 2.0 # 2.74812849
cInit = 0.0 # intercept
fmodel = np.linspace(20, 50, 280)
x0 = fmodel.copy()
y0 = cap (x0, CmaxInit, KInit, TCInit, gammaInit)
y1 = func_1(x0, CmaxInit, KInit, TCInit, cInit)
y_noise = 0.05 * np.random.normal(size=x0.size)
Y0 = y0 + y_noise
Y1 = y1 + y_noise
#--- fit the data by a function ------------
pOpt, pCov = curve_fit(func_1, x0, Y0, p0=[CmaxInit, KInit, TCInit, cInit], absolute_sigma=True)
Yfit = func_1(x0, *pOpt)
#--- print the results ---------------------------
print("CmaxInit, KInit, TCInit, c", CmaxInit, KInit, TCInit, c)
print("[CmaxOpt KOpt TCOpt cOpt] =", pOpt); print()
print("pCov ="); print(pCov)
#---- graphics --------------------------------------------
fig, plot = plt.subplots(figsize=(12, 12))
plt.plot(x0, Y0, linewidth=2, label='simulated data with CAP')
plt.plot(x0, Y1, ls=':', lw=1,label='simulated data with EXP')
plt.plot(x0, Yfit, label='Yfit: Cmax=%5.3f, K=%5.3f, TC=%5.3f, c=%5.3f' % tuple(pOpt))
plt.legend(); plt.savefig('pic3.jpg'); plt.show()
..