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


36

我从来没有上过统计学课程,所以我希望在正确的位置提问。

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

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

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


您的语言有随机数生成器吗?该生成器是仅从均匀分布生成还是从正态分布生成?
ttnphns 2011年

@ttnphns:几乎每种计算机语言都附带一个随机数生成器。它们在某些有限域上是压倒性的统一生成器。
Fixee 2011年

Answers:


33

如果可以从均值为0的给定分布,方差为1样,然后可以对从一个容易样品尺度位置变换该分布的,其具有平均和方差σ 2。如果X是一个样品从一个均值为0,方差为1的分布则 σ X + μ 是均值的样本μ和方差σ 2。因此,您要做的就是加上平均值μ之前,按标准偏差σ(方差的平方根)对变量进行缩放。μσ2X

σX+μ
μσ2σμ

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

编辑:根据评论,其他答案以及Fixee接受此答案的事实,我将提供更多有关如何使用统一变量的转换来产生正态变量的详细信息。

  • VitalStatistix在评论中已经提到的一种方法是Box-Muller方法,它采用两个独立的统一随机变量并产生两个独立的正常随机变量。francogrex提出了一种类似的方法,该方法避免了两个先验函数sincos的计算,却减少了一些模拟。
  • 完全通用的方法是通过逆分布函数转换均匀随机变量。如果均匀分布于[ 0 1 ]然后 Φ - 1Û 具有标准正态分布。尽管没有关于Φ 1的明确解析公式,但可以通过精确的数值近似来计算。R中的当前实现(最后我检查过)使用了这个想法。该方法在概念上非常简单,但需要一个精确的实施Φ - 1,这可能不是作为广泛的(其他)超越函数ü[01个]
    Φ-1个ü
    Φ-1个Φ-1个原木罪恶角色
  • 有几个答案提到了使用中心极限定理将正态分布近似为均匀随机变量平均值的可能性。通常不建议这样做。提出的参数(例如均值0和方差1匹配)以及支持分布的考虑都不令人信服。在Christian P. Robert和George Casella的“用R介绍蒙特卡罗方法”中的练习2.3中,该生成器被称为过时的,其近似值被称为非常差
  • 还有其他一些令人困惑的想法。第3章,尤其是第3.4节,在“计算机程序设计的艺术”第一卷中。Donald E. Knuth的“ 2”是有关随机数生成的经典参考。Brian Ripley写了《随机变量的计算机生成:教程》,可能会有用。还建议使用Robert和Casella提到的书,或者他们另一本书中的第2章“蒙特卡洛统计方法”。

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


(+1)对OP的良好回答和建议。
主教

18
我不确定是否要在此处进行不必要的评论,但是,如果您只能访问统一的随机数生成器,则可以使用Box-Muller变换生成独立的N(0,1)随机数。简而言之,如果U_1和U_2是来自Uniform(0,1)分布的独立绘制,则
-2日志ü1个cos2πü2
被分配为独立的N(0,1)随机变量。基本想法
-2日志ü1个2πü2
VitalStatistix

2
@Vital:不是不必要的评论;好人 Box-Muller变换可能是最容易编程的程序,并且无意间做了一些不好的事情。它不是最快的,但具有足够的竞争力。也就是说,使用已建立的代码库可能仍然更安全,尤其是因为最有可能出错的地方是如何生成统一的随机变量输入!
主教

@Vital:谢谢,这就是我想要的。如果您想将您的评论转换成答案,我会很乐意赞成。
Fixee 2011年

1
@VitalStatistix,这是一个很好的评论,看来这就是OP所要的。为什么不把它变成一个答案,或者也许在使用统一随机变量的转换的一般思想上稍作阐述。我很犹豫这样做,主要是因为Cardinal提到了这个原因,因为我不知道任何语言的默认统一生成器是否是一个好的生成器。
NRH

10

这实际上是对Michael Lew的回答和Fixee的评论,但由于我没有在此站点上的声誉发表评论,因此被发布为答案。

[01个]61个

Ë[一世=1个12X一世]=一世=1个12Ë[X一世]=12×1个2=6
变种[一世=1个12X一世]=一世=1个12变种[X一世]=12×1个12=1。
一世=1个12X一世-610/12一世=1个12X一世-6[-66]6

5

除了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.使用z= sqrt(-2ln(w)/w) 示例代码返回u * z和y = v * z 如下所示:

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)


当我在上面发布答案时,我没有注意到@vitalStatistix为您提供了Box-Muller变换算法。我上面给出的也是我想的。
francogrex 2011年

2
您能否解释从均匀分布生成正态变量的原因(而不是从算法的角度),而不仅仅是直接使用高斯/正态分布的pdf?还是完全错误?
阿伦(Arun)

4
@Arun原因之一:当您只有一个生成均匀偏差的RNG时,Marsaglia的极坐标方法非常有用。
chl

1
@Arun是最简单的方法。您也可以使用“接受拒绝”方法直接从pdf生成。我在您的网站上为您发布了一个简单的示例(因为此处的评论框中没有足够的空间)。
francogrex 2011年

4

当人们将许多相似分布的随机值相加(我是说彼此相似)时,就会出现正态分布。如果将十个或更多均匀分布的随机值相加,则总和几乎是正态分布的。(如果您希望它更加正常,则添加十个以上,但十个就几乎可以满足所有用途。)

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

我倾向于用这些术语与学生讨论正态分布,因为在许多系统中假设正态分布的效用完全源于许多随机影响之和导致正态分布的性质。


您在此处使用的是Central Limit Thm(一堆iid随机变量求和为一个正常随机变量)。我没有考虑这是因为我认为它太慢了,但是您说10足够了?这比计算日志和sin / cos和sqrt更好!
Fixee 2011年

同样,[0,1]上的均值rv的平均值为0.5,方差为1/12。如果将这些总数相加10,您将得到平均值5,方差10/12 = 5/6。
Fixee 2011年

1
从教学的角度来看,此方法提供了很好的,有用的讨论和演示。但是,我强烈不鼓励任何人在实践中使用此方法。
主教

1
日志cos

1
@Michael:声明它给出了“正确的”分布有点困难,特别是因为近似分布具有紧凑的支持,并且在许多应用中,人们确实在乎变量的生成效率。:)问题是有几个提供更好的选择。但是,我仍然认为它在教学上提供了有用的东西。
主教
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.