【问题标题】:Sampling from a set according to unnormalized log-probabilities in NumPy根据 NumPy 中的非标准化对数概率从集合中采样
【发布时间】:2021-01-25 05:16:29
【问题描述】:

我有一个 1-D np.ndarray 填充了定义分类分布的非标准化对数概率。我想从这个分布中采样一个整数索引。由于许多概率很小,归一化和取幂对数概率会引入显着的数值错误,因此我不能使用np.random.choice。实际上,我正在寻找与 TensorFlow 的 tf.random.categorical 等效的 NumPy,它适用于非标准化的对数概率。

如果 NumPy 中没有直接实现这一点的函数,那么实现这种采样的有效方式是什么?

【问题讨论】:

  • “由于许多概率很小,归一化和取幂对数概率会引入显着的数值错误,” 你有一组对数概率的例子吗?证明问题?
  • @WarrenWeckesser 并不是说​​我可以方便地发帖。 well known 使用对数概率可防止出现下溢。采样是作为我正在实施的重要性采样算法的一部分完成的。因此,所涉及的许多概率都很小(1e-8 阶)。过去我遇到过问题,当从非标准化对数概率转换为标准化概率时,我最终会得到 NaN。
  • 您能否至少给出一些关于您拥有多少对数概率的典型值,以及对数概率值的典型范围是多少? 1e-8 似乎不足以引起问题。

标签: python numpy random


【解决方案1】:

一般来说,many ways to choose an integer 具有自定义分布,但它们中的大多数采用与给定概率成比例的权重。如果权重是对数概率,则需要稍微不同的方法。也许最简单的算法是拒绝采样,如下所述并在 Python 中实现。在以下算法中,最大对数概率为max,有k整数可供选择。

  1. 在 [0, k) 中选择一个统一的随机整数 i
  2. 获取i对应的log-weight,然后生成一个指数(1)的随机数,命名为ex
  3. 如果max 减去ex 小于对数权重,则返回i。否则,请转到第 1 步。

平均而言,拒绝采样的时间复杂度是恒定的,尤其是当 max 设置为等于真正的最大权重时。另一方面,每个样本的预期迭代次数很大程度上取决于分布的形状。另请参阅 Keith Schwarz's discussion 关于“公平骰子/偏置硬币加载骰子”算法。

现在,该算法的 Python 代码如下。

import random
import math

def categ(c):
 # Do a weighted choice of an item with the
 # given log-probabilities.
 cm=max(c) # Find max log probability
 while True:
      # Choose an item at random
      x=random.randint(0,len(c)-1)
      # Choose it with probability proportional
      # to exp(c[x])
      y=cm-random.expovariate(1)
      # Alternatively: y=math.log(random.random())+cm
      if y<c[x]:
          return x

上面的代码一次生成一个变量,并且只使用 Python 的基本模块,而不是 NumPy。 Another answer 展示了如何在 NumPy 中一次通过随机变量块来实现拒绝抽样(不过,在不同的随机抽样任务中进行了演示)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 2022-07-26
    • 2017-11-05
    • 2015-08-08
    • 2017-09-22
    • 1970-01-01
    • 2018-07-18
    相关资源
    最近更新 更多