Chcę, aby zaimplementować algorytm EM ręcznie, a następnie porównać je do wyników działań normalmixEM
z mixtools
opakowania. Oczywiście byłbym szczęśliwy, gdyby oba doprowadziły do tych samych rezultatów. Głównym odniesieniem jest Geoffrey McLachlan (2000), Finite Mixture Models .
Mam gęstość mieszanki dwóch Gaussów, w ogólnej formie, logarytmiczne prawdopodobieństwo podaje (McLachlan strona 48):
E krokiem jest teraz obliczenie warunkowa wartość oczekiwana:
Próbowałem napisać kod R (dane można znaleźć tutaj ).
# 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
Algorytm nie działa, ponieważ niektóre obserwacje mają prawdopodobieństwo zerowe, a logarytm z tego jest -Inf
. Gdzie jest mój błąd?
źródło
Odpowiedzi:
Masz kilka problemów z kodem źródłowym:
Jak wskazał @Pat, nie powinieneś używać log (dnorm ()), ponieważ ta wartość może łatwo przejść do nieskończoności. Powinieneś użyć logmvdnorm
Kiedy używasz sumy , pamiętaj, aby usunąć nieskończone lub brakujące wartości
Pętla zmiennej k jest niepoprawna, powinieneś zaktualizować loglik [k + 1], ale zaktualizujesz loglik [k]
Sugeruję również, abyś umieścił pełne kody (np. Jak zainicjalizujesz loglik []) w kodzie źródłowym i wciąć kod, aby ułatwić czytanie.
W końcu dziękuję za wprowadzenie pakietu mixtools i planuję wykorzystać je w moich przyszłych badaniach.
Podaję również mój kod roboczy w celach informacyjnych:
Historgram
źródło
loklik <- rep(NA, 100)
który wstępnie przydzieli loglik [1], loglik [2] ... loglik [100]. Podnoszę to pytanie, ponieważ w twoim oryginalnym kodzie nie znalazłem delcaration loglik, może kod jest obcinany podczas wklejania?Ciągle pojawia się błąd podczas próby otwarcia pliku .rar, ale to może być po prostu to, że robię coś głupiego.
Jeśli to jest problem, istnieje kilka możliwych rozwiązań:
Jednym z nich jest przeniesienie twojegoτ
oceniać
ale z tau poruszasz się
Innym rozwiązaniem jest rozszerzenie elementów wewnątrz logarytmu. Zakładając, że używasz logarytmów naturalnych:
Matematycznie to samo, ale powinien być bardziej odporny na błędy zmiennoprzecinkowe, ponieważ uniknąłeś obliczenia dużej mocy ujemnej. Oznacza to, że nie możesz już korzystać z wbudowanej funkcji oceny norm, ale jeśli nie jest to problem, prawdopodobnie jest to lepsza odpowiedź. Załóżmy na przykład, że mamy sytuację, w której
źródło