사용자 정의 분포에서 무작위 샘플 생성


16

R을 사용하여 사용자 정의 PDF에서 임의의 샘플을 생성하려고합니다. 내 PDF는 다음과 같습니다.

에프엑스(엑스)=2(1엑스2),0엑스1

균일 한 샘플을 생성 한 다음이를 사용자 지정 배포로 변환하려고했습니다. 내 분포의 cdf ( )를 찾아 균일 표본 ( )으로 설정하고 해결하여이를 수행했습니다 .에프엑스(엑스)엑스

에프엑스(엑스)=홍보[엑스엑스]=0엑스2(1와이2)와이=2(엑스엑스)

상기 분포가 임의의 샘플을 생성하기 위해 균일 한 시료 얻을 [0,1] 및 풀기 엑스

2(엑스엑스)=

나는 그것을 구현했지만 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

나는 당신의 코드를 시도했지만 (매우 효율적이지 않습니다) 예상되는 분포를 얻었습니다.
Aniko

@jpillow와 @Aniko 내 실수. 내가 사용했을 때 nsamples <- 1e6그것은 잘 어울렸다.
Anand

2
@Anand 하나의 방법은 관찰하는 의 직접 계산 가능 측면에서 . 엑스=2(아크 신()/)엑스
whuber

답변:


11

코드가 작동한다는 것을 알았지 만 @Aniko는 효율을 향상시킬 수 있다고 지적했습니다. 가장 큰 속도 향상은 아마도 사전 할당 메모리에서 비롯된 z것이므로 루프 내에서 메모리를 늘리지 않을 것입니다. z <- rep(NA, nsamples)트릭을 수행하는 것과 같은 것이 있습니다. vapply()명시 적 루프 대신 (반환 변수 유형을 지정) 을 사용하면 약간의 속도 향상을 얻을 수 있습니다 ( 적용 패밀리에 대한 SO 질문 이 있습니다).

> 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++이것이 ;고통 의 이유입니다 !
Anand

1
+1 uniroot직접 솔루션으로 교체 하면 속도가 3 배 더 빨라집니다. 초당 약 변형을 얻는 데 어려움이 없어야 합니다. 107
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.