Monte Carlo generation

Pseudo-random number sampling

Monte-Carlo simulations를 하기 위해서는 알려진 확률분포를 따르는 random number를 만들 수 있어야 한다. 그래서 1950년도부터 pseudo-random number sampling algorithm이 개발되었다.

GNU Scientific Library에 다양한 algorithm이 나와있다고 하나, C언어로 작성되어 있기에 확인해 볼 수 없었다. 그래서 비교적 계산속도는 늦어지겠지만, R함수를 이용해 다양한 distribution에서 random number를 만드는 함수를 만들어 보았다. 그리고 만들어 본 것들을 R에 내장된 stats 패키지와 비교해 보았다.

Formula for Monte Carlo generation

먼저 hogg책 4.8장에 나와있는 공식을 정리하였다. discret distribution도 만들고자 수업시간에 넘어간 Accept-Reject Algorithm까지 정리하였다.

In case of continuous distribution

Theorem 4.8.1

U~(0, 1) 이고 F가 continuous distirbution fucntion이라면, random variable X = F − 1(U)F의 distribution function을 가진다.

(F가 strictly monotone아닌 경우에도 성립)

In case of discrete distribution

Accept-Reject Algorithm 4.8.1

먼저 우리는 pdf가 f(x)를 따르는 X를 구하고자 한다.

Y~pdfg(y)이고 U~unif(0, 1)일때, Y와 U가 독립이고 f(x) ≤ M g(x)일 경우 (단 M은 상수)

  1. Y와 U를 만들고

  2. $U \le \frac{f(Y)}{M\ g(Y)}$인경우 X = Y라고 하면

X는 pdf f(x)를 가진다.

(pdf를 normalizing하는 constants를 무시하고 알고리즘 사용 가능)

runif()를 이용하여 다른 분포 만들어 보기

사실 runif()도 만들어 사용하고 싶었다. 사실 이 부분은 통계학이라기 보다는 컴퓨터 과학이나 처음부터 만들려고 찾아봤다. R에서는 “Mersenne-Twister” 방법을 사용한다고 한다. 무려 219937 − 1만큼 반복되어 유의미하나 624만의 반복된 수를 알면 seed수를 알 수 있다고 한다. 그 코드(C)가 영어 위키백과에도 나와있으나, 이를 R로 구현시 크기가 커 문제가 있다고 하고, 이를 다시 unif 분포로 만들기 어려워, 상대적으로 간단한 Linear congruential generator 방식을 이용해 runif()를 만들어 봤다. 이 방식은 초기값에 따라 난수의 질이 달라질 수 있고 마지막 난수만 알면 그 다음의 sequence를 예측 할 수 있기에 암호학 적으로 안전하지 않다고 한다. 먼저 방식은 다음과 같다.

양수 m과 0 < a < m, 0 ≤ c < m, 0 ≤ X0 < m 를 만족하는 a, c, X0에 대해서 난수는 아래와 같다.


Xn + 1 = (aXn + cmod m

코드로 구현하면 다음과 같다.

모수 m, a, c 를 정하는 다양한 방식이 있으나, POSIX [de]rand48에서 사용하는 값을 사용하였다.

하지만 이 방식은 앞서 말한것 처럼 연속된 난수들간에 상관관계가 존재하기에 좋은품질의 유사난수라고 하기는 어렵다. 따라서 우리가 사용하려고 하는 몬테 카를로 시뮬레이션에 적합하지 않다. 따라서 “Mersenne-Twister”기반인 runif(1)함수를 바탕으로 아래의 함수를 만들어 보았다. (물론 Mersenne-Twister도 동일한 문제에서 자유로울 수는 없으나, 상대적인 관점에서 사용하게 되었다.)

다항 분포

n=10인 multinormial(0.1,0.2,0.8)인 분포이다.

##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,]    1    0    0    0    0    1    1    0    2     0
## [2,]    0    1    0    1    1    1    1    1    1     0
## [3,]    4    4    5    4    4    3    3    4    2     5
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,]    2    1    2    1    0    1    0    1    0     1
## [2,]    0    4    0    3    2    4    3    4    4     3
## [3,]    3    0    3    1    3    0    2    0    1     1

