1차원 가우시안 혼합 p(x)=∑k=1KπkN(x∣μk,σk2)를 EM으로 학습하는 두 단계를 구현한다.
-
e_step(x, pi, mu, sd): 책임도 resp (N,K)와 현재 파라미터의 주변 로그우도 loglik(스칼라)를 반환한다.
rnk=∑jπjN(xn∣μj,σj2)πkN(xn∣μk,σk2),loglik=n∑logk∑πkN(xn∣μk,σk2)
-
m_step(x, resp): 책임도로 가중한 MLE (pi, mu, sd)를 반환한다. 각각 shape (K,).
Nk=n∑rnk,πk=NNk,μk=Nk1n∑rnkxn,σk=Nk1n∑rnk(xn−μk)2
테스트는 다음을 확인한다.
- 책임도의 각 행의 합이 1이고, 로그우도가 직접 계산한 값과 같다.
- 데이터에서 아주 먼 점(x=1000)이 있어도 NaN이나 무한대가 나오지 않는다.
- 책임도가 0과 1뿐이면 M-step이 집단별 표본 비율·평균·표준편차(N으로 나눈 MLE)와 같다.
- 두 단계를 번갈아 반복하면 로그우도가 감소하지 않고, 잘 떨어진 두 집단의 파라미터를 찾는다.
힌트: 확률을 그대로 계산하면 먼 점에서 모든 성분의 밀도가 0으로 underflow되어 0/0이 된다. 로그 밀도 logπk+logN(xn∣μk,σk2)를 (N,K) 배열로 만들고 scipy.special.logsumexp로 정규화한다.