【问题标题】:Curve fitting in Python with Scipy使用 Scipy 在 Python 中进行曲线拟合
【发布时间】:2020-03-19 02:26:48
【问题描述】:

只是想说明我是一个非常初学者的 Python 程序员。我的大部分知识是我在物理实验室的数据分析/绘图中使用/学到的知识。

我基本上收集了作为温度函数的电容数据,我应该用函数拟合我绘制的数据以找到其最佳参数。

请注意,我为初始值输入了随机数,然后运行了代码。我的POpt 函数为我提供了新的最佳参数,我将其替换为初始随机数

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]

指数函数似乎比我应该建模的方程更适合这个。也许这就是我没有得到最佳参数的原因?

【问题讨论】:

  • 看起来你的曲线拟合为你的参数找到了一个局部最优解并且无法逃脱它。尝试为您的参数提供更好的算法起始值。请参阅有关如何执行此操作的文档docs.scipy.org/doc/scipy/reference/generated/…
  • 我在想是什么导致了这种限制。我以前做过这个曲线拟合,虽然有指数衰减,所以我猜这个程序能够很容易地优化它。那么您是否建议使用试错初始值,然后对其进行优化?因为这看起来很麻烦。
  • 如果您适合不同类型的函数,优化环境可能看起来完全不同,因此有时这些方法可能会失败。您的数据看起来您的拟合参数应该接近:CmaxInit = 6; KInit =0.01; gamma=2;TCInit = 50 尝试将这些作为起点,而不是使用随机的起点并报告结果。您的 gamma 参数似乎很差
  • 它似乎确实有帮助,但现在它无法优化我的价值观。我在上面做了修改。
  • 这是我的实验脚本中给出的方程式。我现在实际上注意到他们确实说要绘制 T>TC(如果你想知道,TC 是“居里温度”),但是这种情况不应该改变我的图表的形状,就在我开始绘制它的地方。

标签: python data-modeling curve-fitting scipy-optimize


【解决方案1】:

拟合函数存在一些数值问题:

  • 算法似乎很难拥有指数 (gamma) 作为拟合参数。这似乎也适用于某些东西 exp(gamma)
  • 我将拟合功能替换为 Cmax*np.exp(-K*(T-TC)**2) + c。这取决于 x 范围 (数据窗口)拟合的好坏。
  • 出于数字原因,截取c 可能会更好。
  • 通过变换将数据带到拟合函数的“简单区域”通常是一个好主意,这样峰值在零附近,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()

..

【讨论】:

  • 我意识到我必须砍掉我的数据,所以我的函数是从T>TC(第三个图)开始建模的,现在这个错误已经消失了。我很困惑为什么我现在在尝试获得最佳参数时会出错。它以前工作正常,现在对于我输入的任何初始值,我都会得到nan。值得一提的是,我的数据中有一个微妙之处。很难注意到,因为这个数据收集运行了大约 30 分钟,但是温度稳定了大约 30 秒的不稳定点(我们做到了)。
  • 我增强了我的回答
  • 我明天会和我的教授谈谈,因为这应该是一个简单的拟合练习,但我理解考虑到参数的数量,拟合会有一些困难。谢谢。
猜你喜欢
  • 2015-09-14
  • 1970-01-01
  • 1970-01-01
  • 2012-04-25
  • 2013-10-10
  • 2021-11-14
  • 2014-09-08
  • 2017-04-21
  • 1970-01-01
相关资源
最近更新 更多