当我试图找到最适合我的数据时,我遇到了问题。使用 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()
像那样。当我运行代码时,我正在适应:
但是,应该大致相同:
谁能告诉我哪里出错了?我是曲线拟合的初学者。
答案 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
初始估算值。
...然后使用您选择的软件计算简单的线性回归。在这里,我使用 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的估计存在相当大的不确定性。
我还没有成功地使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越小。但我认为这会使合适的模型拥抱'如你所见,水平轴。