在python中计算自定义概率分布(数字)



我有一个自定义的(离散的(概率分布,其形式为:给定离散集x中的x'的f(x(/(sum(f(x'((。此外,0<x<1.所以我一直试图在python 3.8.2中实现它,问题是分子和分母都很小,python的浮点表示法只将它们取为0.0
在计算这些概率后,我需要从数组中采样一个随机元素,其每个索引都可以在分布中以相应的概率选择。因此,如果我的分布是[p1,p2,p3,p4],并且我的数组是[a1,a2,a3,a4],那么选择a2的概率是p2,依此类推。
那么我如何以优雅高效的方式实现这一点呢
在这种情况下,有什么方法可以使用np.rrandom.beta((吗?由于贝塔分布和我的实际分布之间的区别只是归一化常数不同,并且域被限制在几个点上。

注意:上面定义的概率质量函数实际上是由贝叶斯定理和f(x(=x^s*(1-x(^f给出的形式,其中s和f是给定迭代的固定数。所以确切的问题是,当s或f变得非常大时,这个值会变为0。

使用日志可以很好地计算事物。关键是,虽然分子和分母都可能下溢到0,但它们的对数不会,除非你的数字真的小得惊人。

你说

f(x) = x^s*(1-x)^t

所以

logf (x) = s*log(x) + t*log(1-x)

你想计算,比如

p = f(x) / Sum{ y in X | f(y)}

所以

p = exp( logf(x) - log sum { y in X | f(y)}
= exp( logf(x) - log sum { y in X | exp( logf( y))}

唯一的困难是计算第二项,但这是一个常见的问题,例如这里的

另一方面,手工计算logsumexp是很容易的。

我们想要

S = log( sum{ i | exp(l[i])})

如果L是L[i]的最大值,则

S = log( exp(L)*sum{ i | exp(l[i]-L)})
= L + log( sum{ i | exp( l[i]-L)})

最后一个和可以按写的方式计算,因为每个项现在都在0和1之间,所以没有溢出的危险,其中一个项(l[i]==l的项(是1,所以如果其他项下溢,那是无害的。

然而,这可能会失去一点准确性。一种改进是识别所在的指数集A

l[i]>=L-eps (eps a user set parameter, eg 1)

然后计算

N = Sum{ i in A | exp(l[i]-L)}
B = log1p( Sum{ i not in A | exp(l[i]-L)}/N)
S = L + log( N) + B

最新更新