使用 scipy.stats 将 Weibull 分布拟合到数据是否表现不佳?
Does fitting Weibull distribution to data using scipy.stats perform poor?
我正在研究对一些整数数据拟合威布尔分布并估计相关的形状、比例、位置参数。但是,我注意到 scipy.stats 库在执行此操作时性能不佳。
所以,我采取了不同的方向,并使用下面的代码检查了拟合性能。我首先使用参数 shape=3、scale=200、location=1 的 Weibull 分布创建 100 个数字。随后,我使用 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()
我希望最适合的是 Weibull 分布。我试过重新运行ning这个测试。有时 Weibull 拟合是一个很好的估计。然而,大多数时候威布尔拟合被报告为最差的结果。在这种情况下,估计参数为 = (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
此外,还产生了以下情节。
此外,Rayleigh 分布是 Weibull 的特例,形状参数 = 2。因此,我希望生成的 Weibull 拟合至少与 Rayleigh 一样好。
更新
我 运行 在 Linux/Ubuntu 20.04 机器上使用 numpy 版本 1.19.2 和 scipy 版本 1.5.2 进行上述测试。上面的代码似乎 运行 符合预期,return 在 Mac 机器上的 Weibull 分布的正确结果。
我还测试了使用 R 库 fitdistrplus[=43 在 Linux 机器上生成的数据 x 上拟合威布尔分布=] 为:
fit.weib <- fitdist(x, "weibull")
并观察到估计的形状和比例值被发现非常接近最初给定的值。到目前为止最好的猜测是问题是由于某些 Python-Ubuntu bug/incompatibility.
我算是这方面的新手。所以,我想知道,我在这里做错了什么吗?还是以某种方式预期会出现此结果?非常感谢任何帮助。
谢谢。
库 fitter
不允许为 a、loc 等分布指定参数。奇怪的是,Mac 产生更好的拟合,而 Linux 严重影响结果最适合,对于相同版本的 Numpy 和 Scipy。根本原因可能包括为 Linux 和 Mac、 或 weibull_min 设计的不同 BLAS-LAPACK 算法可能无法初始化参数 a
= 1在线讨论,还是默认floating-point准确率。但是,可以解决 fitter
库中的错误。知道weib_min是expon_weib,参数a固定为1,将fitter.py中的_timed_run函数里面的运行函数改成
def run(self):
try:
if distribution == "exponweib":
self.result = func(args,floc=0,fa = 1, **kwargs)
else:
self.result = func(args, floc=0, **kwargs)
except Exception as err:
self.exc_info = sys.exc_info()
并使用 exponweib 作为 weib_min 给出与 R fitdist
.
几乎相同的结果
我不熟悉 Fitter 库,但为了得出一些结论我建议:
重试您的代码,但取 size=10,000。在这种情况下,有足够的数据点供拟合方法使用。从理论上讲,您会期望 Weibull 提供最佳拟合。
我注意到位置参数有时会很麻烦。您可以通过将位置参数固定为 floc=1(即等于您的位置采样参数)来尝试 运行 您的拟合。你得到了什么?另外,仅供参考,使用 MLE,取 loc=min(x) 就足够了,其中 x 是您的数据集。对于指数分布,这实际上是位置参数的 MLE。对于其他发行版,我不确定,但如果这也适用于其他发行版,我不会感到惊讶。这将减少 1 个参数的拟合过程。
最后,我注意到如果您为某些分布取较小的 location/scale/shape 值,scipy.stats 分布的函数 logpdf 和 logcdf 会导致 np.inf 值.在这种情况下,您或许可以使用 Powell 优化算法并设置参数值的界限。
我正在研究对一些整数数据拟合威布尔分布并估计相关的形状、比例、位置参数。但是,我注意到 scipy.stats 库在执行此操作时性能不佳。
所以,我采取了不同的方向,并使用下面的代码检查了拟合性能。我首先使用参数 shape=3、scale=200、location=1 的 Weibull 分布创建 100 个数字。随后,我使用 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()
我希望最适合的是 Weibull 分布。我试过重新运行ning这个测试。有时 Weibull 拟合是一个很好的估计。然而,大多数时候威布尔拟合被报告为最差的结果。在这种情况下,估计参数为 = (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
此外,还产生了以下情节。
此外,Rayleigh 分布是 Weibull 的特例,形状参数 = 2。因此,我希望生成的 Weibull 拟合至少与 Rayleigh 一样好。
更新
我 运行 在 Linux/Ubuntu 20.04 机器上使用 numpy 版本 1.19.2 和 scipy 版本 1.5.2 进行上述测试。上面的代码似乎 运行 符合预期,return 在 Mac 机器上的 Weibull 分布的正确结果。
我还测试了使用 R 库 fitdistrplus[=43 在 Linux 机器上生成的数据 x 上拟合威布尔分布=] 为:
fit.weib <- fitdist(x, "weibull")
并观察到估计的形状和比例值被发现非常接近最初给定的值。到目前为止最好的猜测是问题是由于某些 Python-Ubuntu bug/incompatibility.
我算是这方面的新手。所以,我想知道,我在这里做错了什么吗?还是以某种方式预期会出现此结果?非常感谢任何帮助。
谢谢。
库 fitter
不允许为 a、loc 等分布指定参数。奇怪的是,Mac 产生更好的拟合,而 Linux 严重影响结果最适合,对于相同版本的 Numpy 和 Scipy。根本原因可能包括为 Linux 和 Mac、a
= 1在线讨论,还是默认floating-point准确率。但是,可以解决 fitter
库中的错误。知道weib_min是expon_weib,参数a固定为1,将fitter.py中的_timed_run函数里面的运行函数改成
def run(self):
try:
if distribution == "exponweib":
self.result = func(args,floc=0,fa = 1, **kwargs)
else:
self.result = func(args, floc=0, **kwargs)
except Exception as err:
self.exc_info = sys.exc_info()
并使用 exponweib 作为 weib_min 给出与 R fitdist
.
我不熟悉 Fitter 库,但为了得出一些结论我建议:
重试您的代码,但取 size=10,000。在这种情况下,有足够的数据点供拟合方法使用。从理论上讲,您会期望 Weibull 提供最佳拟合。
我注意到位置参数有时会很麻烦。您可以通过将位置参数固定为 floc=1(即等于您的位置采样参数)来尝试 运行 您的拟合。你得到了什么?另外,仅供参考,使用 MLE,取 loc=min(x) 就足够了,其中 x 是您的数据集。对于指数分布,这实际上是位置参数的 MLE。对于其他发行版,我不确定,但如果这也适用于其他发行版,我不会感到惊讶。这将减少 1 个参数的拟合过程。
最后,我注意到如果您为某些分布取较小的 location/scale/shape 值,scipy.stats 分布的函数 logpdf 和 logcdf 会导致 np.inf 值.在这种情况下,您或许可以使用 Powell 优化算法并设置参数值的界限。