Генерация вероятностного распределения - PullRequest
18 голосов
/ 31 января 2010

Учитывая массив размером n Я хочу генерировать случайные вероятности для каждого индекса таким образом, чтобы Sigma(a[0]..a[n-1])=1

Один из возможных результатов может быть:

0     1     2     3     4
0.15  0.2   0.18  0.22  0.25

Еще один совершенно законный результат может быть:

0     1     2     3     4
0.01  0.01  0.96  0.01  0.01

Как я могу генерировать это легко и быстро? Ответы на любом языке в порядке, предпочтительнее Java.

Ответы [ 6 ]

22 голосов
/ 31 января 2010

Получить n случайных чисел, вычислить их сумму и нормализовать сумму до 1, разделив каждое число на сумму.

16 голосов
/ 31 января 2010

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

http://en.wikipedia.org/wiki/Simplex#Random_sampling может вам помочь.

Наивное решение может выглядеть следующим образом:

public static double[] getArray(int n)
    {
        double a[] = new double[n];
        double s = 0.0d;
        Random random = new Random();
        for (int i = 0; i < n; i++)
        {
           a [i] = 1.0d - random.nextDouble();
           a [i] = -1 * Math.log(a[i]);
           s += a[i];
        }
        for (int i = 0; i < n; i++)
        {
           a [i] /= s;
        }
        return a;
    }

Чтобы нарисовать точку равномерно из N-мерного единичного симплекса, мы должны взять вектор экспоненциально распределенных случайных величин, а затем нормализовать его по сумме этих переменных. Чтобы получить экспоненциально распределенное значение, мы берем отрицательный log равномерно распределенного значения.

1 голос
/ 14 ноября 2015

Это относительно поздно, но показать поправку к простому и прямому ответу @ Kobi, приведенному в этой статье , на которую указывает @dreeves, что делает выборку равномерной. Метод (если я это ясно понимаю) -

  1. Генерирует n-1 отличных значений из диапазона [1, 2, ..., M-1].
  2. Сортировать полученный вектор
  3. Добавьте 0 и M в качестве первого и последнего элементов результирующего вектора.
  4. Создать новый вектор путем вычисления x i - x i-1 , где i = 1,2, ... n. То есть новый вектор состоит из различий между последовательными элементами старого вектора.
  5. Разделите каждый элемент нового вектора на M. У вас равномерное распределение!

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

0 голосов
/ 09 сентября 2018
public static double[] array(int n){

    double[] a = new double[n];
    double flag = 0;

    for(int i=0;i<n;i++){
        a[i] = Math.random();
        flag += a[i];
    }

    for(int i=0;i<n;i++) a[i] /= flag;

    return a;
}

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

0 голосов
/ 02 апреля 2017

Получить n случайных чисел, рассчитать их сумму и нормализовать сумму до 1 путем деления каждого числа на сумму.

В продолжение ответа Коби , вот функция Java, которая делает именно это.

public static double[] getRandDistArray(int n)  {
    double randArray[] = new double[n];
    double sum = 0;

    // Generate n random numbers
    for (int i = 0; i < randArray.length; i++) {
        randArray[i] = Math.random();
        sum += randArray[i];
    }

    // Normalize sum to 1
    for (int i = 0; i < randArray.length; i++) {
        randArray[i] /= sum;
    }
    return randArray;
}

В тестовом прогоне getRandDistArray(5) вернул следующее

[0.1796505603694718, 0.31518724882558813, 0.15226147256596428, 0.30954417535503603, 0.043356542883939767]
0 голосов
/ 31 января 2010

Если вы хотите эффективно генерировать значения из нормального распределения, попробуйте преобразование Box Muller .

...