Numpy 如何从非均匀分布中抽取随机数?

How does Numpy sample random numbers from a non-uniform distribution?

我一直在学习随机抽样方法,我知道 Numpy 使用 Mersenne-Twister 生成均匀随机数,然后它如何传递这些以生成非均匀分布?

例如:

np.random.normal(mu,sigma,n)

这里使用什么算法对正态分布的数字进行采样?谢谢

您的总体问题过于宽泛,可以(并且确实)填写 entire textbook

也就是说,一个非常快速的概述是生成 非均匀随机数 的技术分为几个常见类别。其中包括:

  1. 累积分布函数 (CDF) 的逆变换;
  2. 卷积(随机变量的总和本身是随机的 具有不同分布的变量);
  3. 合成(分解一个 使用条件将复杂的分布分成更容易的部分 概率);
  4. Acceptance/rejection 技术(生成随机 "guesses",拒绝并 如果违反了目标分布的约束,则重试);和
  5. "Special Relationships"(认识到某些 发行版与其他发行版有着密切的关系 更容易生成)。

可以在 this tutorial paper 的第 4.3 节中找到 1-3 和 5 中每一个的简单示例。

在实践中,经常结合使用这些技术。

例如,无法通过反演分析找到正态分布,因为这需要能够为 CDF 编写一个封闭形式的方程。

Two popular variants for generating normals查看极坐标中的法线对,即表示为方向和距离。基本的 Box-Muller 算法指出方向从 0 到 2π 是均匀的,毕达哥拉斯告诉我们距离基于法线平方和,具有卡方 (2) 分布(卷积)。 "Special relations" 告诉我们卡方 (2) 是指数 (2),很容易通过反演生成。将所有部分放在一起并转换回笛卡尔坐标给出维基百科文章中的一对公式。

第二种变体是Marsaglia's Polar method, which appears to be the method used by NumPy。它通过在正方形中随机生成点并拒绝任何不包含在外接圆 (acceptance/rejection) 内的点来避免计算 sine/cosine 超越函数。然后它使用相同的 chi-square/exponential 距离计算来缩放结果,因此它也利用了卷积、"special relationships, " 和反演。

最快的方法是基于 ziggurat algorithm,它将法线分解成层(合成),对某些层使用特殊关系,并使用 acceptance/rejection 处理尾部一层。