9.Gaussian Mixture Model
지난 주에는 Mixture Model, 그 중에서도 Gaussian Mixture Model을 공부했다. 가우시안 혼합모델을 적용해보는 프로그래밍은 간단했지만 생각보다 이해하는데 시간이 조금 걸렸는데, 역시 수학을 좀 훑어볼 필요가 있겠다. 시간을 어디서 내지…
1. Intro
머신러닝의 많은 모델들은 각자 쓰이는 곳이 다르다. 사실 다 다른 모델링 방법들인데 머신러닝이라는 이름으로 묶여있다고 해야할지도.. 그 중에서도 Gaussian Mixture Model은 generative model이다. 뭔 말인고 하니, (가우시안) 확률 모델을 한 번 생성하고 나면 이 모델을 기반으로 모델에 포함되는 새로운 데이터를 생성해낼 수 있다는 것이다. 다른 모델은 안 그런가? SVM을 보자. SVM은 hyperplane을 만들어서 두 (개 혹은 그 이상의) 데이터군을 분류하는 모델이다. 이 모델은 주어진 상태를 바탕으로 A와 B를 분류할 수는 있겠지만, A와 B가 어떤 규칙을 갖고 생성되는지 정하기는 어려울 것이다. 아래 그래프를 보면 직관적으로 이해가 될 듯 하다.

위 그래프1에서 SVM을 통해 형성된 hyperplane인 세 직선이 있는데, 물론 H3가 우리가 찾고자 하는 값일 것이다. 그런데 문제는 저렇게 분류를 할 수 있다는 것과, 값을 ‘generate’할 수 있다는 것은 동치가 아니라는 점. SVM에 대해서 더 궁금하면 여기 참조(업데이트 예정).
요컨대, 가우시안 분포를 형성하는 데이터를 통해 확률 분포 모델을 형성하고 나면 이 모델로 새로운 데이터를 만들 수 있다, 라는 것.
예를 통해 생각해보자. 아래 그래프2는 가상으로 생성한 머신러닝을 배우는 학생들의 키의 분포이다.

이 데이터를 바탕으로 (일반) 가우시안 분포를 형성하기 위해서는 분포가 어떤 형태를 가지는지 먼저 알아야한다. 이 분포는 아래 식으로 정리되는데, 여기서 $\mu$는 평균, $\sigma$는 표준편차이며, x는 데이터 포인트 하나의 값이다.
\[\frac{1}{(2\pi)^{1/2}\sigma}e^\frac{-(x-\mu)^2}{2\sigma^2}\]위의 식에서 볼 때, 알아야하는 parameter($\theta$)들은 평균과 분산($표준편차^2$)이다. 즉, 주어진 각 데이터들이 특정 평균과 분산을 따르는 분포에 속할 확률을 계산하고, 평균과 분산을 수정해가면서 이 확률을 최대로 하는 parameter($\theta^*$)들을 구하면 주어진 점들에서 가우시안 분포를 도출해낼 수 있다는 것이다.
어렵게 설명했지만 사실, 중학교 때 다들 배웠듯, 이 두 값은 아래 식으로 간단하게 구할 수 있다. 파이썬으로도 (1차원의 경우) 달랑 두 줄의 코드면 된다.(numpy느님..) 중학 수학의 자세한 내용은 생략…
구한 분포는 아래 그래프2와 같다.

이제 우리는 분포를 구했으니, 이 분포에 속하는 새로운 값들을 생성해낼 수 있다.
2. Gaussian Mixture Model
이걸로 끝나면 얼마나 좋을까. 하지만 실생활에서 하나의 분포만 구할 일은 별로 없다. 여러 분포에 속하는 데이터들이 뒤섞여 있을 때, 각 분포를 찾아내고, 새로운 데이터가 들어왔을 때 어떤 분포에 속할 확률이 높은지 찾아내고 싶은 것이 우리 마음이다 (!?). 여러 분포를 따로따로 알 수 있다면 각 분포의 파라미터들을 이용해서 해당 분포에 속할 확률을 구하기만 하면 그만이지만, 분포를 따로 알고 있지 않다면 분포를 구해내야 한다. 아마 일반적인 상황이라면 분포가 몇 개인지도 모를 것이기 때문이다. 이렇게 각기 다른 분포를 따르는 데이터들에서 각각의 분포를 구해낼 때 사용하는 것이 바로 Gaussian Mixture Model (GMM)이다.
ML을 공부하는 학생에 더해 NBA 선수들의 키 분포까지 포함한 새로운 그래프 모양은 아래2와 같다.

