如何使用传统编程语言从具有已知均值和方差的正态分布中采样?

机器算法验证 正态分布 采样 计算统计
2022-02-03 14:42:32

我从来没有上过统计学课程,所以我希望我在这里问对了地方。

假设我只有两个描述正态分布的数据:均值和方差我想使用计算机从这个分布中随机抽样,以便我尊重这两个统计数据。μσ2

很明显,我可以通过简单地在 0 左右标准化来处理平均值:只需在输出样本之前将添加到每个样本。但我看不到如何以编程方式生成样本以尊重μσ2

我的程序将使用传统的编程语言;我无权访问任何统计包。

4个回答

如果您可以从均值 0 和方差 1 的给定分布中采样,那么您可以轻松地从该分布的尺度位置变换中采样,该分布具有均值和方差如果是来自均值 0 和方差 1 分布的样本,则 是具有均值和方差的样本。因此,您所要做的就是在添加均值之前(方差的平方根)缩放变量μσ2x

σx+μ
μσ2σμ

如何从均值 0 和方差 1 的正态分布中实际获得模拟是另一回事。知道如何实现这些东西很有趣,但无论您是否使用统计包或编程语言,我都建议您获取并使用合适的函数或库来生成随机数。如果您想获得有关使用哪个库的建议,您可能需要添加有关您正在使用的编程语言的特定信息。

编辑:根据评论、其他一些答案以及 Fixee 接受这个答案的事实,我将提供更多关于如何使用统一变量的转换来产生正常变量的细节。

  • 一种方法,已经在VitalStatistix的评论中提到,是 Box-Muller 方法,它采用两个独立的均匀随机变量并产生两个独立的正态随机变量。francogrex发布了一种类似的方法,该方法可以避免计算两个超越函数sincos ,但需要进行更多的模拟。
  • 一种完全通用的方法是通过逆分布函数对均匀随机变量进行变换。如果U均匀分布在[0,1]然后
    Φ1(U)
    具有标准正态分布。虽然没有明确的解析公式Φ1,它可以通过精确的数值近似来计算。R 中的当前实现(我上次检查过)使用了这个想法。该方法在概念上非常简单,但需要准确实现Φ1,这可能不像(其他)超越函数logsincos那样普遍。
  • 几个答案提到使用中心极限定理将正态分布近似为均匀随机变量的平均值的可能性。一般不建议这样做。所提出的论点,例如匹配均值 0 和方差 1,以及对分布支持的考虑并不令人信服。在 Christian P. Robert 和 George Casella 的“用 R 介绍蒙特卡洛方法”的练习 2.3 中,这个生成器被称为过时的,而近似值被称为非常差
  • 还有一些令人眼花缭乱的其他想法。第 3 章,特别是第 3.4 节,在“计算机编程的艺术”卷。Donald E. Knuth 的 2 是关于随机数生成的经典参考。Brian Ripley 写了Computer Generation of Random Variables: A Tutorial,这可能很有用。还推荐罗伯特和卡塞拉提到的书,或者他们的另一本书“蒙特卡洛统计方法”中的第 2 章。

归根结底,正确实施的方法并不比使用的统一伪随机数生成器好。就个人而言,我更喜欢依赖我认为值得信赖的特殊用途库。我几乎总是依赖在 R 中直接在 R 中或通过 C/C++ 中的 API 实现的方法。显然,这不是适合所有人的解决方案,但我对其他库还不够熟悉,无法推荐替代方案。

这实际上是对 Michael Lew 的回答和 Fixee 的评论的评论,但作为答案发布是因为我在这个网站上没有评论的声誉。

十二个独立随机变量的和均匀分布在[0,1]有意思6和方差1. 换句话说,

E[i=112Xi]=i=112E[Xi]=12×12=6
var[i=112Xi]=i=112var[Xi]=12×112=1.
然后可以使用 CLT 断言 i=112Xi6 近似为标准正态分布。与 Michael Lew 和 Fixee 考虑的十个变量相比,需要额外调用两次随机数生成器,但我们避免除以10/12以获得所需的单位方差。还值得记住的是i=112Xi6只能取范围内的值[6,6]因此极端(极低概率)值与平均值相差超过6永远不会出现标准偏差。这通常是计算机和通信系统模拟中的一个问题,在这些系统中,这种非常低概率的事件非常有趣。

除了 NRH 的答案之外,如果您仍然无法从“标准正态分布”N(0,1) 生成随机样本,下面是一种很好且简单的方法(因为您提到您没有统计包,下面的功能应该可以在大多数标准编程语言中使用)。

1. 将 u 和 v 生成为 -1 到 1 范围内的两个均匀分布的随机
u = 2 r1 - 1v = 2 r2 - 1

2.计算w = u^2 + v^2如果 w > 1 则返回 1

3.return u*z and y= v*z withz= sqrt(-2ln(w)/w) 示例代码如下所示:

u = 2 * random() - 1;
v = 2 * random() - 1;
w = pow(u, 2) + pow(v, 2);
if (w < 1) {
    z = sqrt((-2 * log(w)) / w);
    x = u * z;
    y = v * z;
    }

然后使用上面的 MHR 建议来获得随机偏差N(mu, sigma^2)

当一个人将许多相似分布的随机值加在一起(我的意思是彼此相似)时,就会出现正态分布。如果将十个或更多均匀分布的随机值相加,则总和非常接近正态分布。(如果您希望它更正常,请添加十多个,但对于几乎所有目的而言,十个就足够了。)

假设您的均匀随机值均匀分布在 0 和 1 之间。总和将介于 0 和 10 之间。从总和中减去 5,所得分布的平均值将为 0。现在将结果除以标准差(接近)正态分布并将结果乘以所需的标准偏差。不幸的是,我不确定十个均匀随机偏差之和的标准偏差是多少,但如果我们幸运的话,有人会在评论中告诉我们!

我更喜欢用这些术语与学生谈论正态分布,因为在许多系统中正态分布假设的效用完全源于许多随机影响的总和导致正态分布的特性。