如果我有一个随机数Z
,它被定义为其他两个随机数和的X
和Y
,那么 的概率分布是和的概率分布Z
的卷积。卷积基本上是分布函数乘积的积分。卷积中的积分往往没有解析解,所以必须用基本的求积算法来计算。在伪代码中:X
Y
prob_z(z) = integrate(lambda t: prob_x(t) * prob_y(z-t), -inf, inf)
举一个具体的例子,Z
一个正态分布变量X
和一个对数正态分布变量之和Y
可以用下面的 Python/Scipy 代码计算:
from scipy.integrate import quad
from scipy.stats import norm, lognorm
from scipy import log
prob_x = lambda x: norm.pdf(x, 0, 1) # N(mu=0, sigma=1)
prob_y = lambda y: lognorm.pdf(y, 0.1, scale=10) # LogN(mu=log(10), sigma=0.1)
def prob_z(z):
return quad(lambda t: prob_x(t)*prob_y(z-t), -inf, inf)
现在我想计算对数概率。天真的解决方案很简单:
def log_prob_z(z):
return log(prob_z(z))
然而,这在数值上是不稳定的。在大约 39 个标准差之后,概率分布在数值上为 0.0,因此即使对数概率具有某个有限值,也无法通过简单地取概率的对数来计算除此之外的值。比较norm.pdf(39, 1, 0)
哪个是 0.0,norm.logpdf(39, 1, 0)
哪个大约是 -761。logpdf
显然,Scipy 不会计算log(pdf)
- 它会找到其他方式 - 因为否则它会返回-inf
,一个较差的响应。同样,我想为我的问题找到另一种方法。
(您可能想知道为什么我关心与平均值相差甚远的值的对数相似度。答案是参数拟合。当对数似然为某个极大的负数时,拟合算法可以更接近,但当它是-inf
或时,什么都做不了nan
。 )
问题是:有谁知道我可以如何重新排列log(quad(...))
,所以我不计算quad(...)
,从而避免在日志中创建 0.0?