Мой вопрос вдохновлен встроенным экспоненциальным генератором случайных чисел R , функцией rexp()
. При попытке генерировать экспоненциально распределенные случайные числа многие учебники рекомендуют метод обратного преобразования, описанный на этой странице Википедии . Я знаю, что есть другие методы для решения этой задачи. В частности, исходный код R использует алгоритм, изложенный в статье Аренса и Дитера (1972) .
Я убедил себя, что метод Аренса-Дитера (AD) является правильным. Тем не менее, я не вижу преимущества использования их метода по сравнению с методом обратного преобразования (IT). AD не только сложнее в реализации, чем IT. Похоже, выигрыша в скорости тоже нет. Вот мой код R для сравнения обоих методов с последующими результатами.
invTrans <- function(n)
-log(runif(n))
print("For the inverse transform:")
print(system.time(invTrans(1e8)))
print("For the Ahrens-Dieter algorithm:")
print(system.time(rexp(1e8)))
Полученные результаты:
[1] "For the inverse transform:"
user system elapsed
4.227 0.266 4.597
[1] "For the Ahrens-Dieter algorithm:"
user system elapsed
4.919 0.265 5.213
Сравнивая код для двух методов, AD рисует как минимум два одинаковых случайных числа (с функцией Cunif_rand()
), чтобы получить одно экспоненциальное случайное число. Этому нужно только одно равномерное случайное число. Предположительно, основная команда R отказалась от внедрения IT, поскольку предположила, что логарифм может быть медленнее, чем генерация более однородных случайных чисел. Я понимаю, что скорость взятия логарифмов может зависеть от машины, но, по крайней мере, для меня все наоборот. Возможно, есть проблемы, связанные с числовой точностью ИТ, связанные с сингулярностью логарифма при 0? Но тогда
исходный код R sexp.cпоказывает, что реализация AD также теряет некоторую числовую точность, потому что следующая часть кода C удаляет начальные биты из единого случайного числа u .
double u = unif_rand();
while(u <= 0. || u >= 1.) u = unif_rand();
for (;;) {
u += u;
if (u > 1.)
break;
a += q[0];
}
u -= 1.;
U позже переработаны в виде однородного случайного числа в остальной части sexp.c . Пока что кажется, что
- ЭТО легче кодировать,
- Это быстрее, и
- И IT, и AD, возможно, теряют числовую точность.
Я был бы очень признателен, если бы кто-то мог объяснить, почему R по-прежнему использует AD как единственный доступный вариант rexp()
.
источник
rexp(n)
было бы узкое место, разница в скорости не является сильным аргументом в пользу перемен (по крайней мере, для меня). Я мог бы больше беспокоиться о числовой точности, хотя мне не ясно, какой из них был бы более численно надежным.Ответы:
На моем компьютере (простите мой французский!):
обратное преобразование делает хуже. Но вы должны следить за изменчивостью. Введение параметра скорости приводит к еще большей изменчивости для обратного преобразования:
Вот сравнение с использованием
rbenchmark
:Таким образом, пробег все еще варьируется, в зависимости от масштаба!
источник
microbenchmark
вместо этого?rexp
-log(runif())
R
log
runif
Это просто цитирование статьи в разделе «Алгоритм LG: (метод логарифма)»:
Таким образом, похоже, что авторы выбрали другие методы, чтобы избежать этого «изготовителя» ограничения медленных логарифмов. Возможно, тогда этот вопрос лучше всего перенести в stackoverflow, где кто-то, обладающий знаниями в области R, может прокомментировать.
источник
Просто запускаю это с
microbenchmark
; на моей машине родной подход R одинаково быстрее:источник