2014-06-13 23 views
2

太远当试图获得一个截断正态分布的概率密度函数:截断法线当“A”和“B”是按照平均

from scipy.stats import truncnorm 
truncnorm.pdf(-31, np.inf, -30, loc=0, scale=1) 

它工作正常。但是,如果上界的距离太远的平均值,在未截断侧分配给样品的概率(那里的总质量应是1)为NaN:

# -41 is one of the points with highest probability. Why nan? 
>truncnorm.pdf(-41, np.inf, -40, loc=0, scale=1) 
nan 

# 39 is impossible since it lays in the truncated side 
>truncnorm.pdf(-39, np.inf, -40, loc=0, scale=1) 
0.0 

是否有错误由于数值精确度问题还是什么? 有没有另一种方法来做到这一点?

更新1(其中R库 “truncnorm”):

这似乎是一个常见的问题。同样的问题R “truncnorm” 库:

> dtruncnorm(-41, a=-Inf, b=-40, mean = 0, sd = 1) 
[1] NaN 

更新2(其中R库 “MSM”):

在他的博客,基督教罗伯特pointed out的 “MSM” 库,实现了他的paper

然而,它缩短为这种情况下:

> dtnorm(-41, mean = 0, sd=1, lower=-Inf, upper=-40) 
[1] NaN 
+0

我看起来像这个问题可以给一些提示。看起来这个函数并没有被认为能够以很高的数值精度工作:https://github.com/scipy/scipy/issues/1489 – alberto

+1

这也是R truncnorm库的一个问题,甚至在使用近似值时,请参阅Christian Roberts的帖子:http://xianblog.wordpress.com/2013/04/09/painful-truncnorm/ – alberto

回答

3

用于truncnorm的计算是基于正态分布的累积分布函数。

不可能以浮点(双精度)来表示尾部的cdf。

>>> stats.norm.cdf(-37) 
5.7255712225239266e-300 
>>> stats.norm.cdf(-38) 
0.0 

>>> stats.norm.pdf(-37) 
2.120006551524606e-298 
>>> stats.norm.pdf(-38) 
1.0972210519949712e-314 
>>> stats.norm.pdf(-39) 
0.0 

>>> np.finfo(float).tiny 
2.2250738585072014e-308 

来实现,这将是截断分布的直接计算或近似,不通过正态分布特殊功能的唯一途径。

我从来没有见过一个用例,我想用这个。

+1

如果你用零代替nans,那么你只剩下零,这不会产生密度。除了切换到多精度计算(mpmath)或提供尾部特定的“特殊”功能外,没有办法解决这个问题。 – user333700

+0

准确地说,你不能只用0代替NaN,因为NaN部分实际上是截断后剩下的部分,因此它必须重新归一化,以便它总和为1. – alberto

+0

感谢@ user333700,它在列表中令人放心。我的情况是对probit回归混合的Gibbs抽样。它与本文描述的whqt非常相似:http://jmlr.org/papers/volume10/shahbaba09a/shahbaba09a.pdf 我会在我做一些废话的时候回顾我的算法。 – alberto

相关问题