사실 이 정도 눈에 보이는 분포는 그래프를 대략 구해봐도 알 수 있지만, 차원이 더 많아지고, 분포의 개수가 늘어갈수록 불가능에 가까워진다. 인간은 3차원, 기껏해야 4차원까지가 상상할 수 있는 최대한이기 때문에, 수백개의 차원은 low dimension이라고 치는 머신러닝에서는 저차원에서 모델의 개념을 확립하고 고차원에서 그 모델을 활용 및 수정하는 것이 중요하다.
다시 GMM으로 돌아와서, 우리의 목표는 이 두 분포의 $\theta$들을 구하고, 새로 관측된 데이터가 속할 분포를 판단하는 것이다. 식으로 표현해보자.
\[P(x) = \sum^K_{j=1}P(z_j)P(x∣z_j)\]여기서 $z_j$는 가우시안 분포 j가 데이터 포인트 x를 생성했는지 여부를 드러내는 boolean값이고 K는 총 가우시안 분포의 수이다. 즉 어떤 가우시안 분포가 그 값을 생성했는지를 판단하기 위한 식인데, 분포들이 겹쳐있는 경우에 단순히 결정한다 하지 않는다라고 하기는 어려우니 boolean값 $z_j$를 가중치 $w_j$로 변경하고, 가우시안 분포를 식에 대입하면, 식 (4)는
\[\sum^K_{j=1}w_jN(x∣\mu_j, \sigma_j^2)\]이렇게 만들 수 있다. 이 때 모든 가우스 분포의 (이제서야 한글로는 ‘가우스’도 자연스럽다는 것을 깨달았다) 가중치의 합은 1이다. 이에 따라 우리가 optimize해야 할 값으로 가중치 하나가 추가되어, 하나의 가우스 분포 당 총 3개의 최적 parameter($\theta^*$)를 구해야 한다. 위 식을 대입하여 최적화 식을 도출하면,
식을 전개하면서 underflow를 방지하기위한 log-likelihood 사용하면,
\[= \sum^n_{i=1}log(p(x_i∣\theta))\] \[=\sum^n_{i=1}log\Bigl(\sum^K_{j=1}w_jN(x_i∣\mu_j, \sigma_j^2)\Bigl)\]최종적으로 식 (8)이 도출되는데, 이 값들이 바로 log-likelihood가 된다. 즉, 더 좋은 $\theta$를 판단할 때, 이 값들을 비교하면 된다.
그런데 이 값들을 한번에 구할 수 있는 closed-form solution (단일 가우스 분포의 평균, 분산을 구하는 식과 같은)은 없다. 이 문제를 풀기 위한 가장 많이 사용되는 방법은 Expectation Maximization (EM)이다.
Expectation Maximization
EM은 Expectation 단계와 Maximization 단계의 2단계를 반복적을 밟아가면서 파라미터를 업데이트해가는 문제 해결 방법이다. 매 파라미터 업데이트 후에 log-likelihood를 구하게 되는데, 이 알고리즘은 local optimum으로 converge된다. 다시 말해, 최적해에 확실히 도달했는지 판단하기는 어렵지만 hill climbing을 하는 알고리즘으로 최소한 유사도가 감소하지는 않는다는 것이다 (증명은 생략한다). 알고리즘의 대략의 흐름은 이렇다.
- Initialize parameters
- Expectation step: 업데이트된 파라미터로 모델의 likelihood값을 계산한다.
- Maximization step: 파라미터를 업데이트한다.
- converge될 때까지 (local minimum에 수렴하여 값이 계속 증가하지 않을때까지) 2,3을 반복한다,
Expecatation step
likelihood는 위에서 계산했다. 이 스텝에서는 추가로 likelihood를 기반으로 각 파라미터를 업데이트하기 위한 값, responsibility를 구한다. 우선 가우스 분포 j의 데이터 x에 대한 responsibility인 $\gamma_{j,n}$를 구해 보면,
\[\gamma_{j,n}\equiv p(z_j∣x_n)=\frac{p(x_n∣z_j)p(z_j)}{p(x_n)}\] \[=\frac{p(x_n∣z_j)p(z_j)}{\sum^K_{k=1}p(z_k)p(x_n∣z_k)}= \frac{w_jN(x_n∣\mu_j, \sigma_j^2)}{\sum^K_{j=1}w_jN(x_n∣\mu_j, \sigma_j^2)}\]그리고 j의 모든 데이터들에 대한 responsibility를 구해서 더한다.
\(\Gamma_j\equiv \sum^N_{n=1}\gamma_{j,n}\)
Maximization step
responsibility를 기반으로 값을 다음과 같이 업데이트한다.
\[*new* w_j = \frac{\Gamma_j}{num(x)}\] \[*new* \mu_j = \frac{\sum^N_{i=1}\gamma_{j,i}x_i}{\Gamma_j}\] \[*new* \sigma_j^2 = \frac{\sum^N_{i=1}\gamma_{j,i}(x_i-\mu_i)^2}{\Gamma_j}\]증명은.. 해보고는 싶었으나 시간부족으로 생략한다 (심지어 수업시간에도 생략되었다). 다시 이 모델을 접하는 그날에 증명을 공부하고 이 포스팅을 업데이트해야겠다 (그날이 올까..).
3. 정리하며
생각보다 이해하는데 시간을 쏟아 주어진 데이터를 가지고 시간 내에 모델링을 제대로 할 수 있을까 싶었지만 의외로 잘 돌아갔다.

위의 두 GMM 분포를 따르는 트레이닝 데이터를 가지고 각각 러닝을 하여 classifier를 만든 후, 각각의 분포에 속하는 데이터를 섞어놓은 다른 테스트 데이터를 분류해보니 약 94%의 성공률이 나왔다. 아래는 그 결과.

히스토그램의 바는 원래의 클래스를 표시한 것이고 아래쪽의 점들은 실제 분류기가 분류한 결과이다. 단순한 모델링을 통해서 단순한 분포를 분류한 것이지만, EM모델이 꽤 잘 돌아간다는 것은 확인할 수 있었다.
GMM을 넘어 하나의 데이터 포인트 X가 스칼라가 아니라 여러 차원을 가지는 경우에는 단순 분산값을 대신하여 covariance matrix를 사용한다고 한다. 기초에서 다룰 레벨은 아니기 때문에, 다음에 벡터값을 대상으로 한 multivariate GMM을 추가적으로 공부할 때 따로 포스팅해야겠다.