在d-dimension 球中生成均匀分布的随机点的最佳方法似乎是考虑极坐标(方向而不是位置)。 代码如下。
- 在单位球上随机选取一个分布均匀的点。
- 选择一个随机半径,其中半径的可能性对应于该半径在
d 维度中的球的表面积。
此选择过程将 (1) 使所有方向均等,并且 (2) 使单位球内球表面上的所有点均等可能。这将在球的整个内部产生我们想要的均匀随机分布。
选择一个随机方向(在单位球上)
为了实现(1),我们可以从d 独立绘制的高斯分布中随机生成一个向量,该高斯分布归一化为单位长度。 This works 因为高斯分布具有概率分布函数 (PDF),x^2 在指数中。这意味着联合分布(对于独立随机变量,这是它们的 PDF 的乘积)将在指数中具有 (x_1^2 + x_2^2 + ... + x_d^2)。请注意,这类似于 d 维球体的定义,这意味着来自高斯分布的d 独立样本的联合分布对于旋转是不变的(向量在球体上是均匀的)。
这是在 2D 中生成的 200 个随机点的样子。
选择一个随机半径(以适当的概率)
为了实现 (2),我们可以使用累积分布函数 (CDF) 的逆函数生成半径,该函数对应于半径为 d 的球的表面积r。我们知道surface area of an n-ball 与r^d 成正比,这意味着我们可以在[0,1] 范围内使用它作为CDF。现在,通过将[0,1] 范围内的随机数映射到逆r^(1/d),生成一个随机样本。
这是x^2(二维)CDF 的视觉效果,[0,1] 中的随机生成数字将映射到该曲线上相应的 x 坐标。 (例如.1 ➞ .317)
以上代码
最后,这里有一些 Python 代码(假设您安装了 NumPy),用于计算上述所有内容。
# Generate "num_points" random points in "dimension" that have uniform
# probability over the unit ball scaled by "radius" (length of points
# are in range [0, "radius"]).
def random_ball(num_points, dimension, radius=1):
from numpy import random, linalg
# First generate random directions by normalizing the length of a
# vector of random-normal values (these distribute evenly on ball).
random_directions = random.normal(size=(dimension,num_points))
random_directions /= linalg.norm(random_directions, axis=0)
# Second generate a random radius with probability proportional to
# the surface area of a ball with a given radius.
random_radii = random.random(num_points) ** (1/dimension)
# Return the list of random (direction & length) points.
return radius * (random_directions * random_radii).T
为了后代,这里是使用上述代码生成的 5000 个随机点的视觉效果。