问题
我的很多编程都涉及 scipy.stats 中的统计功能。一个新问题需要计算beta-二项分布的 pmf 。因为它具有解析形式,但没有出现在 scipy.stats 中,所以我需要自己为其 pmf 定义一个函数。我正在使用 scipy 0.12.0 版和 numpy 1.7.0 版。
import numpy
from scipy.special import gammaln, betaln
def beta_binomial_pmf(k, n, K, N):
# compute natural log of pmf
ln_pmf = ( gammaln(n+1) - gammaln(k+1) - gammaln(n-k+1) ) + \
- betaln(K+1,N-K+1) + betaln(K+k+1,N-K+n-k+1)
return numpy.exp(ln_pmf)
在统计问题中,我试图解决 n 和 k 的值通常介于 0 和 100 之间,但 K 和 N 可以大到 1e9。我的问题是这个函数将为不同的输入返回相同的值。
例子
k = 0
n = 5
K = numpy.array([12, 10, 8])
N = 101677958
beta_binomial(k, n, L, N)
结果数组是
array([ 0.99999928, 0.99999905, 0.99999928])
考虑到 K 的每个值都不同,这很奇怪。为了更好地了解数组中第一个和第三个值之间的相似性
1 - beta_binomial(k, n, L, N)
array([ 7.15255482e-07, 9.53673862e-07, 7.15255482e-07])
对函数精度的一个非常简单的测试gammaln
是 1-(Gamma(N+1)/Gamma(N))/N。它很有用,因为如果您在纸上计算代数,结果正好是 0。
N = numpy.logspace(0,10,11)
1-numpy.exp(gammaln(N+1)-gammaln(N))/N
array([ 0.00000000e+00, -1.11022302e-15, 1.90958360e-14,
-9.94537785e-13, -4.96402919e-12, 7.74684761e-11,
-1.70086167e-13, 1.45905219e-08, 2.21033640e-07,
-7.64616381e-07, 2.54126535e-06])
问题
我认识到人们可以计算的精度是有限制的,但是在 N=1e7 左右会发生什么使精度变化gammaln
了五个数量级?关于如何解决这个问题的建议?