Summary

MCMC(Markov chain Monte Carlo) 는 샘플링 방법이다. 여기서는 계산가능한 함수 f(x) 를 타겟분포로 주어졌을 때 이 함수로부터 샘플링하는 간단한 예제를 작성해본다. 자세한 내용은 아래 참고 사이트를 참조한다.

참고 사이트:

# 타겟분포 설정
f_x <- function (x) {
  0.3 * exp(-0.2*x^2) + 0.7*exp(-0.2*(x-10)^2) # 타겟 분포
} 

# 타겟 분포를 그려본다. 그래프 이하의 면적은 당연히 1 이 아니기 때문에 PMF 가 아니다.
x <- seq(-10, 20, by=0.01)
plot(x, f_x(x), type='l', col='red')

# 제안분포 설정
g_x <- function (x) {
  # 제안분포로 정규분포를 사용한다. 표준편차는 임의로 설정한다.
  rnorm(1, mean = x, sd = 2)
}

# 반복 횟수 설정
N <- 10000

# x 의 현재 상태를 초기화한다. 랜덤하게 생성해도 좋고, 고정으로 해도 상관없다.
x_current <- 0

result <- c() # 샘플링된 결과 수집

for (i in 1:N) {
  # 0과 1사이의 균등분포 샘플링을 한번 수행해서, 제안된 값을 받아들일지 거부할지 결정한다.
  u <- runif(1) 
  
  # 제안분포에서 샘플링을 한번 수행한다. 제안분포: 정규분포
  x_next <- g_x(x_current)
  
  # 현재 상태와 다음 상태에서의 함수값을 계산하고 그 비율을 계산한다.
  # 그 중 가장 작은 값을 선택한다.
  a_ij <- min(1, f_x(x_next) / f_x(x_current))
  # 제안분포가 대칭이기 때문에 아래에서 dnorm 에 해당하는 부분은 약분되고 결국 위의 식과 동일해진다.
  #a_ij <- min(1, (f_x(x_next) * dnorm(x_current, x_next, sd=2)) / (f_x(x_current) * dnorm(x_next, x_current, sd=2)) )
  
  
  # 제안된 값 x_next 를 accept 할지 reject 할지 결정한다.
  # 위에서 a_ij 는 0보다 크고 1보다 같거나 작은 값을 가진다. 
  # 만약 1 이라면, 무조건 제안된 값을 선택하고
  # 1 이하라면, 선택할지 말지를 확률적으로 결정한다.
  if (u < a_ij) {
    # 만일 a_ij 가 크다면, 다음 상태값이 현재 상태로 변경된다.
    x_current <- x_next
    
  } else {
    # 만일 다음 상태에서의 함수값이 현재 상태보다도 작고, 균등분포로 구한 랜덤값보다도 작으면 
    # 현재 상태를 유지한다.
    
  }
  
  result <- c(result, x_current)
}
hist(result, freq = FALSE, breaks = 100, ylim = c(0, 1))
lines(x, f_x(x), col='red')

# 함수값 기대치 계산
mean(f_x(x))
## [1] 0.1320669
# 위에서 얻은 샘플링 데이터를 이용해서, 테스트로 복원 샘플링을 해본다.
hist(sample(result, 1000, replace = T), breaks = 100)