【问题标题】:Fit a gaussian function拟合高斯函数
【发布时间】:2012-07-15 11:04:11
【问题描述】:

我有一个直方图(见下文),我正试图找到平均值和标准偏差以及适合我的直方图曲线的代码。我认为 SciPy 或 matplotlib 中有些东西可以提供帮助,但是我尝试过的每个示例都不起作用。

import matplotlib.pyplot as plt
import numpy as np

with open('gau_b_g_s.csv') as f:
    v = np.loadtxt(f, delimiter= ',', dtype="float", skiprows=1, usecols=None)

fig, ax = plt.subplots()

plt.hist(v, bins=500, color='#7F38EC', histtype='step')

plt.title("Gaussian")
plt.axis([-1, 2, 0, 20000])

plt.show()

【问题讨论】:

  • 不起作用是什么意思?它没有运行,或者输出不正确?
  • 我无法从互联网上获取代码来运行,以实际制作出应有的曲线
  • 这很可能发生,因为我刚开始编程,我通常不知道我在做什么
  • 那么当您尝试运行它时是否收到错误消息?还是程序在没有产生任何东西的情况下完成?
  • 我只是不知道如何正确使用我的数据

标签: python matplotlib scipy histogram curve-fitting


【解决方案1】:

查看this answer 以将任意曲线拟合到数据。基本上你可以使用scipy.optimize.curve_fit 来适应你想要的数据的任何功能。下面的代码显示了如何将高斯拟合到一些随机数据(感谢this SciPy-User 邮件列表帖子)。

import numpy
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

# Define some test data which is close to Gaussian
data = numpy.random.normal(size=10000)

hist, bin_edges = numpy.histogram(data, density=True)
bin_centres = (bin_edges[:-1] + bin_edges[1:])/2

# Define model function to be used to fit to the data above:
def gauss(x, *p):
    A, mu, sigma = p
    return A*numpy.exp(-(x-mu)**2/(2.*sigma**2))

# p0 is the initial guess for the fitting coefficients (A, mu and sigma above)
p0 = [1., 0., 1.]

coeff, var_matrix = curve_fit(gauss, bin_centres, hist, p0=p0)

# Get the fitted curve
hist_fit = gauss(bin_centres, *coeff)

plt.plot(bin_centres, hist, label='Test data')
plt.plot(bin_centres, hist_fit, label='Fitted data')

# Finally, lets get the fitting parameters, i.e. the mean and standard deviation:
print 'Fitted mean = ', coeff[1]
print 'Fitted standard deviation = ', coeff[2]

plt.show()

【讨论】:

  • 谢谢,这得到了平均值和标准差,但曲线拟合实际上并没有产生曲线,它产生了线条
  • 你的意思是我的例子只产生线条吗?或者当您将上述代码应用于您的数据时,您会得到线条?还有,直线和曲线有什么区别?
  • 与钟形曲线形状相反,它看起来像一个胡萝卜^
  • 如果没有更多信息,我真的帮不了你。你的意思是你的数据看起来像胡萝卜吗?如果是这样,那么大概是因为这就是您的数据的样子。提问时最好附上short, self contained example
  • 我怀疑@user1496646 的意思是,在他的情况下, 并不多,所以当你绘制(bin_centres,hist_fit)时,它的高斯采样率很差(“胡萝卜”) .他应该只对 bin_centers 进行二次采样,使用 new_bin_centers = numpy.linspace(bin_centres[0], bin_centres[-1], 200), new_hist_fit = gauss(new_bin_centres, *coeff) 和 plot(new_bin_centres, new_hist_fit)
【解决方案2】:

您可以尝试 sklearn 高斯混合模型估计如下:

import numpy as np
import sklearn.mixture

gmm = sklearn.mixture.GMM()

# sample data
a = np.random.randn(1000)

# result
r = gmm.fit(a[:, np.newaxis]) # GMM requires 2D data as of sklearn version 0.16
print("mean : %f, var : %f" % (r.means_[0, 0], r.covars_[0, 0]))

参考:http://scikit-learn.org/stable/modules/mixture.html#mixture

请注意,通过这种方式,您无需使用直方图估计样本分布。

【讨论】:

【解决方案3】:

有点老问题,但对于任何只想绘制适合系列的密度的人,您可以尝试 matplotlib 的 .plot(kind='kde')。文档here.

以熊猫为例:

mydf.x.plot(kind='kde')

【讨论】:

  • 哇,TIL matplotlib 内置了内核密度估计。+1
【解决方案4】:

我不确定您的输入是什么,但您的 y 轴刻度可能太大(20000),请尝试减少此数字。以下代码适用于我:

import matplotlib.pyplot as plt
import numpy as np

#created my variable
v = np.random.normal(0,1,1000)


fig, ax = plt.subplots()


plt.hist(v, bins=500, normed=1, color='#7F38EC', histtype='step')

#plot
plt.title("Gaussian")
plt.axis([-1, 2, 0, 1]) #changed 20000 to 1

plt.show()

编辑:

如果您想要 y 轴上的实际值计数,可以设置 normed=0。并且会摆脱plt.axis([-1, 2, 0, 1])

import matplotlib.pyplot as plt
import numpy as np

#function
v = np.random.normal(0,1,500000)


fig, ax = plt.subplots()

# changed normed=1 to normed=0
plt.hist(v, bins=500, normed=0, color='#7F38EC', histtype='step')

#plot
plt.title("Gaussian")
#plt.axis([-1, 2, 0, 20000]) 

plt.show()

【讨论】:

  • 没有我正在处理超过 50 万个点,所以我希望规模那么大,因为我不想要 50,000 个垃圾箱
  • @我相信 y 轴上的值不会告诉您每个 bin 中的观察次数,它会告诉您每个 bin 中的百分比。只需注释掉整个plt.axis([-1, 2, 0, 1]) 行并运行它,您应该会得到一个分布图。
  • 它肯定会告诉我每个 bin 中的数字,因为我可以看到直方图本身,y 轴为 20,000
  • 投反对票的人,你能解释一下投反对票的原因吗?
猜你喜欢
  • 2021-11-19
  • 2017-06-11
  • 1970-01-01
  • 1970-01-01
  • 2017-08-30
  • 2023-03-19
  • 2021-09-09
  • 2017-06-14
  • 1970-01-01
相关资源
最近更新 更多