2010-01-31 2 views
16

вероятности Дан массив размера 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 предпочитает.

+0

СИГМА вы имеете в виду стандартное отклонение? Надеюсь, вы поймете, что как только вы скажете стандартное отклонение, вы автоматически подразумеваете, что вы производите произвольные числа из обычного распределения. – ldog

+0

Большинство компьютерных номеров RNG выходят из равномерного распределения. – ldog

+0

Вы можете ответить на этот вопрос, осознав, что теорема Центрального предела может помочь: http://en.wikipedia.org/wiki/Central_limit_theorem – ldog

ответ

15

Задача, которую вы пытаетесь выполнить, равнозначна рисованию случайной точки из простого 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.

+3

На большинстве языков вы должны создавать «Случайные» только один раз, или вы получите не случайные результаты (и во многих случаях - одно и то же число снова и снова). Я также обеспокоен использованием 'log' - не могли бы вы объяснить, почему он там? – Kobi

+0

+1 для хорошей справки, но я думаю, что 'nextDouble()' уже настраивается для равномерного распределения: http://java.sun.com/javase/6/docs/api/java/util/Random.html#nextDouble() – trashgod

+0

Коби, спасибо, что указал на «новую случайную() вещь. Что касается 'log' - я редактировал свой пост, чтобы включить более подробное объяснение. – viaclectic

22

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

+0

Ницца :) не думал об этом ... תודה! –

+12

Это вводит предвзятость. Таким образом, вы не можете равномерно выбирать образец из симплекса. – dreeves

+0

@ dreeves - вы можете уточнить? –

0

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

+0

Хороший отзыв, но я считаю, что он не является родным. – dreeves

1

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

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

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

0

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

Expanding on Kobi's answer, здесь есть функция 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] 
Смежные вопросы