如果我有一个随机数
现在我想计算对数概率。朴素的解决方案是简单地执行以下操作:
然而,这是数值不稳定的。大约在39个标准偏差之后,概率分布数值变为0.0,因此即使对数概率有一些有限的值,也不能通过简单地取概率的对数来计算。比较
(你可能会想知道为什么我关心远离平均值的值的对数似然。答案是参数拟合。当对数似然是一些极为负数的数时,拟合算法可以更接近,但当它为
问题是:有人知道我如何重新排列
Z
,它被定义为另外两个随机数X
和Y
的总和,那么Z
的概率分布是X
和Y
的概率分布的卷积。卷积基本上是分布函数乘积的积分。通常,卷积中的积分没有解析解,因此必须使用基本的积分算法进行计算。伪代码如下:prob_z(z) = integrate(lambda t: prob_x(t) * prob_y(z-t), -inf, inf)
举个具体的例子,正态分布变量X
和对数正态分布变量Y
的总和Z
可以使用以下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。显然,Scipy没有将logpdf
计算为log(pdf)
- 它找到了其他方法 - 否则它会返回-inf
,这是一个劣质的响应。同样地,我想找到另一种方法来解决我的问题。(你可能会想知道为什么我关心远离平均值的值的对数似然。答案是参数拟合。当对数似然是一些极为负数的数时,拟合算法可以更接近,但当它为
-inf
或nan
时就无能为力了。)问题是:有人知道我如何重新排列
log(quad(...))
,以便我不计算quad(...)
,从而避免在对数中创建0.0吗?