python - scipy stats binom cdf 返回 nan

标签 python scipy

如果我理解正确,scipy.stats 离散分布的 cdf 应该返回给定参数值的概率总和。

因此,scipy.stats.binom(7000000000, 0.5).cdf(6999999999) 应该返回几乎恰好为 1 的值,因为在 70 亿次试验中,有 50/50 的概率在 70 亿减 1 或更少的情况下取得成功是非常确定的。相反,我得到了 np.nan。事实上,对于提供给 .cdf 的任何值,除了 70 亿本身(或更多),我都会返回 np.nan

这是怎么回事? scipy.stats 发行版可以处理的数字是否有一些限制,但文档中没有?

最佳答案

TL;博士

内部计算时缺乏浮点精度。虽然 scipy 是一个 Python 库,但它的核心是用 C 语言编写的,并使用 C 数字类型。


举个例子:

import scipy.stats

for i in range (13):
    trials = 10 ** i
    print(f"i: {i}\tprobability: {scipy.stats.binom(trials, 0.5).cdf(trials - 1)}")

输出是:

i: 0    probability: 0.5
i: 1    probability: 0.9990234375
i: 2    probability: 0.9999999999999999
i: 3    probability: 0.9999999999999999
i: 4    probability: 0.9999999999999999
i: 5    probability: 0.9999999999999999
i: 6    probability: 0.9999999999999999
i: 7    probability: 0.9999999999999999
i: 8    probability: 0.9999999999999999
i: 9    probability: 0.9999999999999999
i: 10   probability: nan
i: 11   probability: nan
i: 12   probability: nan

原因在于二项分布的 CDF 公式(我无法嵌入图像,所以这里是维基链接:https://en.wikipedia.org/wiki/Binomial_distribution

在 scipy 源代码中,我们会看到对此实现的引用:http://www.netlib.org/cephes/doubldoc.html#bdtr

在它的深处涉及到按trials划分(incbet.c, line 375: ai = 1.0/a; 这里叫做a,但是 nwm)。如果您的 trials 太大,这个除法的结果会很小,以至于当我们将这个小数字加到另一个不是那么小的数字时,它实际上并没有改变,因为我们缺乏浮点精度这里(目前只有 64 位)。然后,经过更多的算术运算,我们尝试从一个数字中得到对数,但它等于零,因为它没有在应该改变的时候改变。而log(0)没有定义,等于np.nan

关于python - scipy stats binom cdf 返回 nan,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53199088/

相关文章:

scipy - `scipy.integrate.odeint` 自动调整时间步长

python - 覆盖类属性但不覆盖子类中的方法

python - 在多组的多个日期范围内查找缺失日期

python - 忽略工具提示文本并仅获取当前使用 Beautiful Soup 显示的文本

python - .shape[] 在 "for i in range(Y.shape[0])"中做了什么?

python - 如何在Python中向稀疏矩阵添加稀疏行?

python - 有没有更快的方法来找到形状的周长?

python - Pandas 滚动应用 Scipy FindPeaks 函数 : TypeError: only size-1 arrays can be converted

python - 如何删除列表中满足 python 特定条件的最左边/最右边的元素?

Python:无法从json获取数据并转换为列表