정규분포

정규분포의 경우 2개의 모수 μσ2가 필요하므로 2개의 unif가 필요하다. 방법으로는 책에 나와 있는 Box–Muller transform 방법과, 이를 조금 더 심화한 Marsaglia polar method, 그리고 더 심화하여 가장 최신의 방법인 Ziggurat algorithm이 있다.

먼저 책에 나와 있는 Box–Muller방법을 이용해 만들어 보았다.

그리고 Box–Muller transform 방법을 심화시킨 Marsaglia polar method이다. 이는 unif를 따르는 2개의 U를 -1과 1사이의 좌표에 포함되는 x,y로 만들고 이들중 단위원에 포함되는 x,y를 바탕으로 한다. 앞에서 cos(2πU)$x\over {\sqrt s}$형태로 바꾸어 코사인 함수를 간접적으로 사용하게 된 것이다. 코드를 만들어 보면 아래와 같다.

n=10000인 N(1, 0.5)인 분포이다.

위의 두 방법에서 알 수 있는 것과 같이 log와 sqrt 그리고 삼각함수 등이 사용되기에 계산에 시간이 걸린다는 단점이 있다. 이를 보완한 방법이 Ziggurat algorithm이다. 정규분포의 pdf를 같은 면적으로 분할한 후 그 layer 중 하나를 바탕으로 random generating을 한 후 합치는 방식이다. 코드는 생략하였다.

Student’s t 분포

t분포도 정규분포와 카이제곱 분포를 통해 쉽게 만들 수 있다. $Z\over \sqrt {V/\nu}$이므로 lcp_norm2와 lcp_chisq를 사용하여 만들었다.

n=10000인 t(2)인 분포이다.

감마분포

Computer Methods for Sampling from Gamma, Beta, Poisson and Binomial Distributions (1973) J. H. Ahrens, Halifax, and U. Dieter, Graz에서 사용한 방식을 참고한다. 먼저 Gamma(1,1)분포의 pdf는 e − x형태로 간단한 지수함수형태이다. 따라서 iid한 Gamma(1,1)를 alpha개 더하고 beta(rate parameter)를 곱하면 Gamma(alpha,beta)가 될 것이다.

n=10000인 Gamma(4, 2)인 분포이다.

그러나 shape parameter alpha가 정수인 경우에만 가능한 방법이다. 따라서 0 < a ≤ 1인 경우에는 다른 방식이 필요하다.

## [1] 1.512437
## [1] 0.0005884823
## [1] 0.04528588
## [1] 0.6667582

이제 이 둘을 합쳐 모든 shape parameter alpha에 대해 성립하도록 만들어 보면 다음과 같다.

n=10000인 Gamma(3.3, 3.3)인 분포이다.

추가적으로 위의 방식은 rejection이 많아 계산이 오래걸릴 수있다. A Convenient Way of Generating Gamma Random Variables Using Generalized Exponential Distribution (2007) Debasis Kundu & Rameshwar D. Gupta에 따르면나온 동일하게 기본적으로 Accept-Reject Algorithm방식을 활용하지만 rejection을 줄이는, 즉 좀더 빠르게 만들 수 있는 알고리즘을 알 수 있다.

베타분포

베타분포는 2개의 감마분포를 통해 계산할 수 있다. 즉 각각의 shape parameter가 α β인 두 표준감마분포 Xα Xβ에 대해 $X_\alpha\over X_\alpha +X_\beta$는 Beta(α, β)를 따르게 된다. 따라서 lcp_gamma2를 사용하여 코드는 다음과 같다.

n=10000인 Beta(0.5, 0.5)인 분포이다.

n=10000인 Beta(2, 4)인 분포이다.

updatedupdated2020-08-202020-08-20