返回

生成任意分布的随机数的技巧和方法

人工智能

对于随机数,平时我们还是比较常用的,一般都会直接通过各种语言原生自带的随机函数,比如 C++ 中有 random() 函数,Java 中有 Random 类,Python 有 random 模块等等。都能很方便地生成随机变量。

但它们有一个特点,那就是都服从均匀分布,而有些场景需要生成服从其他分布(如正态分布、指数分布、二项分布等)的随机数。

如何生成指定分布的随机数呢?

  1. 直接生成法

对于一些简单的分布,如均匀分布、指数分布和泊松分布,可以直接使用数学公式生成随机数。

例如,如果要生成服从均匀分布(0, 1)的随机数,可以使用以下公式:

random()

如果要生成服从指数分布(λ)的随机数,可以使用以下公式:

-1 / λ * log(random())

如果要生成服从泊松分布(λ)的随机数,可以使用以下公式:

def poisson(λ):
  L = math.exp(-λ)
  k = 0
  p = 1.
  while p > L:
    k += 1
    p *= random()
  return k
  1. 逆变换法

逆变换法是一种通用的方法,可以用来生成任意分布的随机数。

其基本思想是:对于一个给定的分布,其分布函数是一个单调递增的函数。因此,如果我们能够生成一个服从均匀分布(0, 1)的随机数,那么我们可以通过对该随机数进行变换,得到一个服从给定分布的随机数。

例如,如果要生成服从正态分布(0, 1)的随机数,可以使用以下步骤:

  1. 生成一个服从均匀分布(0, 1)的随机数 u。
  2. 计算 z = Φ^-1(u),其中 Φ^-1 是正态分布的分布函数的逆函数。

则 z 是一个服从正态分布(0, 1)的随机数。

  1. 接受-拒绝法

接受-拒绝法是一种通用的方法,可以用来生成任意分布的随机数。

其基本思想是:对于一个给定的分布,如果我们能够找到一个“包络”分布,其分布函数大于或等于给定分布的分布函数,那么我们可以通过生成服从包络分布的随机数,并对该随机数进行接受或拒绝,从而生成服从给定分布的随机数。

例如,如果要生成服从正态分布(0, 1)的随机数,可以使用以下步骤:

  1. 生成一个服从均匀分布(0, 1)的随机数 u。
  2. 生成一个服从 χ^2 分布(1)的随机数 v。
  3. 计算 w = u * v。
  4. 如果 w <= 1,则接受 u,否则拒绝 u。

如果 u 被接受,则 u 是一个服从正态分布(0, 1)的随机数。否则,重复步骤 1-4,直到生成一个被接受的 u。

  1. 马尔可夫链蒙特卡罗法

马尔可夫链蒙特卡罗法是一种通用的方法,可以用来生成任意分布的随机数。

其基本思想是:对于一个给定的分布,如果我们能够构造一个马尔可夫链,其平稳分布是给定分布,那么我们可以通过模拟该马尔可夫链,并记录下马尔可夫链的状态,从而生成服从给定分布的随机数。

例如,如果要生成服从正态分布(0, 1)的随机数,可以使用以下步骤:

  1. 初始化马尔可夫链的状态为 x0。
  2. 重复以下步骤,直到生成足够的随机数:
    • 从马尔可夫链的转移概率分布中生成一个随机数 u。
    • 计算 x1 = x0 + u。
    • 如果 x1 属于正态分布(0, 1)的支持集,则接受 x1,否则拒绝 x1。

如果 x1 被接受,则 x1 是一个服从正态分布(0, 1)的随机数。否则,重复步骤 2,直到生成一个被接受的 x1。