1 Inverse Transformation Method

역변환방법(Inverse Transformation Method)을 통한 표본 추출은 다음 3단계 방법을 거치게 된다.

  1. 누적밀도함수(CDF)를 구한다.
  2. 역변환을 취한다.
  3. \(U \sim \text{Unif} [0,1]\) 값을 역변환 인수로 넣는다.

상기 1, 2, 3 단계를 통해 해당 확률밀도함수(PDF)를 따르는 확률표본을 추출할 수 있다.

2 역변환 방법 일반화

직관적으로 \(U \sim \mathrm{Unif}[0,1]\) 균등분포에서 난수를 발생시켜 이를 누적밀도함수 \(Y=F_X(X)\) 를 활용하여 \(X\) 표본을 추출하는 것이다. 이를 일반화하여 역변환 방법을 설명하면 다음과 같다.

  1. 누적밀도함수 \(Y=F_X(X)\)\(\mathrm{Unif}[0,1]\)$ 균등분포를 따르게 된다.
  2. 이런 성질을 이용하여 역함수 \(F_X^{-1}(Y) = X\)가 되고
  3. \(U \sim \mathrm{Unif}[0,1]\)을 대입시키게 되면 \(F_X^{-1}(U)\)로부터 \(X\) 표본을 추출할 수 있다.

3 사례: 지수분포

지수분포(Exponential Distribution)를 따르는 난수를 추출해보자. 먼저, \(\lambda\)를 모수로 갖는 지수분포 확률밀도함수(Probability density function)를 다음과 같이 표현할 수 있다.

\[f(x;\lambda) = \begin{cases} \lambda e^{-\lambda x} & x \ge 0, \\ 0 & x < 0. \end{cases}\]

지수분포에서 난수를 추출하는데 역변환방법을 사용해보자.

  1. 누적밀도함수를 구한다. u-치환 방법을 사용하면 다음과 같이 누적밀도함수를 구할 수 있다.

\[F(x;\lambda) = \begin{cases} 1-e^{-(\lambda x)} & x \ge 0, \\ 0 & x < 0. \end{cases}\]

  1. 누적밀도함수의 역함수를 계산한다.

\[x = F^{-1}(y) = -\frac{1}{\lambda}\ln(1-y)\]

  1. \(U \sim \mathrm{Unif}(0,1)\) 균등분포에서 난수를 하나 잡아 \(x_0 = F_X^{-1}(y_0) = -\frac{1}{\lambda}\ln(1-y_0)\) 에서 나온 \(x_0\)는 지수분포에서 나온 표본이 된다.

직관적인 그림을 통한 설명은 Inverse transform sampling을 참고한다.

4 R 코드

\(\lambda = 3\) 을 모수로 갖는 지수분포에서 표본을 추출해보자. 먼저 균등분포에서 \([0, 1]\)에서 표본을 추출하고 이를 앞서 수학적으로 찾은 \(-\frac{1}{\lambda}\ln(1-y) = -\frac{1}{3}\ln(1-y)\) 함수에 넣는다.

library(tidyverse)

set.seed(1337)

unif_smpl <- runif(1000)
exp_smpl  <- -log(1-unif_smpl) / 3

inv_trans_tbl <- tibble(`균등분포표본` = unif_smpl,
                        `지수분포표본` = exp_smpl,
                        `내장함수표본` = rexp(1000, rate = 3))

inv_trans_tbl %>% 
  pivot_longer(cols = everything(),
               names_to = "분포", 
               values_to = "표본") %>% 
  ggplot(aes(x = 표본, fill = 분포, color = 분포)) +
    geom_density(alpha = 0.3) +
    labs(x="", y="밀도") +
    theme_minimal() +
    theme(legend.position = "top")

함수로 만들어 표본수를 늘려 이론적인 지수분포에서 나온 표본값과 비교해보자.

library(patchwork)

draw_exp_smpl <- function(num_samples) {
  
  unif_smpl <- runif(num_samples)
  exp_smpl  <- -log(1-unif_smpl) / 3
  
  inv_trans_tbl <- tibble(`균등분포표본` = unif_smpl,
                          `지수분포표본` = exp_smpl,
                          `내장함수표본` = rexp(num_samples, rate = 3))
  
  inv_trans_tbl %>% 
    pivot_longer(cols = everything(),
                 names_to = "분포", 
                 values_to = "표본") %>% 
    ggplot(aes(x = 표본, fill = 분포, color = 분포)) +
      geom_density(alpha = 0.3) +
      labs(x="", y="밀도", title = glue::glue("지수분포 표본수: {num_samples}")) +
      theme_minimal() +
      theme(legend.position = "top")
}

( draw_exp_smpl(100)   + draw_exp_smpl(1000) ) /
( draw_exp_smpl(5000)  + draw_exp_smpl(10000) )  

 

데이터 과학자 이광춘 저작

kwangchun.lee.7@gmail.com