Box-Muller transformation
예제 · 케이플러스 한성탁 ·Box-Muller transformation으로 정규 난수 생성하기
박스-뮬러 변환은 가장 간단한 정규 난수 발생법 중 하나입니다. Box와 Muller에 의해 1958년 발표되었습니다.
U1,U2∼U(0,1) 일 때,
X1=√−2logU1cos(2πU2)∼N(0,1)
X2=√−2logU1sin(2πU2)∼N(0,1)
이 되어 서로 독립이고 같은 분포를 가지는(iid) 2개의 표준 정규 난수를 발생시키게 됩니다.
먼저 X1,X2∼N(0,1) 이라고 가정합니다. X1,X2 를 좌표에 놓고 극좌표법으로 좌표를 구하면 (X1,X2)=(R,θ) 이고
R2=X21+X22 θ=arctanX2X1이 됩니다.
R2을 보면 X21과 X22의 합으로 이루어져 있고, 표준 정규 난수의 제곱은 카이제곱 분포 χ2(1)를 따르고, 카이제곱 분포는 지수 분포로 표현할 수 있으며, 지수분포는 역변환법(Inverse transformation)에 의해 U(0,1)의 꼴로 표현할 수 있습니다. 이를 식으로 표현하면 다음과 같습니다.
R2=X21+X22∼χ2(2)∼Exp(12)∼−2logU다른 방법으로 R의 누적분포함수를 직접 구하면 다음과 같습니다.
f(X1,X2)=12πexp(−(X21+X22)2)=1√2πexp(−X212)1√2πexp(−X222)=f(X1)f(X2) P(R≤r0)=∫x21+x22≤r2012πexp(−(x21+x22)2)dx1dx2=12π∫2π0∫r00exp(−r22)rdθdr=∫r00exp(−r22)rdr=∫r2020exp(−z)dz=1−exp(−r202)=F(r20|λ=12)위의 식을 통해 X1,X2는 서로 독립이라는 것과 P(R≤r0) 은 지수분포의 누적분포함수라는 것을 확인 할 수 있습니다(r20>=0 이므로). 이때 λ=12 입니다.
이제 위 식을 아래에서 위로 반대로 거슬러보면, −2logU를 구하여서 이 값을 통해 두 표준 정규 난수의 제곱의 합을 알 수 있습니다. 그런데 x1,x2의 제곱의 합이 같은 경우는 무수히 많고(원에 대한 방정식 x21+x22=r2 와 같습니다) 모두 정규분포를 따릅니다.
그러므로 이때 반지름이 정해진 경우 θ는 0≤θ<2π 범위에서 아무거나 공평하게 고르면 됩니다. 따라서 θ=2πU2, U2∼U(0,1) 로 정합니다.
따라서
X1=Rcos(θ)=√−2logU1cos(2πU2)∼N(0,1)X2=Rsin(θ)=√−2logU1sin(2πU2)∼N(0,1)가 성립합니다.
아래는 박스-뮬러 변환법을 R 코드로 구현한 것입니다.
rnorm.boxmuller = function(n, mean=0, sd=1){
U1 = runif(ceiling(n/2))
U2 = runif(ceiling(n/2))
Z1 = sqrt(-2*log(U1))*cos(2*pi*U2)
Z2 = sqrt(-2*log(U1))*sin(2*pi*U2)
c(Z1, Z2)[1:n] * sd + mean
}
rnorm.boxmuller(100)
꽤 간단하게 작성 가능합니다.