случайный единичный вектор в многомерном пространстве

Я работаю над алгоритмом интеллектуального анализа данных, в котором я хочу выбрать случайное направление из определенной точки в пространстве функций.

Если я выберу случайное число для каждого из n измерений из [-1,1], а затем нормализую вектор до длины 1, получу ли я равномерное распределение по всем возможным направлениям?

Я говорю здесь только теоретически, поскольку случайные числа, сгенерированные компьютером, на самом деле не случайны.


person Matt    schedule 08.06.2011    source источник


Ответы (5)


Один простой трюк - выбрать каждое измерение из гауссовского распределения, а затем нормализовать:

from random import gauss

def make_rand_vector(dims):
    vec = [gauss(0, 1) for i in range(dims)]
    mag = sum(x**2 for x in vec) ** .5
    return [x/mag for x in vec]

Например, если вам нужен 7-мерный случайный вектор, выберите 7 случайных значений (из распределения Гаусса со средним 0 и стандартным отклонением 1). Затем вычислите величину результирующего вектора, используя формулу Пифагора (возведите каждое значение в квадрат, сложите квадраты и извлеките квадратный корень из результата). Наконец, разделите каждое значение на величину, чтобы получить нормализованный случайный вектор.

Если у вас большое количество измерений, то у этого есть сильное преимущество - всегда работать немедленно, а генерация случайных векторов до тех пор, пока вы не найдете тот, который имеет величину меньше единицы, приведет к тому, что ваш компьютер просто зависнет в более чем дюжине измерений или около того, потому что вероятность того, что любой из них будет квалифицирован, становится исчезающе мала.

person Bram Cohen    schedule 10.12.2011
comment
Хороший! Спасибо за дополнительное предложение. - person Matt; 10.12.2011
comment
Кстати, вот как ускоряют boost.org/doc/ libs / 1_47_0 / boost / random / uniform_on_sphere.hpp реализует его. ;) - person Jorge Leitao; 13.11.2012
comment
Думаю, это лучший ответ! Однако есть небольшая вероятность, что вы будете получать нулевой вектор (и, следовательно, ошибку деления на ноль) время от времени. - person Kip; 27.02.2013
comment
Вот справка о том, почему этот метод верен mathworld.wolfram.com/HyperspherePointPicking.html - person yoavram; 09.10.2013
comment
Краткое объяснение того, почему это работает: вероятность P нахождения точки в заданном ‹x, y› равна P (x) * P (y). Гауссово распределение имеет примерно форму e ^ (- x ^ 2), поэтому e ^ (- x ^ 2) * e ^ (- y ^ 2) равно e ^ (- (x ^ 2 + y ^ 2)). Это функция только расстояния точки от начала координат, поэтому результирующее распределение является радиально-симметричным. Это легко обобщается на более высокие измерения. - person mindoftea; 20.08.2014
comment
Дополнительное примечание: преобразование Бокса – Мюллера может использоваться для генерации независимых пар нормально распределенных переменных из независимых пар равномерно распределенных (без «потерь»). - person Rhubbarb; 13.10.2014
comment
с numpy это будет vec = numpy.random.randn(dims); return vec / numpy.linalg.norm(vec) - person stav; 17.06.2017

Вы не получите равномерно распределенный ансамбль углов с помощью описанного вами алгоритма. Углы будут смещены в сторону углов вашего n-мерного гиперкуба.

Это можно исправить, удалив все точки, находящиеся на расстоянии больше 1 от начала координат. Тогда вы имеете дело со сферическим, а не кубическим (n-мерным) объемом, и ваш набор углов должен быть равномерно распределен по пространству образца.

Псевдокод:

Пусть n - количество измерений, K - желаемое количество векторов:

vec_count=0
while vec_count < K
   generate n uniformly distributed values a[0..n-1] over [-1, 1]
   r_squared = sum over i=0,n-1 of a[i]^2
   if 0 < r_squared <= 1.0
      b[i] = a[i]/sqrt(r_squared)  ; normalize to length of 1
      add vector b[0..n-1] to output list
      vec_count = vec_count + 1
   else
      reject this sample
end while
person Jim Lewis    schedule 08.06.2011
comment
Вот что меня волновало. Я просто не смог формализовать это в своей голове, как вы описали. Интуитивно я знаю, что хочу, чтобы мои возможные случайные векторы описывали круг. Я просто не вижу, как это реализовать в коде. - person Matt; 08.06.2011
comment
@Matt: Я немного расширил свой ответ, надеюсь, что это поможет. - person Jim Lewis; 08.06.2011
comment
Зачем вам использовать алгоритм с недетерминированным временем выполнения И ветвью, если вы можете решить эту проблему с помощью выражения в закрытой форме? - person John Shedletsky; 13.03.2013

У меня был точно такой же вопрос при разработке алгоритма машинного обучения.
Я пришел к тому же выводу, что и Джим Льюис, нарисовав образцы для двумерного случая и построив результирующее распределение угла.

Кроме того, если вы попытаетесь получить распределение плотности для направления в 2d, когда вы будете рисовать случайным образом из [-1,1] для осей x и y, вы увидите, что:

f_X(x) = 1/(4*cos²(x)), если 0 ‹x‹ 45⁰
и
f_X(x) = 1/(4*sin²(x)), если x> 45⁰

где x - угол, а f_X - распределение плотности вероятности.

Я написал об этом здесь: https://aerodatablog.wordpress.com/2018/01/14/random-hyperplanes/

person cmhteixeira    schedule 21.01.2018

Существует ускоренная реализация алгоритма, который выбирает образцы из нормальных распределений: random :: uniform_on_sphere

person killogre    schedule 07.06.2012

person    schedule
comment
Для таких немеханических парней, как я, «Код больше нет» трудно читать. Любые комментарии о том, что он делает, почему это лучше, чем принятый ответ или что-то в этом роде? - person Nikana Reklawyks; 27.10.2012