使用scipy.stats将Weibull分布拟合到数据是否效果不佳?

问题描述

我正在对一些整数数据拟合Weibull分布,并估计相关的形状,比例和位置参数。但是,我注意到 scipy.stats 库在执行此操作时表现不佳。

因此,我采取了另一个方向,并使用下面的代码检查了贴合性能。我首先使用Weibull分布创建了100个数字,参数为shape = 3,scale = 200,location = 1。随后,我使用 fitter 库估算出最佳的分布拟合。

from fitter import Fitter
import numpy as np
from scipy.stats import weibull_min

# generate numbers
x = weibull_min.rvs(3,scale=200,loc=1,size=100)

# make them integers
data = np.asarray(x,dtype=int)

# fit one of the four distributions
f = Fitter(data,distributions=["gamma","rayleigh","uniform","weibull_min"])
f.fit()

f.summary()

我希望最合适的是威布尔分布。我尝试重新运行此测试。有时,威布尔拟合是一个很好的估计。然而,大多数时候,威布尔拟合被认为是最糟糕的结果。在这种情况下,估计参数为=(0.13836651040093312、66.99999999999999、1.3200752378443505)。我假设这些参数按顺序对应于形状,比例,位置。以下是拟合过程的摘要

$ f.summary()
             sumsquare_error          aic          bic  kl_div
gamma               0.001601  1182.739756 -1090.410631     inf
rayleigh            0.001819  1154.204133 -1082.276256     inf
uniform             0.002241  1113.815217 -1061.400668     inf
weibull_min         0.004992  1558.203041  -976.698452     inf

此外,将产生以下图。

Plot

此外,瑞利分布是形状参数= 2的威布尔的特例。因此,我希望所得的威布尔拟合至少与瑞利一样好。

更新

我在numpy版本1.19.2和scipy版本1.5.2的Linux / Ubuntu 20.04计算机上运行了上述测试。上面的代码似乎按预期运行,并为在Mac机器上进行Weibull分发返回了正确的结果。

我还测试了使用R库 fitdistrplus 将Weibull分布拟合到上面在Linux机器上生成的数据 x 上:

fit.weib <- fitdist(x,"weibull")

并观察到,估计的形状和比例尺值与初始给定值非常接近。到目前为止,最好的猜测是该问题是由于某些Python-Ubuntu错误/不兼容引起的。

我可以被认为是这方面的新手。所以,我想知道,我在这里做错了吗?还是以某种方式预期此结果?任何帮助将不胜感激。

谢谢。

解决方法

fitter不允许为发行版(例如a,loc等)指定参数。奇怪的是,对于相同版本的Numpy和Scipy。可能的原因可能包括为Linux和Mac设计的不同BLAS-LAPACK算法https://stackoverflow.com/a/49274049/6806531,或者weibull_min可能未初始化在线讨论的参数a = 1或默认浮点精度。但是,可以解决fitter库中的错误。知道weib_min是参数a的expon_weib的事实固定为1,将fitter.py中_timed_run函数内部的run函数更改为

        def run(self):
            try:
                if distribution == "exponweib":
                    self.result = func(args,floc=0,fa = 1,**kwargs)
                else:
                    self.result = func(args,**kwargs)
            except Exception as err:
                self.exc_info = sys.exc_info()

并使用exponweib作为weib_min可获得与R fitdist几乎相同的结果。

,

我对Fitter库不熟悉,但是为了得出一些结论,我建议:

  1. 重试您的代码,但大小为10,000。在这种情况下,有足够的数据点可供拟合方法使用。从理论上讲,您会期望Weibull提供最佳的配合。

  2. 我注意到location参数有时会很痛苦。您可以通过使用floc = 1固定位置参数(即等于位置的采样参数)来尝试拟合。你得到了什么?另外,FYI与MLE一起使用loc = min(x)就足够了,其中x是您的数据集。对于指数分布,这实际上是location参数的MLE。对于其他发行版,我不确定,但是对于其他发行版也一样,我不会感到惊讶。这样可以减少使用1个参数的拟合过程。

  3. 最后,我注意到,如果您为某些分布取小的位置/比例/形状值,则scipy.stats分布的函数logpdf和logcdf会产生np.inf值。在这种情况下,您也许可以使用Powell优化算法并为参数值设置界限。