지난 주에는 Mixture Model, 그 중에서도 Gaussian Mixture Model을 공부했다. 가우시안 혼합모델을 적용해보는 프로그래밍은 간단했지만 생각보다 이해하는데 시간이 조금 걸렸는데, 역시 수학을 좀 훑어볼 필요가 있겠다. 시간을 어디서 내지…

1. Intro

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

alt text

위 그래프1에서 SVM을 통해 형성된 hyperplane인 세 직선이 있는데, 물론 H3가 우리가 찾고자 하는 값일 것이다. 그런데 문제는 저렇게 분류를 할 수 있다는 것과, 값을 ‘generate’할 수 있다는 것은 동치가 아니라는 점. SVM에 대해서 더 궁금하면 여기 참조(업데이트 예정).

요컨대, 가우시안 분포를 형성하는 데이터를 통해 확률 분포 모델을 형성하고 나면 이 모델로 새로운 데이터를 만들 수 있다, 라는 것.

예를 통해 생각해보자. 아래 그래프2는 가상으로 생성한 머신러닝을 배우는 학생들의 키의 분포이다.

alt text

이 데이터를 바탕으로 (일반) 가우시안 분포를 형성하기 위해서는 분포가 어떤 형태를 가지는지 먼저 알아야한다. 이 분포는 아래 식으로 정리되는데, 여기서 $\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느님..) 중학 수학의 자세한 내용은 생략…

\[\mu = \frac{1}{n}\sum^n_{i=1}x_i\] \[\sigma^2 = \frac{1}{n}\sum^n_{i=1}(x_i-\mu)^2\]

구한 분포는 아래 그래프2와 같다.

alt text

이제 우리는 분포를 구했으니, 이 분포에 속하는 새로운 값들을 생성해낼 수 있다.

2. Gaussian Mixture Model

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

ML을 공부하는 학생에 더해 NBA 선수들의 키 분포까지 포함한 새로운 그래프 모양은 아래2와 같다.

alt text

사실 이 정도 눈에 보이는 분포는 그래프를 대략 구해봐도 알 수 있지만, 차원이 더 많아지고, 분포의 개수가 늘어갈수록 불가능에 가까워진다. 인간은 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^*$)를 구해야 한다. 위 식을 대입하여 최적화 식을 도출하면,

\[p(X∣\theta)_{argmax\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을 하는 알고리즘으로 최소한 유사도가 감소하지는 않는다는 것이다 (증명은 생략한다). 알고리즘의 대략의 흐름은 이렇다.

  1. Initialize parameters
  2. Expectation step: 업데이트된 파라미터로 모델의 likelihood값을 계산한다.
  3. Maximization step: 파라미터를 업데이트한다.
  4. 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. 정리하며

생각보다 이해하는데 시간을 쏟아 주어진 데이터를 가지고 시간 내에 모델링을 제대로 할 수 있을까 싶었지만 의외로 잘 돌아갔다.

alt text

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

alt text

히스토그램의 바는 원래의 클래스를 표시한 것이고 아래쪽의 점들은 실제 분류기가 분류한 결과이다. 단순한 모델링을 통해서 단순한 분포를 분류한 것이지만, EM모델이 꽤 잘 돌아간다는 것은 확인할 수 있었다.

GMM을 넘어 하나의 데이터 포인트 X가 스칼라가 아니라 여러 차원을 가지는 경우에는 단순 분산값을 대신하여 covariance matrix를 사용한다고 한다. 기초에서 다룰 레벨은 아니기 때문에, 다음에 벡터값을 대상으로 한 multivariate GMM을 추가적으로 공부할 때 따로 포스팅해야겠다.

I acknowledge that contents of this posting is based on 2017 Fall EECS349 course by Prof. Bryan Pardo at Northwestern Universtiy. I post this for the learning purpose of myself.


  1. Wikipedia(https://en.wikipedia.org/wiki/Support_vector_machine) 

  2. These graphs are taken from the slide in 2017 Fall EECS349 class at NU.  2 3