python-3.x - 在 python 中计算自定义概率分布(数字)
问题描述
我有一个自定义(离散)概率分布,其形式有点定义:f(x)/(sum(f(x')) for x' in a given离散集X)。此外,0<=x<=1。所以我一直在尝试在 python 3.8.2 中实现它,问题是分子和分母都非常小,python 的浮点表示只是将它们作为 0.0。
在计算完这些概率之后,我需要从一个数组中抽取一个随机元素,它的每个索引可以用分布中的相应概率来选择。所以如果我的分布是 [p1,p2,p3,p4],我的数组是 [a1,a2,a3,a4],那么选择 a2 的概率就是 p2,以此类推。
那么我怎样才能以一种优雅而有效的方式实现它呢?
在这种情况下,有什么办法可以使用 np.random.beta() 吗?由于 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
推荐阅读
- javascript - React Hook useEffect 缺少一个依赖项:'formValues'。要么包含它,要么移除依赖数组 react-hooks/exhaustive-deps
- flutter - RenderViewport#0d172 需要-绘制需要-合成-位-更新
- sql - 在 Oracle 表中运行多个插入,如何在每次插入后提交并在最后一个插入点重新启动存储过程?
- jenkins - 如何在 Jenkins 中使用 ssh Api Key
- c# - C# ref 返回值和可移动变量
- php - 类似 SAAS 的 Firebase 身份验证
- python - 从 X 射线图像中检测和分割感兴趣区域
- android - react-native 在底部标签导航中隐藏屏幕的特定标签
- python - 我可以访问 fatimatestpro.pythonanywhere.com 但不能访问 fatimatestpro.pythonanywhere.com/help/
- java - 为什么我使用 Spring Boot 获得“需要 NOAUTH 身份验证”?