Python 高斯拟合

通常我们进行高斯拟合的办法是导入scipy的curve_fit 包,不过这需要自己手写一个高斯分布的函数表达式,不是很方便,astropy提供了一个写好的高斯拟合包

1. 调包
from astropy.modeling import models, fitting
import numpy as np
import matplotlib.pyplot as plt
2. 生成一个高斯的数据

为了检验拟合结果的好坏,我们先生成一个μ=0.5,σ=0.2的高斯数据,并赋予他一个噪声

def func_gaosi(x, miu, sigma):
    return 1/np.sqrt(2*np.pi)/sigma*np.exp(-(x-miu)**2/2/sigma**2)
  
x = np.linspace(0, 1, 100)
y = func_gaosi(x, 0.5, 0.2)
y += np.random.normal(0., 0.02, x.shape)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')

结果如下:在这里插入图片描述

3.使用astropy进行高斯拟合
g_init = models.Gaussian1D(amplitude=1., mean=0, stddev=1.)
fit_g = fitting.LevMarLSQFitter()
g = fit_g(g_init, x, y)

amplitude表示振幅的初值,振幅也就是高斯分布的系数,mean表示μ的初值,stddev表示σ的初值,g就是拟合结果,通过如下命令查看拟合的μ和σ

print(g.mean.value, g.stddev.value)
>>>>0.5007101792640887 0.20002191014593193

可以看到是很精确的,而且也不需要自己写高斯分布的函数

4. 完整的代码

通常在进行高斯拟合的时候,我们都是对一组数据的分布进行拟合,那么我们需要先对这组数据进行分bin,然后取出每个bin的中值和这个bin内数据的数目,把这两个量作为上文中拟合的x和y

def fit_gaosi(data, bins):
    hx, xedge = np.histogram(data,bins)
    xedge = (xedge[1:]+xedge[:-1])/2

    g_init = models.Gaussian1D(amplitude=np.max(hx), mean=np.mean(data), stddev=np.std(data))
    fit_g = fitting.LevMarLSQFitter()
    g = fit_g(g_init, xedge, hx)
    
    return g.mean.value, g.stddev.value, g

以上这个函数输入一组数据,以及你想分的bins数,就可以返回这组数据的μ和σ了,g返回的是一个函数,只需要

bins = 20
plt.hist(data,bins)
miu, sigma, g = fit_gaosi(data,bins)
x = np.linsapce(-0.5,0.5,20)
y = g(x)
plt.plot(x,y)

就可以把data的直方图和高斯分布画到一张图上了,这个x就是你想拟合数据的范围

当你的数据有若干个距离其他数据特别散的点,可能需要只针对数据比较集中的部分进行高斯拟合,杂乱的点反而会使你的拟合变差,那么fit_gaosi这个函数的输入就需要变一下,变成你数据集中位置的范围的一个数组,具体的例子如下:

bins = np.linspace(-0.5,0.5,10)
plt.hist(data,bins)
miu, sigma, g = fit_gaosi(data,bins)
x = np.linspace(-0.5,0.5,20)
y = g(x)
plt.plot(x,y)
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