Pertanyaan saya terinspirasi oleh generator nomor acak eksponensial bawaan R , fungsinya rexp()
. Ketika mencoba untuk menghasilkan angka acak yang didistribusikan secara eksponensial, banyak buku teks merekomendasikan metode transformasi terbalik seperti yang diuraikan dalam halaman Wikipedia ini . Saya sadar bahwa ada metode lain untuk menyelesaikan tugas ini. Secara khusus, kode sumber R menggunakan algoritma yang digariskan dalam sebuah makalah oleh Ahrens & Dieter (1972) .
Saya telah meyakinkan diri saya sendiri bahwa metode Ahrens-Dieter (AD) benar. Namun, saya tidak melihat manfaat dari menggunakan metode mereka dibandingkan dengan metode inverse transform (IT). AD tidak hanya lebih kompleks untuk diterapkan daripada IT. Sepertinya tidak ada manfaat kecepatan juga. Berikut adalah kode R saya untuk membandingkan kedua metode yang diikuti oleh hasilnya.
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)))
Hasil:
[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
Membandingkan kode untuk dua metode, AD menggambar setidaknya dua angka acak seragam (dengan fungsi Cunif_rand()
) untuk mendapatkan satu nomor acak eksponensial. TI hanya membutuhkan satu nomor acak yang seragam. Agaknya tim inti R memutuskan untuk tidak mengimplementasikan TI karena diasumsikan bahwa mengambil logaritma mungkin lebih lambat daripada menghasilkan angka acak yang lebih seragam. Saya mengerti bahwa kecepatan mengambil logaritma dapat bergantung pada mesin, tetapi setidaknya bagi saya yang sebaliknya adalah benar. Mungkin ada masalah di sekitar ketepatan numerik IT yang berkaitan dengan singularitas logaritma pada 0? Tapi kemudian,
kode sumber R sexp.cmengungkapkan bahwa implementasi AD juga kehilangan beberapa ketepatan numerik karena bagian berikut dari kode C menghilangkan bit-bit utama dari nomor acak seragam 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 kemudian didaur ulang sebagai nomor acak seragam dalam sisa sexp.c . Sejauh ini, tampak seolah-olah
- IT lebih mudah untuk dikodekan,
- TI lebih cepat, dan
- IT dan AD mungkin kehilangan akurasi numerik.
Saya akan sangat menghargai jika seseorang dapat menjelaskan mengapa R masih mengimplementasikan AD sebagai satu-satunya pilihan yang tersedia untuk rexp()
.
sumber
rexp(n)
akan menjadi hambatan, perbedaan dalam kecepatan bukanlah argumen yang kuat untuk perubahan (setidaknya bagi saya). Saya mungkin lebih peduli tentang akurasi numerik, meskipun tidak jelas bagi saya yang mana yang lebih dapat diandalkan secara numerik.Jawaban:
Di komputer saya (maafkan bahasa Prancis saya!):
transformasi terbalik tidak lebih buruk. Tetapi Anda harus berhati-hati terhadap variabilitas. Memperkenalkan parameter laju mengarah ke variabilitas yang lebih besar untuk transformasi terbalik:
Berikut perbandingan yang digunakan
rbenchmark
:Jadi jarak tempuh masih bervariasi, tergantung pada skalanya!
sumber
microbenchmark
sebaliknya?rexp
, 3% waktu pengguna lebih pendek untuk-log(runif())
, dan tidak ada variabilitas dengan parameter laju ( total detik). Kita semua secara implisit berasumsi mencapai waktu untuk dan sebanding dengan apa yang akan diperoleh seseorang dengan subrutin Fortran.R
log
runif
Ini hanya mengutip artikel di bawah bagian "Algoritma LG: (Metode logaritma)":
Jadi sepertinya penulis memilih metode lain untuk menghindari pembatasan "pabrikan" logaritma lambat ini. Mungkin pertanyaan ini kemudian lebih baik dipindahkan ke stackoverflow di mana seseorang dengan pengetahuan tentang nyali R dapat berkomentar.
sumber
Hanya menjalankan ini dengan
microbenchmark
; pada mesin saya, pendekatan asli R lebih cepat:Demi kebaruan, inilah yang memastikan itu tidak sepenuhnya karena memiliki :λ=1
sumber