Чтобы моделировать нормальное распределение из набора однородных переменных, есть несколько методов:
Алгоритм Бокса-Мюллера , в котором производится выборка двух независимых равномерных переменных в и преобразование их в два независимых стандартных нормальных распределения с помощью:
метод CDF , где можно приравнять нормальный cdf к Унифицированной переменной:
и получить
Мой вопрос: что вычислительно более эффективно? Я бы подумал, что это последний метод - но большинство статей, которые я читаю, используют Бокса-Мюллера - почему?
Дополнительная информация:
Обратное значение нормального CDF известно и определяется как:
Следовательно:
normal-distribution
simulation
uniform
user2350366
источник
источник
Ответы:
С чисто вероятностной точки зрения оба подхода верны и, следовательно, эквивалентны. С алгоритмической точки зрения сравнение должно учитывать как точность, так и стоимость вычислений.
Box-Muller полагается на равномерный генератор и стоит примерно столько же, сколько и этот равномерный генератор. Как упоминалось в моем комментарии, вы можете обойтись без синус или косинус, если не без логарифма:
Общий алгоритм инверсии требует обращения к обратному нормальному cdf, например,
qnorm(runif(N))
в R, что может быть более дорогостоящим, чем приведенное выше, и, что более важно, может потерпеть неудачу в терминах точности, если только функция квантиля не является хорошо закодированной.Чтобы следить за комментариями, сделанными whuber , сравнение
rnorm(N)
иqnorm(runif(N))
имеет преимущество обратного cdf, как во время выполнения:и с точки зрения посадки в хвост:
Следуя комментарию Рэдфорда Нила в моем блоге , я хочу отметить, что по умолчанию
rnorm
в R используется метод инверсии, следовательно, приведенное выше сравнение отражает интерфейс, а не сам метод моделирования! Чтобы процитировать R документацию по RNG:источник
R 3.0.2
rowSums
qnorm(runif(N))
InverseCDF[NormalDistribution[], #] &
qnorm(runif(N))
даже на 20% быстрее, чемrnorm(N)
RNGkind(kind = NULL, normal.kind = 'Inversion');At <- microbenchmark(A <- rnorm(1e5, 0, 1), times = 100L);RNGkind(kind = NULL, normal.kind = 'Box-Muller');Bt <- microbenchmark(B <- rnorm(1e5, 0, 1), times = 100L)
я получаюmean 11.38363 median 11.18718
для инверсии иmean 13.00401 median 12.48802
для Бокса-Мюллера