Random 加随机数逼近正态分布

Random 加随机数逼近正态分布,random,probability,normal-distribution,Random,Probability,Normal Distribution,我想生成一些正态分布的随机数。它不是关键任务,所以一个简单的算法就足够了。然后我想提供我自己的平均值和标准偏差 根据我所读到的,根据中心极限定理,我应该能够通过将随机数相加来近似正态分布的随机数 例如: rand()+rand()+rand()+rand()+rand()+rand() 其中,rand() 这是一个合理的近似值。(我知道技术上它是0≤ rand()

我想生成一些正态分布的随机数。它不是关键任务,所以一个简单的算法就足够了。然后我想提供我自己的平均值和标准偏差

根据我所读到的,根据中心极限定理,我应该能够通过将随机数相加来近似正态分布的随机数

例如:

rand()+rand()+rand()+rand()+rand()+rand()
其中,
rand()
这是一个合理的近似值。(我知道技术上它是
0≤ rand()<1

预期的平均值是
6*0.5
,因此我用如下方法得到了期望的平均值:

(rand()+rand()+rand()+rand()+rand()+rand()-3) + mean
但是标准差是多少呢

一旦我知道了这一点,设定一个任意的标准偏差仅仅是一个乘法问题吗

更新

通过实验,我发现

(rand()+rand()+rand()+rand()+rand()+rand()-3)*sqrt(2)*sd+mean
给我一组数据和期望的标准偏差和平均值。我已经在一个1000万行的数据库(PostgreSQL)中测试了这一点,使用了
stddev()
avg()
聚合函数,典型结果接近小数点后2位,这还不算太糟糕

我不知道为什么涉及到
sqrt(2)

解决方案

好的,感谢下面的塞韦林·帕帕德乌斯,我有一个答案

我可以通过以下方式产生合理的结果:

(rand() + … + rand() - n/2) / sqrt(n/12) * sd + mean

其中
n
是我准备进行的
rand()调用的次数。

标准偏差定义如下:

其中,您迭代表示为
xi
N
值,并使用平均值(
xbar
)。一些JavaScript伪代码如下所示:

var values = [...];
for(var i = 0, var mean; i < values.length; i++) {
   mean += values[i];
}
mean /= values.length;
for(var i = 0, var standardDev; i < values.length) {
   standardDev += Math.pow(values[i] - mean, 2);
}
standardDev = Math.sqrt(standardDev / (values.length - 1));
var值=[…];
对于(var i=0,var均值;i

从理论上讲,一个好的RNG应该以一种非常平坦的方式偏离,这表明RNG范围内所有值的可能性都相等。

如果使用Python,可以使用
[numpy][1]

import numpy
numpy.random.randn()
根据我所读到的,根据中心极限定理,我应该能够通过将随机数相加来近似正态分布的随机数

这是正确的做法。唯一的问题是仔细分析你丢失的尾巴

<>我们考虑使<代码> n(0,1)< /代码>高斯分布,平均0,STD偏差1。然后,任何其他高斯
N(\mu,\sigma)
都只是缩放和从
N(0,1)
移动

因此,针对
G(0,1)
(这是
N(0,1)
的近似值)提出的算法是

其中
U(0,1)
在[0,1]范围内。让我们看看平均值

E(G(0,1)) = 6*E(U(1,0)) = 6*0.5 = 3
这正是你得到的。所以,要得到G(0,1)
的0平均值,我们必须减去3。现在让我们检查G(0,1)的方差,我们必须使它等于1

V(G(0,1)) = 6*V(U(1,0)) = 6*(1/12) = 1/2
标准偏差(σ)是方差的平方根,所以要使其为1,必须除以sqrt(1/2)

所以,最后的表达是

G(0,1) = (U(0,1) + U(0,1) + U(0,1) + U(0,1) + U(0,1) + U(0,1) - 3)/sqrt(1/2)
它是
N(0,1)
的相当好的近似

我不知道为什么sqrt(2)会牵涉其中

除以sqrt(1/2)与乘以sqrt(2)是一样的——现在我希望您知道它的来源

一些简单的推论-对于其他一些
n
U(0,1)的和,方差乘数将包括术语sqrt(n/12)

另一个简单的推论——因为V(U(0,1))等于1/12,所以求十二个U(0,1)的和不需要任何乘法器

G(0,1) = Sum_1^12 U(0,1) - 6
实际上,在一些旧的抽样食谱书/论文中经常引用

您可能还想看看相关的和

更新

我考虑过简化这个方法。假设我们想要求
U(0,1)
的偶数之和,那么
n=2m
。再次,我们将
G(0,1)
作为
n(0,1)

让我们把它改写为

G(0,1) = (Sum_1^m U(0,1) - (m - Sum_1^m U(0,1)))/sqrt(m/6) =
       = (Sum_1^m U(0,1) - Sum_1^m(1 - U(0,1)))/sqrt(m/6)
由于这个事实,
1-U(0,1)
U(0,1)
具有相同的分布,我们可以 以对称形式写入
G(0,1)

G(0,1) = (Sum_1^m U(0,1) - Sum_1^m U(0,1))/sqrt(m/6) =
       = Sum_1^m (U(0,1) - U(0,1)) / sqrt(m/6)

求和随机数提供了一个最大值为平均值两倍的分布,因此严重限制了方法。似乎无法正确地近似正态分布。

对不起…?numpy?请不要这样做。中心极限定理是一个渐进结果,6!=无穷大。你将无法生成任何具有m的值振幅大于3,标准偏差为sqrt(2)这是2.12个标准偏差,它将先验地排除3.4%的可能值,并相应地扭曲生成值的概率。它在计算上也比现成的精确技术更昂贵。请参阅数学正确方法的示例。@pjs Marsaglia或Box Muller可能在b但是它们需要log()和/或三角函数,这在sql中是不可用的。虽然对我来说求和6u(0,1)可能有点低,但对于简单的N(0,1)采样,求和12可能是一个oksolution@SeverinPappadeux似乎与此相矛盾。@pjs这很好-但它以前没有log()和类似的功能。很明显,这是特定于供应商的扩展,它们甚至被命名为differently@SeverinPappadeux谢谢你的编辑。我想我应该让你知道我已经删除了SQL标记,因为我正在寻找一个更通用的解决方案,它可能适用于任何编码环境。我现在需要的是一个数据库,但我也很感兴趣一般来说,参考文献很旧是有原因的。这被认为是一个非常糟糕的主意,比其他许多算法更不精确,也更昂贵。我认为这是一个好主意
G(0,1) = (Sum_1^m U(0,1) - (m - Sum_1^m U(0,1)))/sqrt(m/6) =
       = (Sum_1^m U(0,1) - Sum_1^m(1 - U(0,1)))/sqrt(m/6)
G(0,1) = (Sum_1^m U(0,1) - Sum_1^m U(0,1))/sqrt(m/6) =
       = Sum_1^m (U(0,1) - U(0,1)) / sqrt(m/6)