случайный единичный вектор в многомерном пространстве - PullRequest
20 голосов
/ 08 июня 2011

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

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

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

Ответы [ 5 ]

36 голосов
/ 10 декабря 2011

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

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).Затем вычислите величину результирующего вектора с помощью формулы Пифагора (возведите в квадрат каждое значение, добавьте квадраты и возьмите квадратный корень из результата).Наконец, разделите каждое значение на величину, чтобы получить нормализованный случайный вектор.

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

14 голосов
/ 08 июня 2011

Вы не получите равномерно распределенный ансамбль углов с алгоритмом, который вы описали. Углы будут смещены в сторону углов вашего 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
2 голосов
/ 21 января 2018

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

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

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

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

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

1 голос
/ 07 июня 2012

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

0 голосов
/ 23 апреля 2012
#define SCL1 (M_SQRT2/2)
#define SCL2 (M_SQRT2*2)

// unitrand in [-1,1].
double u = SCL1 * unitrand();
double v = SCL1 * unitrand();
double w = SCL2 * sqrt(1.0 - u*u - v*v);

double x = w * u;
double y = w * v;
double z = 1.0 - 2.0 * (u*u + v*v);
...