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)