有没有办法从scipy.stats.norm.fit中获取参数的拟合错误?

时间:2018-03-06 12:01:00

标签: python statistics curve-fitting gaussian data-fitting

我有一些数据符合正态分布,使用scipy.stats.normal对象适合函数,如下所示:

import numpy as np                                                                                                                                                                                                                       
import matplotlib.pyplot as plt                                                                                                                                                                                                          
from scipy.stats import norm                                                                                                                                                                                                             
import matplotlib.mlab as mlab                                                                                                                                                                                                           

x = np.random.normal(size=50000)                                                                                                                                                                                                         

fig, ax = plt.subplots()                                                                                                                                                                                                                 

nbins = 75                                                                                                                                                                                                                               
mu, sigma = norm.fit(x)                                                                                                                                                                                                                  
n, bins, patches = ax.hist(x,nbins,normed=1,facecolor = 'grey', alpha = 0.5, label='before');                                                                                                                                            
y0 = mlab.normpdf(bins, mu, sigma) # Line of best fit                                                                                                                                                                                    
ax.plot(bins,y0,'k--',linewidth = 2, label='fit before')                                                                                                                                                                                 
ax.set_title('$\mu$={}, $\sigma$={}'.format(mu, sigma))                                                                                                                                                                                  

plt.show()                                                                                                                                                                                                                               

我现在想要提取拟合mu和sigma值的不确定性/误差。我怎么能这样做?

2 个答案:

答案 0 :(得分:6)

您可以使用scipy.optimize.curve_fit: 该方法不仅返回估计的最优值 参数,还有相应的协方差矩阵:

  

popt:array

     

参数的最佳值,以便残差平方和       f(xdata,* popt) - ydata最小化

     

pcov:2d数组

     

popt估计的协方差。对角线提供参数估计的方差。要计算参数上的一个标准偏差,请使用perr = np.sqrt(np.diag(pcov))。

     

sigma参数如何影响估计的协方差取决于absolute_sigma参数,如上所述。

     

如果解的雅可比矩阵没有满秩,那么'lm'方法返回一个填充np.inf的矩阵,另一方面'trf'和'dogbox'方法使用Moore-Penrose伪逆计算协方差矩阵。

您可以从协方差矩阵的对角元素的平方根计算参数的标准偏差,如下所示:

import numpy as np                                                                                                                                                                                                                       
import matplotlib.pyplot as plt                                                                                                                                                                                                          
from scipy.stats import norm                                                                                                                                                                                                                                                                                                                                                                                                                   
from scipy.optimize import curve_fit

x = np.random.normal(size=50000)
fig, ax = plt.subplots()                                                                                                                                                                                                                 
nbins = 75                                                                                                                                                                                                                                                                                                                                                                                                                                              
n, bins, patches = ax.hist(x,nbins, density=True, facecolor = 'grey', alpha = 0.5, label='before');       

centers = (0.5*(bins[1:]+bins[:-1]))
pars, cov = curve_fit(lambda x, mu, sig : norm.pdf(x, loc=mu, scale=sig), centers, n, p0=[0,1])  

ax.plot(centers, norm.pdf(centers,*pars), 'k--',linewidth = 2, label='fit before')                                                                                                                                                                                 
ax.set_title('$\mu={:.4f}\pm{:.4f}$, $\sigma={:.4f}\pm{:.4f}$'.format(pars[0],np.sqrt(cov[0,0]), pars[1], np.sqrt(cov[1,1 ])))                                                                                                                                                                              

plt.show()

这导致以下情节:

enter image description here

答案 1 :(得分:2)

另请参阅lmfit(https://github.com/lmfit/lmfit-py),它提供了更简单的界面并报告拟合变量的不确定性。要将数据拟合到正态分布,请参阅http://lmfit.github.io/lmfit-py/builtin_models.html#example-1-fit-peak-data-to-gaussian-lorentzian-and-voigt-profiles

并使用类似

的内容
from lmfit.models import GaussianModel

model = GaussianModel()

# create parameters with initial guesses:
params = model.make_params(center=9, amplitude=40, sigma=1)  

result = model.fit(ydata, params, x=xdata)
print(result.fit_report())

该报告将包含1-sigma错误,如

[[Variables]]
    sigma:       1.23218358 +/- 0.007374 (0.60%) (init= 1.0)
    center:      9.24277047 +/- 0.007374 (0.08%) (init= 9.0)
    amplitude:   30.3135620 +/- 0.157126 (0.52%) (init= 40.0)
    fwhm:        2.90157055 +/- 0.017366 (0.60%)  == '2.3548200*sigma'
    height:      9.81457817 +/- 0.050872 (0.52%)  == '0.3989423*amplitude/max(1.e-15, sigma)'