将更好的高斯拟合到数据点?
Fitting a better gaussian to data points?
我正在尝试将高斯分布拟合到一组似乎遵循高斯分布的数据点。我已经检查了很多可能的方法来做到这一点,但我并不真正理解其中的大部分。然而,我找到了一个似乎有效的解决方案,但我得到的实际拟合看起来并不比我的数据点更像高斯分布。
这是我的代码:
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()
这是它生成的输出:
如您所见,拟合并未描述漂亮且对称的 "real" 高斯分布。
有什么办法可以得到 "better" 高斯函数,或者这已经很好了吗?
非常感谢!
最好的方法是简单地使用点的均值和方差。我的意思是,如果您有权访问生成此直方图的基础数据,那么您应该使用 mean
和 var
函数计算其均值和方差。
直方图只是对基础数据的视觉近似,本质上,您是通过拟合直方图而不是数据来以迂回的方式估计均值和方差。
无论如何,如果你想继续上面的思路,你需要给角度添加更多的点。最好的方法是做类似
的事情
angles2 = np.arange(-8,8,.1);
plt.plot(angles2,gaus(angles2,*popt),'r',label='Fit')
可能是因为您的数据点很少,所以您的合身性看起来很差。使用这种方法,您将看到连续分布应该是什么样子。
我认为这里有两点不同:
seem to follow a gaussian distribution
→ 如果你认为数据是正态分布的,那么你就处于统计和概率分布的领域,可能想做一个 test 看看它们是否符合特定的分布(正态或其他)。
并使用你的情节:
get a "better" gaussian plot
在您的代码中,您可以省略 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。
我正在尝试将高斯分布拟合到一组似乎遵循高斯分布的数据点。我已经检查了很多可能的方法来做到这一点,但我并不真正理解其中的大部分。然而,我找到了一个似乎有效的解决方案,但我得到的实际拟合看起来并不比我的数据点更像高斯分布。
这是我的代码:
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()
这是它生成的输出:
如您所见,拟合并未描述漂亮且对称的 "real" 高斯分布。 有什么办法可以得到 "better" 高斯函数,或者这已经很好了吗?
非常感谢!
最好的方法是简单地使用点的均值和方差。我的意思是,如果您有权访问生成此直方图的基础数据,那么您应该使用 mean
和 var
函数计算其均值和方差。
直方图只是对基础数据的视觉近似,本质上,您是通过拟合直方图而不是数据来以迂回的方式估计均值和方差。
无论如何,如果你想继续上面的思路,你需要给角度添加更多的点。最好的方法是做类似
的事情angles2 = np.arange(-8,8,.1);
plt.plot(angles2,gaus(angles2,*popt),'r',label='Fit')
可能是因为您的数据点很少,所以您的合身性看起来很差。使用这种方法,您将看到连续分布应该是什么样子。
我认为这里有两点不同:
seem to follow a gaussian distribution
→ 如果你认为数据是正态分布的,那么你就处于统计和概率分布的领域,可能想做一个 test 看看它们是否符合特定的分布(正态或其他)。
并使用你的情节:
get a "better" gaussian plot
在您的代码中,您可以省略 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。