在计算β二项式似然时,我正在努力解决数值精度问题。我的目标是估计某个数字d的概率y mod 10 = d,假设y是二项式(n,p),p是β(a,b)。我正在尝试为大n提出快速解决方案,我的意思是至少1000.似乎给我合理答案的一件事是使用模拟。
def npliketest_exact(n,digit,a,b):
#draw 1000 values of p
probs = np.array(beta.rvs(a,b,size=1000))
#create an array of numbers whose last digit is digit
digits = np.arange(digit,n+1,10)
#create a function that calculates the pmf at x given p
exact_func = lambda x,p: binom(n,p).pmf(x)
#given p, the likeklihood of last digit "digit" is the sum over all entries in digits
likelihood = lambda p: exact_func(digits,p).sum()
#return the average of that likelihood over all the draws
return np.vectorize(likelihood)(probs).mean()
np.random.seed(1)
print npliketest_exact(1000,9,1,1) #0.0992310195195
这可能没问题,但我担心这个策略的精确性。特别是如果有更好/更精确的方法来进行这种计算,我很想知道如何去做。
我已经开始尝试使用对数可能性来得出答案,但即便如此,我也遇到了数值稳定性问题。
def llike(n,k,a,b):
out = gammaln(n+1) + gammaln(k+a) + gammaln(n-k+b) + gammaln(a+b) - \
( gammaln(k+1) + gammaln(n-k+1) + gammaln(a) + gammaln(b) + gammaln(n+a+b) )
return out
print exp(llike(1000,9,1,1)) #.000999000999001
print exp(llike(1000,500,1,1)) #.000999000999001
由于β1,1的平均值为0.5,因此从n = 1000的β二项式获得y = 500的概率应远高于得到9,但上述计算显示可疑的常数值。
我尝试过的另一件事就是使用stackoverflow来处理这个问题的另一件事,就是使用一些聪明的技巧来支持数值稳定性,这显然隐藏在scipy的betaln公式中。
def binomln(n, k): #log of the binomial coefficient
# Assumes binom(n, k) >= 0
return -betaln(1 + n - k, 1 + k) - log(n + 1)
def log_betabinom_exact(n,k,a,b):
return binomln(n,k) + betaln(k+a,n-k+b) - betaln(a,b)
print exp(log_betabinom_exact(1000,9,1,1)) #.000999000999001
print exp(log_betabinom_exact(1000,500,1,1)) #0.000999000999001
同样,同样可疑的常数。非常感谢任何建议。使用sympy会对此有任何帮助吗?
****跟进
对不起,伙计们,我的哑巴错误,Beta(1,1)是统一的,所以我得到的结果是有道理的。尝试不同的参数会使不同的k值看起来不同。