模拟磁盘上的均匀分布

机器算法验证 随机生成 循环统计
2022-02-06 03:21:36

我试图模拟一个圆圈内随机点的注入,这样圆圈的任何部分都有相同的缺陷概率。如果我将圆分成等面积的矩形,我希望得到的分布的单位面积计数遵循泊松分布。

由于它只需要在圆形区域内放置点,因此我在极坐标中注入了两个均匀随机分布:R(半径)和θ(极角)。

但是在进行这种注入之后,与边缘相比,我在圆的中心明显得到了更多的点。

在此处输入图像描述

在整个圆圈中执行此注入以使点随机分布在圆圈中的正确方法是什么?

4个回答

您希望点的比例与面积成正比,而不是与原点的距离成正比。由于面积与平方距离成正比,因此生成均匀的随机区域并取其平方根;根据需要缩放结果。将其与均匀的极角相结合。

这代码快速简单,执行效率高(尤其是在并行平台上),并准确生成规定数量的点。

例子

这是R说明算法的工作代码。

n <- 1e4
rho <- sqrt(runif(n))
theta <- runif(n, 0, 2*pi)
x <- rho * cos(theta)
y <- rho * sin(theta)
plot(x, y, pch=19, cex=0.6, col="#00000020")

在此处输入图像描述

可以使用拒绝采样。这意味着我们可以从二维均匀分布中采样,并选择满足圆盘条件的样本。

这是一个例子。

x=runif(1e4,-1,1)
y=runif(1e4,-1,1)

d=data.frame(x=x,y=y)
disc_sample=d[d$x^2+d$y^2<1,]
plot(disc_sample)

在此处输入图像描述

当然,我会给你一个通用的 n 维答案,它也适用于二维情况。在三维空间中,圆盘的类似物是实心球(球体)的体积。

我将讨论两种方法。其中一个我称之为“精确”,你将在 R 中得到一个完整的解决方案。第二个我称之为启发式,这只是想法,没有提供完整的解决方案。

“精准”解决方案

我的解决方案基于Marsaglia 和 Muller 的作品基本上,它的发生是为了使归一化为其范数的高斯向量会给你一个 d 维超球面上的均匀分布点:

在此处输入图像描述

它与二维圆上均匀分布的点相同。要将其扩展到磁盘的整个表面,您需要按半径进一步缩放它们。半径的平方是从二维均匀分布,或者升幂d在 d 维度上。所以,你提升权力1/d一个均匀的随机数来获得正确分布的半径。这是 R 中二维的完整代码,您可以轻松地将其扩展到任意数量的维度:

n <- 1e4
rho <- sqrt(runif(n))
# d - # of dimensions of hyperdisk
d = 2
r = matrix(rnorm(n*d),nrow=n,ncol=d)
x = r/rep(sqrt(rowSums(r^2))/rho,1)
plot(x[,1], x[,2], pch=19, cex=0.6, col="#00000020")

在此处输入图像描述

这是 3d 案例的代码片段,即实心球:

library(scatterplot3d)
n <- 1e3
# d - # of dimensions of hyperdisk

d=3
rho <- (runif(n))^(1/d)
r = matrix(rnorm(n*d),nrow=n,ncol=d)
x = r/rep(sqrt(rowSums(r^2))/rho,1)

scatterplot3d(x[,1], x[,2], x[,3])

在此处输入图像描述

启发式方法

这种方法基于一个不太明显的事实,即当维数增加到无穷大时,单位超球面的体积与包围它的单位超立方体的体积之比会缩小到零。这可以从超球体体积的表达式中很容易地看出

Vn(R)=πn2Γ(n2+1)Rn
在这里,您可以看到前面的系数如何Rn迅速减少到零。这是与机器学习中所谓的维度诅咒有关的现象的另一种表现形式。

为什么这与我们手头的问题有关?假设,你想生成 d 个随机均匀数,这些将是 d 维超立方体内的随机点。接下来,您应用拒绝采样来选择超球面(又名 n 球)内的点:i=1dxi2<R2. 问题是对于大量的维度 d,几乎所有的点都会在球体之外!您最终会丢弃绝大多数样品。

我提出的解决方案是使用拒绝采样对中心附近的点进行过采样。事实证明,如果您从球内部观察随机均匀样本的笛卡尔坐标之一,它的分布将收敛到具有方差的高斯坐标1d+2. 因此,我们不是从立方体中均匀地选取点,而是使用高斯对笛卡尔坐标进行采样,然后对它们应用拒绝采样。这样我们就不会浪费那么多生成的随机变量。这将是重要性抽样技术的一种形式。

这是一个替代解决方案R

n <- 1e4
## r <- seq(0, 1, by=1/1000)
r <- runif(n)
rho <- sample(r, size=n, replace=T, prob=r)
theta <- runif(n, 0, 2*pi)
x <- rho * cos(theta)
y <- rho * sin(theta)
plot(x, y, pch=19, cex=0.6, col="#00000020")

在此处输入图像描述