Я хочу реализовать алгоритм EM вручную , а затем сравнить его с результатами normalmixEM
из mixtools
пакета. Конечно, я был бы счастлив, если бы они оба привели к одинаковым результатам. Основное упоминание - Джеффри МакЛахлан (2000), Модели конечных смесей .
У меня плотность смеси двух гауссианов, в общем виде, логарифмическая вероятность определяется (McLachlan стр. 48):
Е шаг теперь, вычисление условного ожидания:
Я пытался написать код R (данные можно найти здесь ).
# 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
Алгоритм не работает, так как некоторые наблюдения имеют вероятность нуля, и лог этого -Inf
. Где моя ошибка?
источник
Ответы:
У вас есть несколько проблем в исходном коде:
Как указал @Pat, вы не должны использовать log (dnorm ()), так как это значение может легко переходить в бесконечность. Вы должны использовать logmvdnorm
Когда вы используете сумму , будьте внимательны, чтобы удалить бесконечные или отсутствующие значения
Вы зацикливаете переменную k неправильно, вы должны обновить loglik [k + 1], но вы обновляете loglik [k]
Я также предлагаю вам вставить полные коды (например, как вы инициализируете loglik []) в свой исходный код и сделать отступ для кода, чтобы его было легко читать.
В конце концов, спасибо за введение пакета mixtools , и я планирую использовать их в своих будущих исследованиях.
Я также поставил свой рабочий код для вашей справки:
Historgram
источник
loklik <- rep(NA, 100)
который будет предварительно выделять loglik [1], loglik [2] ... loglik [100]. Я поднимаю этот вопрос, потому что в вашем исходном коде я не нашел делкарации loglik, может быть, код обрезается при вставке?Я продолжаю получать сообщение об ошибке при попытке открыть ваш .rar файл, но это может быть просто из-за того, что я делаю что-то глупое.
Если это проблема, есть несколько возможных решений:
оценивать
но с тау переехал ты получаешь
Другое решение состоит в том, чтобы расширить содержимое внутри логарифма. Предполагая, что вы используете натуральные логарифмы:
Математически то же самое, но должно быть более устойчивым к ошибкам с плавающей запятой, поскольку вы избегаете вычисления большой отрицательной мощности. Это означает, что вы больше не можете использовать встроенную функцию оценки норм, но если это не проблема, возможно, это лучший ответ. Например, скажем, у нас есть ситуация, когда
источник