Menghasilkan sampel acak dari distribusi khusus

16

Saya mencoba untuk menghasilkan sampel acak dari pdf kustom menggunakan R. Pdf saya adalah:

fX(x)=32(1x2),0x1

Saya menghasilkan sampel yang seragam dan kemudian mencoba mengubahnya menjadi distribusi khusus saya. Saya melakukan ini dengan menemukan cdf dari distribusi saya ( FX(x) ) dan mengaturnya ke sampel seragam ( ) dan menyelesaikannya untuk .ux

FX(x)=Pr[Xx]=0x32(1y2)dy=32(xx33)

Untuk menghasilkan sampel acak dengan distribusi di atas, dapatkan sampel seragam dan selesaikan untuk inu[0,1]x

32(xx33)=u

Saya menerapkannya Rdan saya tidak mendapatkan distribusi yang diharapkan. Adakah yang bisa menunjukkan kekurangan dalam pemahaman saya?

nsamples <- 1000;
x <- runif(nsamples);

f <- function(x, u) { 
  return(3/2*(x-x^3/3) - u);
}

z <- c();
for (i in 1:nsamples) {
  # find the root within (0,1) 
  r <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root;
  z <- c(z, r);
}
Anand
sumber
1
Pasti ada kesalahan pengkodean. Saya tidak menggunakan R, jadi saya tidak bisa mengatakan apa kesalahan sebenarnya - tapi saya baru saja membuat kode solusi Anda (berhati-hati untuk mengambil akar tengah dari polinomial kubik, yang selalu terletak antara 0 dan 1), dan Saya mendapatkan persetujuan yang baik antara sampel dan distribusi yang diharapkan. Mungkinkah ada masalah dengan pencari root Anda? Apa yang salah dengan sampel yang Anda dapatkan?
jpillow
Saya mencoba kode Anda (yang tidak sangat efisien, omong-omong) dan mendapatkan distribusi yang diharapkan.
Aniko
@jpillow dan @Aniko Kesalahan saya. Ketika saya menggunakan nsamples <- 1e6itu cocok.
Anand
2
@ Anand Salah satu cara adalah dengan mengamati bahwa , memungkinkan perhitungan langsung dalam hal . x=2sin(arcsin(u)/3)xu
whuber
1
@Anand en.wikipedia.org/wiki/…
whuber

Jawaban:

11

Sepertinya Anda tahu bahwa kode Anda berfungsi, tetapi @Aniko menunjukkan bahwa Anda dapat meningkatkan efisiensinya. Kenaikan kecepatan terbesar Anda mungkin berasal dari pra-alokasi memori zagar Anda tidak menanamnya di dalam satu lingkaran. Sesuatu seperti z <- rep(NA, nsamples)harus melakukan triknya. Anda dapat memperoleh kecepatan kecil dengan menggunakan vapply()(yang menentukan tipe variabel yang dikembalikan) alih-alih loop eksplisit (ada pertanyaan SO yang bagus tentang keluarga yang berlaku).

> nsamples <- 1E5
> x <- runif(nsamples)
> f <- function(x, u) 1.5 * (x - (x^3) / 3) - u
> z <- c()
> 
> # original version
> system.time({
+ for (i in 1:nsamples) {
+   # find the root within (0,1) 
+   r <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root
+   z <- c(z, r)
+ }
+ })
   user  system elapsed 
  49.88    0.00   50.54 
> 
> # original version with pre-allocation
> z.pre <- rep(NA, nsamples)
> system.time({
+ for (i in 1:nsamples) {
+   # find the root within (0,1) 
+   z.pre[i] <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root
+   }
+ })
   user  system elapsed 
   7.55    0.01    7.78 
> 
> 
> 
> # my version with sapply
> my.uniroot <- function(x) uniroot(f, c(0, 1), tol = 0.0001, u = x)$root
> system.time({
+   r <- vapply(x, my.uniroot, numeric(1))
+ })
   user  system elapsed 
   6.61    0.02    6.74 
> 
> # same results
> head(z)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738
> head(z.pre)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738
> head(r)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738

Dan Anda tidak perlu ;di akhir setiap baris (apakah Anda seorang konversi MATLAB?).

Richard Herron
sumber
Terima kasih atas jawaban terperinci Anda dan untuk menunjukkannya vapply. Saya telah mengkode dalam C/C++waktu yang sangat lama dan itulah alasan ;kesengsaraan!
Anand
1
uniroot107