通常我们进行高斯拟合的办法是导入scipy的curve_fit 包,不过这需要自己手写一个高斯分布的函数表达式,不是很方便,astropy提供了一个写好的高斯拟合包
from astropy.modeling import models, fitting
import numpy as np
import matplotlib.pyplot as plt
为了检验拟合结果的好坏,我们先生成一个μ=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')
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
可以看到是很精确的,而且也不需要自己写高斯分布的函数
通常在进行高斯拟合的时候,我们都是对一组数据的分布进行拟合,那么我们需要先对这组数据进行分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.linsapce(-0.5,0.5,20)
y = g(x)
plt.plot(x,y)