衰减曲线最适合SciPy

时间:2017-01-16 13:46:36

标签: python scipy curve-fitting best-fit-curve

当我试图找到最适合我的数据时,我遇到了问题。使用 scipy.optimize.curve_fit 创建最佳匹配。我的数据和代码是:

编辑您可以从here下载数据文件。 数据是,

         a             b            b2
55478   1.07E+43    54395.93833 
56333   1.63E+43    54380.01385 
57540   2.57E+43    52393.31605 
61866   7.32E+43    52212.22838 52212.22838

代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-


from __future__ import division

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import fit
import glob
import os
from scipy.optimize import curve_fit
import matplotlib.patches as patches

pf = pd.read_csv('/home/imhotep/Desktop/lala.csv', sep=',', encoding ='utf-8')



a1= pf['a'].max()
b1 = pf['b2'].max()
npoc=100

x = np.linspace((b1), (pf['b'].max()),npoc)
yy = np.linspace((pf['a'].min()), (pf['a'].max()), npoc)


fig = plt.figure()

ax4 = fig.add_subplot(111)

def h(x,k):
    return a1* (((x-(b1))/(k))**(-(5./3.)))


popt,pcov = curve_fit(h,x,yy)

print 'POPT,', popt,'PCOV',pcov
y_fi1 = h(x, *popt)

ax4.plot(x, y_fi1, label='fit', ls='-', color='blue')

ax4.plot(pf['b'], pf['a'], ls='None', color='blue', marker='o')

plt.show()
像那样。当我运行代码时,我正在适应: fit

但是,应该大致相同:

fitted

谁能告诉我哪里出错了?我是曲线拟合的初学者。

3 个答案:

答案 0 :(得分:2)

您想要将模型拟合到a和b所描述的4个蓝点吗?

你应该朝这个方向努力:

popt,pcov = curve_fit(h,b,a)

修改

如问题和本答案的评论中所述,您应该仅对原始数据使用fit函数,然后使用np.linspace使用新创建的数组来显示拟合。

以下是我从您的代码中获得的内容:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import division

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

pf = pd.read_csv('lala.csv', sep=',', encoding ='utf-8')

a1 = pf['a'].max()
#b1 = pf['b2'].max()

x = pf["b"]
y = pf["a"]

def h(x,k,b1):
    return a1*((x-b1)/k)**(-5/3)

popt,pcov = curve_fit(h,x,y)

print 'POPT,', popt,'PCOV',pcov

xfit = np.linspace(x.min(),x.max(),100)
y_fi1 = h(xfit, *popt)

fig = plt.figure()
ax4 = fig.add_subplot(111)
ax4.plot(xfit, y_fi1, label='fit', ls='-', color='blue')
ax4.plot(x, y, ls='None', color='blue', marker='o')
plt.show()

使用curve_fit仅查找参数k会导致错误,因此我将b1作为搜索参数包含在内。然后它确实找到了合适,但仍然不能完全满足。 输出:

POPT, [   238.09666313  51973.04601693] 
PCOV [[ 21500.32886377 -22370.88448044] [-22370.88448044  23850.34961769]]

答案 1 :(得分:0)

您可以尝试通过首先以老式的方式线性化您的等式来获得更好的k初始估算值。

Linearised form

...然后使用您选择的软件计算简单的线性回归。在这里,我使用 statsmodels 来获得0.0007的1 / k,这意味着初始估计约为1400,用于 curve_fit

import pandas as pd
import statsmodels.formula.api as smf
import statsmodels.api as sm
import matplotlib.pyplot as plt

df = pd.read_csv('lala.csv')
time_min = min(df.time)
luminosity_max = max(df.luminosity)
df['Y'] = (df.luminosity/luminosity_max)**(-0.6)
results = smf.ols('Y ~ time', data=df).fit()
print (results.summary())
fig, ax = plt.subplots()
fig = sm.graphics.plot_fit(results, 1, ax=ax)
plt.show()

从这段代码产生的图中的误差条来看,很明显(如果不是这样),这个k的估计存在相当大的不确定性。

linearised regression plot

我还没有成功地使curve_fit工作。但是,您可能对要优化的函数的此修改感兴趣。重命名csv中的列后(这样变量对我来说就不那么混乱了)我用这种方式重写了主代码。我发现1400左右的 h 的值首次给出 nan 。我决定用最大亮度来替换这些 nan 。如果你运行这个我认为你会发现 k = 700 给出了最好(粗略)的适合性。

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

df = pd.read_csv('lala.csv')
print (df)

luminosities = df.luminosity
times = df.time

luminosity_max= max(luminosities)
time_min = min(times)

def h(time,k):
    result = luminosity_max*((time-time_min)/k)**(-5./3.)
    if np.isnan(result):
        result = luminosity_max
    return result

for time in range(52000,56000,1000):
    print (time, h(time,2800), h(time,1400),h(time,700))

#~ popt,pcov = curve_fit(h,times,luminosities,700)
#~ print ('POPT,', popt,'PCOV',pcov)

答案 2 :(得分:0)

我不认为你在使用curve_fit做错了什么。我怀疑数学模型非常适合这些数据。这就是原因。我运行以下代码来计算 k 的各种值的最小二乘误差。

   dummy1  luminosity          time       dummy2
0   55478    1.066349  54395.938333          NaN
1   56333    1.630938  54380.013854          NaN
2   57540    2.569603  52393.316048          NaN
3   61866    7.324060  52212.228380  52212.22838
10 263.810260704
20 4431.42454446
30 18991.1298817
40 51557.4862318
50 110648.507655
60 205525.705606
70 346090.508811
80 542810.685895
90 806664.876933
100 1149099.00104

结果:

System.IO.IOException

我注意到, k 的值越小,LSE越小。但我认为这会使合适的模型拥抱'如你所见,水平轴。