【问题标题】:Fitting a better gaussian to data points?将更好的高斯拟合到数据点?
【发布时间】:2017-06-20 23:03:53
【问题描述】:

我正在尝试将高斯拟合到似乎遵循高斯分布的一组数据点。我已经检查了很多可能的方法来做到这一点,但我并不真正了解其中的大多数。但是,我找到了一种似乎可行的解决方案,但我得到的实际拟合看起来并不像我的数据点那样更像高斯。

这是我的代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy import asarray as ar, exp, sqrt
from scipy.optimize import curve_fit


angles = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
data = [99, 610, 1271, 1804, 1823, 1346, 635, 125, 24]
angles = ar(angles)
data = ar(data)

n = len(x)
mean = sum(data*angles)/n
sigma = sqrt(sum(data*(angles-mean)**2)/n)

def gaus(x,a,mu,sigma):
    return a*exp(-(x-mu)**2/(2*sigma**2))

popt,pcov = curve_fit(gaus,angles,data,p0=[0.18,mean,sigma])


fig = plt.figure()
plt.plot(angles, data, "ob", label = "Measured")
plt.plot(angles,gaus(angles,*popt),'r',label='Fit')
plt.xlim(-10, 10)
plt.ylim(0, 2000)
plt.xticks(angles)
plt.title("$^{137}$Cs Zero Point")
plt.xlabel("Angle [$^\circ$]")
plt.ylabel("662 keV-Photon Count")
plt.grid()
plt.legend()
plt.show()

这是它生成的输出:

如您所见,拟合并不能描述一个漂亮且对称的“真实”高斯。 有什么办法可以得到“更好”的高斯,或者这是否尽可能好?

非常感谢!

【问题讨论】:

  • n = len(x) 可能是n = len(data) ?

标签: python matplotlib plot gaussian data-fitting


【解决方案1】:

最好的方法是简单地使用点的均值和方差。我的意思是,如果您可以访问生成此直方图的基础数据,那么您应该使用 meanvar 函数计算其均值和方差。

直方图只是对基础数据的视觉近似,本质上您是通过拟合直方图而不是数据来以迂回的方式估计均值和方差。

无论如何,如果您想继续上面的思路,您需要在角度上添加更多点。做到这一点的最好方法是做类似的事情

angles2 = np.arange(-8,8,.1);
plt.plot(angles2,gaus(angles2,*popt),'r',label='Fit')

这可能是因为您的数据点非常少,因此您的身材看起来很糟糕。使用这种方法,您会看到连续分布应该是什么样子。

【讨论】:

  • The best way is to simply use the mean and variance of the points - 我同意,但你可能想证明这一说法的合理性:)
  • 我如何从中获得高斯拟合?
  • @Philipp,您基本上从数据中估计了高斯的均值和标准差。这些是您的高斯分布的参数。如果将它们插入(即高斯的)概率密度函数中,您将得到您正在寻找的形式
  • @cel,我明白了。在我使用meanvar 的示例中,代码看起来会如何?
【解决方案2】:

我认为这里有两个不同的东西:

似乎服从高斯分布

→ 如果您认为数据是正态分布的,那么您处于统计和概率分布领域,并且可能想要创建test 以查看它们是否符合特定分布(正态或其他)。


和你的情节一起工作:

得到一个“更好”的高斯 情节

在您的代码中,您可以省略 curve_fit 中的第一个估计值,并根据连续自变量绘制拟合曲线:

import numpy as np
import matplotlib.pyplot as plt
from scipy import asarray as ar, exp, sqrt
from scipy.optimize import curve_fit


angles = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
data = [99, 610, 1271, 1804, 1823, 1346, 635, 125, 24]
angles = ar(angles)
data = ar(data)

n = len(data)  ## <---
mean = sum(data*angles)/n
sigma = sqrt(sum(data*(angles-mean)**2)/n)

def gaus(x,a,mu,sigma):
    return a*exp(-(x-mu)**2/(2*sigma**2))

popt,pcov = curve_fit(gaus,angles,data)#,p0=[0.18,mean,sigma])  ## <--- leave out the first estimation of the parameters
xx = np.linspace( -10, 10, 100 )  ## <--- calculate against a continuous variable

fig = plt.figure()
plt.plot(angles, data, "ob", label = "Measured")
plt.plot(xx,gaus(xx,*popt),'r',label='Fit')  ## <--- plot against the contious variable
plt.xlim(-10, 10)
plt.ylim(0, 2000)
plt.xticks(angles)
plt.title("$^{137}$Cs Zero Point")
plt.xlabel("Angle [$^\circ$]")
plt.ylabel("662 keV-Photon Count")
plt.grid()
plt.legend()
plt.savefig('normal.png')
plt.show()


在这个例子中:

print( popt )

[  1.93154077e+03  -9.21486804e-01   3.26251063e+00]

请注意,参数的第一次估计与结果相差几个数量级:0.18 与 1931.15。

【讨论】:

    猜你喜欢
    • 2017-06-11
    • 2019-01-17
    • 2015-10-10
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多