Генерация случайных выборок из собственного дистрибутива

16

Я пытаюсь сгенерировать случайные выборки из пользовательского PDF-файла, используя R. Мой PDF-файл:

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

Я сгенерировал единообразные образцы, а затем попытался преобразовать их в свой собственный дистрибутив. Я сделал это, найдя cdf моего дистрибутива ( FX(x) ) и установив его в единую выборку ( u ) и решив для x .

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

Чтобы сгенерировать случайную выборку с указанным выше распределением, получите равномерную выборку и решите для inu[0,1]x

32(xx33)=u

Я реализовал это, Rи я не получаю ожидаемое распределение. Кто-нибудь может указать на недостаток в моем понимании?

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);
}
Ананд
источник
1
Должно быть ошибка кодирования. Я не использую R, поэтому я не могу точно сказать, в чем именно ошибка - но я просто закодировал ваше решение (стараясь взять средний корень кубического полинома, который всегда лежит между 0 и 1), и Я получаю хорошее согласие между образцами и ожидаемым распределением. Может ли это быть проблема с вашим корневым поиском? Что не так с образцами, которые вы получаете?
jpillow
Я попробовал ваш код (который, кстати, не очень эффективен) и получил ожидаемое распространение.
Анико
@jpillow и @Aniko Моя ошибка. Когда я использовал nsamples <- 1e6это был хороший матч.
Ананд
2
@Anand Одним из способов является наблюдение, что , что позволяет напрямую вычислять x в терминах u . x=2sin(arcsin(u)/3)xu
whuber
1
@Anand en.wikipedia.org/wiki/...
whuber

Ответы:

11

Похоже, вы поняли, что ваш код работает, но @Aniko указал, что вы можете повысить его эффективность. Ваше наибольшее увеличение скорости, вероятно, будет связано с предварительным выделением памяти, zчтобы вы не увеличивали ее в цикле. Что-то вроде z <- rep(NA, nsamples)должно сделать свое дело. Вы можете получить небольшое увеличение скорости от использования vapply()(которое указывает возвращаемый тип переменной) вместо явного цикла (есть большой вопрос SO по семейству apply).

> 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

И вам не нужно ;в конце каждой строки (вы конвертируете в MATLAB?).

Ричард Херрон
источник
Спасибо за ваш подробный ответ и за указание vapply. Я кодировал в C/C++течение очень долгого времени, и это причина ;несчастья!
Ананд
1
uniroot107