使用(Python)Scipy拟合Gamma分布

37

请问有谁能帮我在Python中拟合伽玛分布吗?我的数据包含X和Y坐标,并且我想找到适配该分布的伽玛参数。在Scipy文档中,似乎存在一个fit方法,但我不知道如何使用它:s...首先,参数"data"应该以哪种格式提供,第二个参数(参数)应该如何提供呢?因为那正是我要寻找的。

5个回答

83

生成一些 Gamma 数据:

import scipy.stats as stats    
alpha = 5
loc = 100.5
beta = 22
data = stats.gamma.rvs(alpha, loc=loc, scale=beta, size=10000)    
print(data)
# [ 202.36035683  297.23906376  249.53831795 ...,  271.85204096  180.75026301
#   364.60240242]

这里我们将数据拟合到Gamma分布:

fit_alpha, fit_loc, fit_beta=stats.gamma.fit(data)
print(fit_alpha, fit_loc, fit_beta)
# (5.0833692504230008, 100.08697963283467, 21.739518937816108)

print(alpha, loc, beta)
# (5, 100.5, 22)

非常感谢!但是为什么你在一开始创建了变量x? - Archanimus
啊,看来我的消息太晚了。 再次非常感谢你 ;) - Archanimus
6
scipy.stats 使用最大似然估计进行拟合,因此您需要传递原始数据而不是概率密度函数/概率质量函数(x、y)。 - Christian Alis
2
请注意,beta用于表示分布的“速率”参数,该参数是“形状”的倒数。 - vahid

9

我对ss.gamma.rvs函数感到不满意,因为它可能会生成负数,而伽玛分布不应该有这种情况。因此,我通过期望值=mean(data)和方差=var(data)(有关详细信息,请参见维基百科)拟合了样本,并编写了一个可以在没有scipy的情况下生成伽玛分布随机样本的函数(我发现安装scipy很困难,顺便提一句):

import random
import numpy

data = [6176, 11046, 670, 6146, 7945, 6864, 767, 7623, 7212, 9040, 3213, 6302, 10044, 10195, 9386, 7230, 4602, 6282, 8619, 7903, 6318, 13294, 6990, 5515, 9157]

# Fit gamma distribution through mean and average
mean_of_distribution = numpy.mean(data)
variance_of_distribution = numpy.var(data)

def gamma_random_sample(mean, variance, size):
    """Yields a list of random numbers following a gamma distribution defined by mean and variance"""
    g_alpha = mean*mean/variance
    g_beta = mean/variance
    for i in range(size):
        yield random.gammavariate(g_alpha,1/g_beta)

# force integer values to get integer sample
grs = [int(i) for i in gamma_random_sample(mean_of_distribution,variance_of_distribution,len(data))]

print("Original data: ", sorted(data))
print("Random sample: ", sorted(grs))

# Original data: [670, 767, 3213, 4602, 5515, 6146, 6176, 6282, 6302, 6318, 6864, 6990, 7212, 7230, 7623, 7903, 7945, 8619, 9040, 9157, 9386, 10044, 10195, 11046, 13294]
# Random sample:  [1646, 2237, 3178, 3227, 3649, 4049, 4171, 5071, 5118, 5139, 5456, 6139, 6468, 6726, 6944, 7050, 7135, 7588, 7597, 7971, 10269, 10563, 12283, 12339, 13066]

1
“在维基百科中查看详细信息”非常泛泛而谈。您应该添加一个具体的链接。 - U. Windl

2
如果您想要一个包括估计或修正分布支持的讨论的长示例,则可以在https://github.com/scipy/scipy/issues/1359和链接的邮件列表消息中找到它。
在scipy的trunk版本中已经添加了初步的支持,以固定参数(例如位置)进行拟合。

1

OpenTURNS提供了一个简单的方法来使用GammaFactory类进行操作。

首先,让我们生成一个样本:

import openturns as ot
gammaDistribution = ot.Gamma()
sample = gammaDistribution.getSample(100)

然后对其进行Gamma拟合:
distribution = ot.GammaFactory().build(sample)

然后我们可以绘制Gamma的PDF:
import openturns.viewer as otv
otv.View(distribution.drawPDF())

该段代码产生以下结果:

A gamma distribution

关于此主题的更多细节请参见:http://openturns.github.io/openturns/latest/user_manual/_generated/openturns.GammaFactory.html


-2

1):“data”变量可以是Python列表或元组格式,也可以是通过以下方式获得的numpy.ndarray:

data=numpy.array(data)

以上行中的第二个数据应该是一个包含您数据的列表或元组。

2: "parameter"变量是拟合函数的可选初始猜测,因此可以省略。

3:关于@mondano的答案的说明。使用矩(均值和方差)来计算伽马参数对于大形状参数(alpha> 10)是合理的,但对于小的alpha值可能会产生较差的结果(请参见Wilks的《大气科学中的统计方法》和THOM,H.C.S.,1958年:关于伽马分布的注释。Mon.Weather Rev.,86,117-122。

在这种情况下,使用最大似然估计器(MLE),如scipy模块中实现的那样,被认为是更好的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接