Tôi muốn thực hiện thuật toán EM bằng tay và sau đó so sánh nó với kết quả normalmixEM
của mixtools
gói. Tất nhiên, tôi sẽ rất vui nếu cả hai đều dẫn đến cùng một kết quả. Tài liệu tham khảo chính là Geoffrey McLachlan (2000), Mô hình hỗn hợp hữu hạn .
Tôi có mật độ hỗn hợp của hai Gaussian, ở dạng tổng quát, khả năng đăng nhập được đưa ra bởi (McLachlan trang 48):
Bước E bây giờ, tính toán kỳ vọng có điều kiện:
Tôi đã cố gắng viết một mã R (dữ liệu có thể được tìm thấy ở đây ).
# EM algorithm manually
# dat is the data
# initial values
pi1 <- 0.5
pi2 <- 0.5
mu1 <- -0.01
mu2 <- 0.01
sigma1 <- 0.01
sigma2 <- 0.02
loglik[1] <- 0
loglik[2] <- sum(pi1*(log(pi1) + log(dnorm(dat,mu1,sigma1)))) +
sum(pi2*(log(pi2) + log(dnorm(dat,mu2,sigma2))))
tau1 <- 0
tau2 <- 0
k <- 1
# loop
while(abs(loglik[k+1]-loglik[k]) >= 0.00001) {
# E step
tau1 <- pi1*dnorm(dat,mean=mu1,sd=sigma1)/(pi1*dnorm(x,mean=mu1,sd=sigma1) +
pi2*dnorm(dat,mean=mu2,sd=sigma2))
tau2 <- pi2*dnorm(dat,mean=mu2,sd=sigma2)/(pi1*dnorm(x,mean=mu1,sd=sigma1) +
pi2*dnorm(dat,mean=mu2,sd=sigma2))
# M step
pi1 <- sum(tau1)/length(dat)
pi2 <- sum(tau2)/length(dat)
mu1 <- sum(tau1*x)/sum(tau1)
mu2 <- sum(tau2*x)/sum(tau2)
sigma1 <- sum(tau1*(x-mu1)^2)/sum(tau1)
sigma2 <- sum(tau2*(x-mu2)^2)/sum(tau2)
loglik[k] <- sum(tau1*(log(pi1) + log(dnorm(x,mu1,sigma1)))) +
sum(tau2*(log(pi2) + log(dnorm(x,mu2,sigma2))))
k <- k+1
}
# compare
library(mixtools)
gm <- normalmixEM(x, k=2, lambda=c(0.5,0.5), mu=c(-0.01,0.01), sigma=c(0.01,0.02))
gm$lambda
gm$mu
gm$sigma
gm$loglik
Thuật toán không hoạt động, vì một số quan sát có khả năng bằng 0 và nhật ký của điều này là -Inf
. Lỗi của tôi ở đâu?