Moje pytanie jest inspirowane wbudowanym generatorem wykładniczej liczby losowej R. , funkcją rexp()
. Podczas próby generowania wykładniczych liczb losowych rozkładanych wykładniczo wiele podręczników zaleca metodę transformacji odwrotnej opisaną na tej stronie Wikipedii . Wiem, że istnieją inne metody realizacji tego zadania. W szczególności kod źródłowy R korzysta z algorytmu przedstawionego w artykule Ahrensa i Dietera (1972) .
Przekonałem się, że metoda Ahrensa-Dietera (AD) jest poprawna. Mimo to nie widzę korzyści z zastosowania ich metody w porównaniu z metodą transformacji odwrotnej (IT). AD jest nie tylko bardziej skomplikowany do wdrożenia niż IT. Wydaje się, że nie ma również korzyści z prędkości. Oto mój kod R do porównania obu metod, a następnie wyników.
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)))
Wyniki:
[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
Porównując kod dla dwóch metod, AD rysuje co najmniej dwie jednolite liczby losowe (z funkcją Cunif_rand()
), aby uzyskać jedną wykładniczą liczbę losową. IT potrzebuje tylko jednej jednolitej liczby losowej. Prawdopodobnie główny zespół R zdecydował się nie wdrażać technologii informatycznych, ponieważ zakładał, że przyjęcie logarytmu może być wolniejsze niż generowanie bardziej jednolitych liczb losowych. Rozumiem, że szybkość przyjmowania logarytmów może zależeć od maszyny, ale przynajmniej dla mnie jest odwrotnie. Być może istnieją problemy związane z dokładnością liczbową IT związaną z osobliwością logarytmu przy 0? Ale potem
kod źródłowy R sexp.cujawnia, że implementacja AD również traci pewną dokładność liczbową, ponieważ następna część kodu C usuwa wiodące bity z jednolitej liczby losowej 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 jest następnie zawracana jako jednolity losowej liczby w pozostałej sexp.c . Jak dotąd wydaje się, jakby
- Łatwiej jest kodować,
- IT jest szybsze i
- zarówno IT, jak i AD prawdopodobnie tracą dokładność liczbową.
Byłbym naprawdę wdzięczny, gdyby ktoś mógł wyjaśnić, dlaczego R nadal implementuje AD jako jedyną dostępną opcję dla rexp()
.
źródło
rexp(n)
byłoby wąskie gardło, różnica prędkości nie jest silnym argumentem za zmianą (przynajmniej dla mnie). Być może bardziej martwię się o dokładność numeryczną, chociaż nie jest dla mnie jasne, który z nich byłby bardziej wiarygodny numerycznie.Odpowiedzi:
Na moim komputerze (wybacz mój francuski!):
odwrotna transformacja gorzej. Ale powinieneś uważać na zmienność. Wprowadzenie parametru szybkości prowadzi do jeszcze większej zmienności transformacji odwrotnej:
Oto porównania przy użyciu
rbenchmark
:Tak więc przebieg nadal jest różny, w zależności od skali!
źródło
microbenchmark
zamiast tego wykonać ?rexp
, 3% krótszy czas użytkownika-log(runif())
i brak zmienności z parametrem szybkości ( sekund). Wszyscy niejawnie zakładając osiąga czasy dla i porównywalne do tego, co można by uzyskać z Fortran podprogram.R
log
runif
Cytuję tylko ten artykuł w sekcji „Algorytm LG: (metoda logarytmiczna)”:
Wygląda więc na to, że autorzy wybrali inne metody, aby uniknąć ograniczenia „wolnych producentów” w logarytmach. Być może to pytanie najlepiej przenieść na stackoverflow, w którym ktoś z wiedzą na temat odwagi R może komentować.
źródło
Po prostu uruchamiam to z
microbenchmark
; na moim komputerze natywne podejście R jest jednolicie szybsze:Na wszelki wypadek, upewnijmy się, że nie jest to całkowicie spowodowane tym, że :λ=1
źródło