本着使用与正态分布的计算无关的简单代数计算的精神,我倾向于以下内容。它们是按我的想法排列的(因此需要越来越多的创造力),但是我保留了最好的(也是最令人惊讶的)。
逆转Box-Mueller技术:从每对法线(X,Y),可以将两个独立的制服构造为(在区间上)和(在间隔)。[ - π ,π ] EXP (- (X 2 + ý 2)/ 2 )[ 0 ,1 ]atan2(Y,X)[−π,π]exp(−(X2+Y2)/2)[0,1]
以两个为一组的法线并求和它们的平方,以获得变量的序列。从对获得的表达式 Ÿ 1,Ÿ 2,... ,ÿ 我,...χ22Y1,Y2,…,Yi,…
Xi=Y2iY2i−1+Y2i
将具有一个分布,这是统一的。Beta(1,1)
应该清楚这仅需要简单的基本算法。
由于标准双变量正态分布中四对样本的Pearson相关系数的精确分布均匀地分布在,因此我们可以简单地将正态分为四对(每组中有八个值)每个集合)并返回这些对的相关系数。(这涉及简单的算术加两个平方根运算。)[−1,1]
自古以来就知道球体的圆柱投影(三空间中的一个表面)是等面积的。这意味着在球体上均匀分布的投影中,水平坐标(对应于经度)和垂直坐标(对应于纬度)都将具有均匀分布。由于三元标准正态分布是球对称的,因此其在球体上的投影是均匀的。 获得经度与Box-Mueller方法(qv)中的角度本质上是相同的计算,但是投影纬度是新的。球体上的投影仅将三倍坐标归一化并且在那个点(x,y,z)z是预计的纬度。因此,将正态变量分为三个组,分别为并进行计算X3i−2,X3i−1,X3i
X3iX23i−2+X23i−1+X23i−−−−−−−−−−−−−−−−√
对于。i=1,2,3,…
由于大多数计算系统中表示数字的二进制的,均匀的数生成通常通过产生均匀分布的开始整数之间和2 32 - 1(或一些高功率2涉及计算机字长度)根据需要和重新缩放它们。这样的整数在内部表示为32个二进制数字的字符串。我们可以通过将Normal变量与其中位数进行比较来获得独立的随机位。因此,足以将Normal变量分成大小等于所需位数的组,将每个位与其平均值进行比较,然后将结果的真/假结果序列组合为二进制数。写k0232−1232k为位的数目和的符号(即,H ^ (X )= 1时X > 0和ħ (X )= 0否则)我们可以表示在所得到的归一化的统一值[ 0 ,1 )与式HH(x)=1x>0H(x)=0[0,1)
∑j=0k−1H(Xki−j)2−j−1.
变量可以从中位数为0的任何连续分布(例如标准正态)中得出。它们以k为一组进行处理,每组产生一个这样的伪均匀值。Xn0k
拒绝抽样是一种从任意分布中提取随机变量的标准,灵活,强大的方法。假设目标分布具有PDF 。值ÿ根据绘制另一个与PDF分布克。在拒绝步骤中,独立于Y绘制介于0和g (Y )之间的统一值U,并将其与f (Y )比较:如果较小,则YfYgU0g(Y)Yf(Y)Y保留,否则重复该过程。但是,这种方法似乎是循环的:我们如何使用需要统一变量的过程生成统一变量?
答案是我们实际上不需要统一的变量即可执行拒绝步骤。取而代之(假设),我们可以翻转一个公平的硬币来随机获得0或1。这将在均匀变量的二进制表示被解释为第一比特ü在区间[ 0 ,1 )。当结果是0,则表示0 ≤ Ü < 1 / 2 ; 否则,1 / 2 ≤ Ú < 1。 g(Y)≠001U[0,1)00≤U<1/21/2≤U<1一半的时间,这足以决定排斥步骤:如果,但在硬币是0,ÿ应该被接受; 如果˚F (Ý )/克(Ý )< 1 / 2,但硬币是1,ÿ应被拒绝; 否则,我们需要再次掷硬币以获得U的下一位。因为-无论f (Yf(Y)/g(Y)≥1/20Yf(Y)/g(Y)<1/21YU具有-有一个 1 / 2的每个翻转之后停止的机会,翻转的预期数量仅 1 / 2 (1 )+ 1 / 4 (2 )+ 1 / 8 (3 )+ ⋯ + 2 − n(n )+ ⋯ = 2。f(Y)/g(Y)1/21/2(1)+1/4(2)+1/8(3)+⋯+2−n(n)+⋯=2
如果预期的拒绝数量很小,则拒绝采样可能是值得的(并且很有效)。我们可以通过在法线PDF下安装最大可能的矩形(表示均匀分布)来完成此操作。
用微积分来优化矩形的面积,你会发现,它的终点应该位于在,其中,其高度相当于EXP (- 1 / 2 )/ √±1,使得它的面积稍大于0.48。通过使用该标准正态密度克和拒绝所有值在区间外[-1,1]自动,否则应用程序拒绝,我们将获得均匀个变量[-1,1]有效地:exp(−1/2)/2π−−√≈0.2419710.48g[−1,1][−1,1]
在一小部分的时候,正态变量谎言超出[ - 1 ,1 ]和被立即拒绝。(Φ是标准的普通CDF。)2Φ(−1)≈0.317[−1,1]Φ
在其余时间中,必须遵循二进制拒绝程序,平均需要两个以上的Normal变量。
总体过程需要的平均的步骤。1/(2exp(−1/2)/2π−−√)≈2.07
产生每个均匀结果所需的正态变量的预期数量得出
2eπ−−−√(1−2Φ(−1))≈2.82137.
尽管这非常有效,但是请注意,(1)普通PDF的计算需要计算指数,并且(2 )必须一劳永逸地预先计算值。它仍然比Box-Mueller方法(qv)少一些计算。Φ(−1)
均匀分布的顺序统计具有指数差距。由于两个法线的平方和(均值为零)是指数的,因此我们可以通过对这些法线对的平方求和,计算这些法线对的累积和,重新缩放结果以使其落在区间中来生成独立制服的实现。[ 0 ,1 ],和滴最后一个(其将总是等于1)。这是一种令人愉悦的方法,因为它只需要平方,求和和(最后)一次除法。n[0,1]1
该值会自动按升序排列。如果需要这样的排序,则此方法在计算上避免了排序的O (n log (n ))成本,在计算上优于所有其他方法。但是,如果需要一系列独立的制服,那么随机地对这n个值进行排序就可以了。由于(如在Box-Mueller方法中所见,qv)每对法线的比率与每对平方的平方和无关,因此我们已经有了获取随机排列的方法:按相应比率对累积和进行排序。(如果nnO(nlog(n))nn如果非常大,则此过程可以在较小的组中进行,而效率损失很小,因为每个组仅需要2 (k + 1 )个法线即可创建k个均匀值。对于固定ķ,渐近计算成本因此是ø (Ñ 日志(ķ )) = Ô (Ñ ),需要2 Ñ (1 + 1 / ķ )正常个变量,以生成Ñ均匀的值。)k2(k+1)kkO(nlog(k))O(n)2n(1+1/k)n
作为一个极好的近似,任何具有大标准偏差的正态变量在较小值的范围内看起来都是均匀的。当滚动这个分布到范围(通过取只值的小数部分),我们由此获得的分布即对于所有实际目的,是均匀的。这是非常高效的,需要所有方法中最简单的一种:将每个Normal变量舍入到最接近的整数并保留多余的值。 当我们研究一个实际的实现时,这种方法的简单性变得引人注目:[0,1]R
rnorm(n, sd=10) %% 1
可靠地产生n
在范围均匀值在刚刚的成本普通变元,并且几乎没有计算。[0,1]n
(即使标准偏差为,该近似值的PDF与均匀PDF的差异也如下图所示,差异不超过10 8的十分之一!要可靠地进行检测,将需要10 16个值的样本- 这已经超出了任何标准随机性测试的能力。标准偏差越大,不均匀性就越小,甚至无法计算出来。例如,如代码中所示,SD为10,则均匀性的最大偏差PDF只有10 - 857。)110810161010−857
在每种情况下,“具有已知参数”的法线变量都可以轻松地进行重新定型,并重新缩放为上述假定的标准法线。之后,可以对所得的均匀分布值进行重新定位和重新缩放以覆盖任何所需的间隔。这些仅需要基本的算术运算。
以下R
代码证明了这些构造的简便性,其中大多数代码仅使用一两行。其正确性是通过将得到的近似均匀目睹基于直方图在每种情况下独立的值(需要用于所有七个模拟大约12秒)。作为参考-如果您担心这些图中任何一个中出现的变化量- 末尾包含使用统一随机数生成器模拟的统一值直方图。100,000R
所有这些模拟,使用均匀性测试基于测试1000个箱; 没有一个可以被认为是明显不均匀的(最低的p值为3 % -对于由的实际均匀数生成器产生的结果!)。χ210003%R
set.seed(17)
n <- 1e5
y <- matrix(rnorm(floor(n/2)*2), nrow=2)
x <- c(atan2(y[2,], y[1,])/(2*pi) + 1/2, exp(-(y[1,]^2+y[2,]^2)/2))
hist(x, main="Box-Mueller")
y <- apply(array(rnorm(4*n), c(2,2,n)), c(3,2), function(z) sum(z^2))
x <- y[,2] / (y[,1]+y[,2])
hist(x, main="Beta")
x <- apply(array(rnorm(8*n), c(4,2,n)), 3, function(y) cor(y[,1], y[,2]))
hist(x, main="Correlation")
n.bits <- 32; x <- (2^-(1:n.bits)) %*% matrix(rnorm(n*n.bits) > 0, n.bits)
hist(x, main="Binary")
y <- matrix(rnorm(n*3), 3)
x <- y[1, ] / sqrt(apply(y, 2, function(x) sum(x^2)))
hist(x, main="Equal area")
accept <- function(p) { # Using random normals, return TRUE with chance `p`
p.bit <- x <- 0
while(p.bit == x) {
p.bit <- p >= 1/2
x <- rnorm(1) >= 0
p <- (2*p) %% 1
}
return(x == 0)
}
y <- rnorm(ceiling(n * sqrt(exp(1)*pi/2))) # This aims to produce `n` uniforms
y <- y[abs(y) < 1]
x <- y[sapply(y, function(x) accept(exp((x^2-1)/2)))]
hist(x, main="Rejection")
y <- matrix(rnorm(2*(n+1))^2, 2)
x <- cumsum(y)[seq(2, 2*(n+1), 2)]
x <- x[-(n+1)] / x[n+1]
x <- x[order(y[2,-(n+1)]/y[1,-(n+1)])]
hist(x, main="Ordered")
x <- rnorm(n) %% 1 # (Use SD of 5 or greater in practice)
hist(x, main="Modular")
x <- runif(n) # Reference distribution
hist(x, main="Uniform")