详细算法和数学公式在 http://blog.csdn.net/zouxy09
本文主要想实现上述文中的例子:例子简要描述。
某学校抽样100位男生和100位女生的身高,男生和女生身高分别满足各自的高斯分布。现在200个样本数据混乱放置在一起,如何通过EM算法,求出男生身高的均值和标准差?
首先,我们模拟男女生身高样本。模拟男生theta值为mu=1.75, sd=0.316。女生theta值为mu=1.65, sd=0.316
#Data simulation set.seed(1001) mStudent<-rnorm(100,1.75,0.316) fStudent<-rnorm(100,1.65,0.316) totalStu<-cbind(mStudent,fStudent) totalStu1<-c(mStudent,fStudent)
按照EM算法步骤,E-Step. 对hidden vairiable (z)进行估计,把男生和女生分成两类。
################### #E-step: ################### eStep.fn=function(data,flag, muB,sigmaB,muG,sigmaG){ listB = c() listG = c() numB=0 numG=0 for(i in 1:200){ testB<-dnorm(data[i],muB,sigmaB) testG<-dnorm(data[i],muG,sigmaG) pb=testB/(testB+testG) pg=testG/(testB+testG) if(pb>=pg){ numB=numB+1 listB[numB]=data[i] }else{ numG=numG+1 listG[numG]=data[i] } } if(flag==1){ return (listB) }else return (listG) }
接着, M-Step: 对特定的男生类,或者女生类进行MLE估计
#log-likelihood function set.seed(1001) LL.fn <- function(mu, sigma) { R = suppressWarnings(dnorm(data, mu, sigma)) -sum(log(R)) } # Maximum likelihood Estimator mle(LL.fn, start = list(mu = 1, sigma=1))
最后上EM 算法
##################### # Iteration ##################### itr.fn=function(data,muIniB,sigmaIniB,muIniG,sigmaIniG,itrNum){ #E-step dataB<-eStep.fn(data,1,muIniB,sigmaIniB,muIniG,sigmaIniG) dataG<-eStep.fn(data,2,muIniB,sigmaIniB,muIniG,sigmaIniG) #Redefine LL function #log-likelihood function LLB.fn <- function(mu, sigma) { R = suppressWarnings(dnorm(dataB, mu, sigma)) -sum(log(R)) } LLG.fn <- function(mu, sigma) { R = suppressWarnings(dnorm(dataG, mu, sigma)) -sum(log(R)) } # Maximum likelihood Estimator b.mle.coefs<-mle(LLB.fn, start = list(mu=muIniB, sigma=sigmaIniB)) g.mle.coefs<-mle(LLG.fn, start = list(mu=muIniG, sigma=sigmaIniG)) b.muItr<-coef(b.mle.coefs)[["mu"]]#coef(mle.test)[["mu"]] b.sigmaItr<-coef(b.mle.coefs)[["sigma"]] g.muItr<-coef(g.mle.coefs)[["mu"]]#coef(mle.test)[["mu"]] g.sigmaItr<-coef(g.mle.coefs)[["sigma"]] itrNum=itrNum-1 #Iteration-step if(itrNum==0){ return (c(coef(b.mle.coefs),coef(g.mle.coefs))) }else{ itr.fn(data,b.muItr,b.sigmaItr,g.muItr,g.sigmaItr,itrNum) } }
最后结果
itr.fn(totalStu1,1.8,1,1.6,1,n)#n为迭代的次数。
迭代三次,就开始收敛。但是效果不好,下面是结果
bmu bsigma gmu gsigma
1.9658193 0.2170255 1.4610679 0.1583682
对比模拟值:theta值为mu=1.75, sd=0.316。女生theta值为mu=1.65, sd=0.316
下面是简单地思考,在E-step的过程中,由于两个分布重叠部分较大,所以考虑这样在使用R语言求dnorm时,分类情况如下,男生的身高均值在1.96,女生则在1.46。
下一步考虑如何去除这个干扰。。。本篇未完,待续。。。。
参考:
http://www.r-bloggers.com/fitting-a-model-by-maximum-likelihood/
http://xccds1977.blogspot.de/2012/08/emr.html