Реализуйте функцию плотности - PullRequest
1 голос
/ 27 апреля 2019

Я просматриваю свою книгу, в которой говорится, что «Напишите алгоритм выборки для этой функции плотности»

y=x^2+(2/3)*x+1/3; 0 < ? < 1

Или я могу использовать Монте-Карло? Любая помощь будет оценена!

Ответы [ 2 ]

0 голосов
/ 28 апреля 2019

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

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

Другой вариант - использовать метод принятия / отклонения . После проверки производной становится ясно, что ваша плотность является выпуклой, поэтому легко создать ограничивающую функцию b(x), нарисовав прямую линию от f(0) до f(1). Это дает b(x) = 1/3 + 5x/3. Эта ограничивающая функция имеет область 7/6, в то время как ваша f(x) имеет область 1, поскольку она является действительной плотностью. Следовательно, 6/7 точек, сгенерированных равномерно при b(x), также попадут под f(x), и только 1 из 7 попыток потерпит неудачу в схеме отказа. Вот сюжет f(x) и b(x):

Plot of f(x) and b(x) showing relatively tight bounding

Поскольку b(x) является линейным, легко генерировать значения x, используя его в качестве распределения после масштабирования до 6/7, чтобы сделать его действительной функцией распределения. Алгоритм, выраженный в псевдокоде, затем становится:

function generate():
  while TRUE:
    x <- (sqrt(1 + 35 * U(0,1)) - 1) / 5     # inverse CDF transform of b(x)
    if U(0, b(x)) <= f(x):
      return x
  end while
end function

, где U(a,b) означает генерацию значения, равномерно распределенного между a и b, f(x) - ваша плотность, а b(x) - ограничивающая функция, описанная выше.

Я реализовал алгоритм, описанный выше, чтобы сгенерировать 100 000 возможных значений, из которых 14 199 (~ 1/7) были отклонены, как и ожидалось. Конечные результаты представлены на следующей гистограмме, которую вы можете сравнить с f(x) на графике выше.

Histogram of generated data having density f(x)

0 голосов
/ 27 апреля 2019

Я предполагаю, что у вас есть функция y (x), которая принимает значение в диапазоне [0,1] и возвращает значение y.Вам просто нужно указать случайное значение x и вернуть соответствующее значение y.

def getSample():
  #get uniform random number
  x = numpy.random.random()

  #sample my custom function
  return y(x)
...