2016-12-26 5 views
1

Я пытаюсь генерировать случайные числа из пользовательского дистрибутива, я уже нашел этот вопрос: Simulate from an (arbitrary) continuous probability distribution , но, к сожалению, это не помогает мне, так как предложенный там подход требует формулы для функции распределения. Мое распределение представляет собой комбинацию нескольких однородных распределений, в основном функция распределения выглядит как гистограмма. Примером может быть:Генерировать случайное число из пользовательского дистрибутива

f(x) = { 
    0  for x < 1 
    0.5 for 1 <= x < 2 
    0.25 for 2 <= x < 4 
    0  for 4 <= x 
} 

ответ

5

Вам просто нужно инвертировать метод КОР:

samplef <- function (n) { 
    x <- runif(n) 
    ifelse(x < 0.5, 2 * x + 1, 4 * x) 
    } 

Compute CDF себя, чтобы убедиться, что:

F(x) = 0     x < 1 
     0.5 * x - 0.5  1 < x < 2 
     0.25 * x   2 < x < 4 
     1     x > 4 

так, что ее обратное:

invF(x) = 2 * x + 1  0 < x < 0.5 
      4 * x   0.5 < x < 1 
+0

Спасибо, это отлично работает. Можете ли вы объяснить, почему мне нужно обращать cdf? –

+0

ohhhh теперь я получаю его, x <- runif (n) ifelse (x <0.5, 2 * x + 1, 4 * x) это две строки (я все время забываю, что мне не нужно, в R) Сначала вы генерируете равномерное [0,1], а затем отобразить его. Еще раз спасибо –

1

Вы можете комбинировать различные e методы отбора проб от discrete distributions с непрерывной однородностью.

То есть, имитирует из целочисленной части Y = [X] вашей переменной, которая имеет дискретное распределение с вероятностью, равной вероятности быть в каждом интервале (например, посредством метода таблицы - aka метод псевдонима) , а затем просто добавьте случайную однородную [0,1 $, X = Y + U.

В вашем примере у вас есть Y, принимающий значения 1,2,3 с вероятностью 0,5,0,25 и 0,25 (что эквивалентно выборке 1,1,2,3 с равной вероятностью), а затем добавьте случайную униформу.

Если ваша «гистограмма» действительно велика, это может быть очень быстрый подход.

В R можно сделать простой (если не особенно эффективно) версию этого через

sample(c(1,1,2,3))+runif(1) 

или

sample(c(1,1,2,3),n,replace=TRUE)+runif(n) 

и вообще можно использовать аргумент вероятности весов в sample.

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

Это говорит о том, что даже с использованием вышеуказанного кода со значительно «большой» гистограммой - от десятков до сотен бункеров - этот подход кажется даже на моем довольно неописуемом ноутбуке, чтобы иметь возможность генерировать миллион случайных значений в ну под второй, так что для многих приложений это будет хорошо.

+0

Спасибо, ваш подход кажется очень интуитивным, если все «бункеры» имеют одинаковую ширину. У меня возникли проблемы с пониманием вашего образца линии (c (1,1,2,3), n, replace = TRUE) + runif (n) –

+0

Кстати, вы можете использовать вероятности с помощью такой функции: sample (c (1 , 2, 3), размер = 3000000, replace = TRUE, prob = c (0,5, 0,25, 0.25)), тогда вам не нужно использовать обходной путь с двумя 1s :-) –

+0

Часть (1,1, ...) состоит в том, что 1 ячейка в два раза чаще, если образец хорошо реализован, он должен быть быстрее таким образом чем более общее взвешивание вероятности. Часть ... 2,3) разделяет 2-4-бит, так что они имеют одинаковую ширину. Опять же, это для скорости. Если высоты и ширина бункера не являются всеми рациональными числами (хотя ничто в вопросе не говорит об этом), вам понадобится немного более медленный, но более общий подход, который все еще может быть сделан путем надлежащего использования функций 'sample' и' runif' –