Лучший способ создать равномерно распределенные случайные точки в d
-размерном шаре - это думать о полярных координатах (направлениях, а не местах). Код приведен ниже.
- Выберите случайную точку на единичном шаре с равномерным распределением.
- Выберите случайный радиус, где вероятность радиуса соответствует площадь поверхности шара с таким радиусом в
d
размерах.
Этот процесс выбора (1) сделает все направления одинаково вероятными, и (2) сделает все точкина поверхности шариков внутри блока шаров одинаково вероятно.Это создаст желаемое равномерно случайное распределение по всей внутренней части шара.
Выбор случайного направления (на единичном шаре)
Для достижения (1) мы можем случайным образом сгенерироватьвектор из d
независимых отрисовок гауссовского распределения, нормированного на единицу длины. Это работает , потому что распределение Гаусса имеет функцию распределения вероятностей (PDF) с x^2
в показателе степени.Это означает, что совместное распределение (для независимых случайных величин это умножение их PDF-файлов) будет иметь (x_1^2 + x_2^2 + ... + x_d^2)
в показателе степени.Обратите внимание, что это напоминает определение сферы в d-измерениях, а это означает, что совместное распределение d
независимых выборок из гауссовского распределения инвариантно к вращению (векторы равномерны по сфере).
Вот то, что 200случайные точки, сгенерированные в 2D, выглядят следующим образом.
Picking a random radius (with appropriate probability)
In order to achieve (2) we can generate a radius by using the inverse of a cumulative distribution function (CDF) that corresponds to the surface area of a ball in d
dimensions with radius r
. We know that the площадь поверхности n-шара пропорциональна r^d
, что означает, что мы можем использовать это в диапазоне [0,1]
в качестве CDF.Теперь случайная выборка генерируется путем сопоставления случайных чисел в диапазоне от [0,1]
до инверсии r^(1/d)
.
Вот изображение CDF x^2
(для двух измерений), случайные сгенерированные числа в [0,1]
будут сопоставлены с соответствующей координатой x на этой кривой.(например, .1
➞ .317
)
Code for the above
Finally, here is some Python code (assumes you have NumPy installed) that computes all of the above.
# 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 случайных точек, сгенерированных с помощью вышеуказанного кода.