我在计算这个问题时遇到了麻烦。该代码适用于N的所有值,包括N = 57,但是对于大于或等于58的N,会抛出溢出错误(34,结果太大')。有没有办法绕过这个?感谢。
import numpy as np
import scipy.integrate
import scipy.optimize
import warnings
warnings.filterwarnings('ignore')
R = 6
N = 58
Nb = 4
S_norm = 0.3
Ao = 1/8.02e-5
y = (N-Nb/R)/Ao
def likelihood(psi):
def func_likelihood(A):
sum = 0
for k in range(0, N+1):
r = (np.math.factorial(N-k+Nb)/(np.math.factorial(k)*np.math.factorial(N-k))*(A*psi*(1+R))**k)
sum = r+sum
return sum* (np.exp(-0.5*(np.log(A/Ao)/S_norm)**2)*np.exp(-A*psi)/A)
return (scipy.integrate.quad(func_likelihood, 0, np.inf, full_output=1,epsabs=1e-300, epsrel=1e-300))[0]
psi = y-y/10
MLE = scipy.optimize.fmin(lambda psi: -likelihood(psi), y, disp=0,full_output=1)[0][0]
normal_factor = 1/likelihood(MLE)
print(normal_factor* likelihood(psi))
答案 0 :(得分:2)
它通常更有效,并且具有更少的溢出问题来计算术语的商,并使用该商来更新每个步骤中的术语。
压缩索引k
的术语是
r[k] = ( (N-k+Nb)! )/( k!*(N-k)! ) * (A*psi*(1+R))**k
以便最后一项的商是
r[k+1] / r[k] = ( (N-k) )/( (N-k+Nb)*(k+1) ) * (A*psi*(1+R))
和
r[0] = ( (N+Nb)! )/( N! ) = (N+1)*...*(N+Nb)
然后允许将求和函数重新表示为
def func_likelihood(A):
sum = 0
r = 1
for k in range(Nb): r *= N+k+1
sum = r
for k in range(0, N+1):
sum += r;
r *= (A*psi*(1+R)) * (N-k)/((N-k+Nb)*(k+1))
return sum * (np.exp(-0.5*(np.log(A/Ao)/S_norm)**2)*np.exp(-A*psi)/A)
答案 1 :(得分:1)
您未能提供错误消息,但我打算在r
循环中的因子计算for k
。
有几种方法可以解决这个问题。一种是切换操作顺序,这样就可以消除常见因素,而不是从58开始! (超过默认的整数限制)。这涉及更多编码,或者可能调用组合因子函数,例如将做C(n,k) - @LutzL提到二项式函数。当然,你没有完全二项式,但你可以使用它,然后根据-k+Nb
因子的需要调整分子。
另一种方法是切换到大整数(请参阅numpy& scipy的文档,以便解决所有包中的问题。)