http://blog.csdn.net/wangxin110000/article/details/22404983
EM有很多公式推导,这里还是先说下EM思想,前面说过EM是最大似然估计的思路,但是他的方法是用 参数与数据 去估计 参数,直到估计出的参数基本正确;
很多初学的对EM感到困惑,常常被一堆公式所迷惑,这样不利于深入理解EM,在此我也不想用一堆公式去推倒这个思想的数学证明;我只想给初学EM的读者一个感性的认识以及一些学习建议:
拿K-means来做个例子,我们要求的是聚类中心,我们是怎么做的呢?我们假设若一个聚类中心,然后通过这些聚类中心去得到某些东西,然后我们通过得到这些东西再去更新聚类中心;放到GMM模型中,就是我们假设某个参数,然后通过这个参数得到某个中间变量,再用这个中间变量去更新参数!
如果你还不能理解?
在概率中我们一个数据的期望是不是可以用成我们观测数据的均值去估计,如果两者一致,就叫无偏估计,好了,这是一个统计与估计相互验证的问题,GMM中就是这样一个思路:数据的统计与估计相互验证,我猜个参数,用参数去进行统计,再用统计值对参数进行估计!(再次强调我这里说的不是EM的证明,EM的证明指的的为什么我这么做最后能趋向于正确!是一个收敛性证明!)
如果你想从感性到理性逐渐理解:
建议你首先看看三个硬币模型,再去看下GMM的实际执行过程,再去看下EM的证明,结合起来,相信很快就能理解!
下面是EM算法在三个硬币模型中的代码
- #include <iostream>
- #include <math.h>
- using namespace std;
- typedef struct theta
- {
- double pi;
- double p;
- double q;
- theta(double piInput,double pInput,double qInput):pi(piInput),p(pInput),q(qInput)
- {
- }
- }Theta;
- void threeCoins(int *pData,int nSize,int nNum,Theta &thetaStart);
- int main()
- {
- int pData[10]={1,1,0,1,0,0,1,0,1,1};
- Theta thetaStart(0.5,0.5,0.5);
- threeCoins(pData,10,10,thetaStart);
- getchar();
- return 0;
- }
- //nNum是迭代次数
- void threeCoins(int *pData,int nSize,int nNum,Theta &thetaStart)
- {
- double *u=new double[nSize];
- memset(u,0,sizeof(double)*nSize);
- Theta thetaTemp=thetaStart;
- int iNum=0;
- while(iNum<nNum)
- {
- for (int i=0;i<nSize;i++)
- {
- u[i]=thetaTemp.pi*pow(thetaTemp.p,pData[i])*pow(1-thetaTemp.p,pData[i])
- /(thetaTemp.pi*pow(thetaTemp.p,pData[i])*pow(1-thetaTemp.p,pData[i])+(1-thetaTemp.pi)*pow(thetaTemp.q,pData[i])*pow(1-thetaTemp.q,1-pData[i]));
- }
- double uSum=0;
- for (int i=0;i<nSize;i++)
- {
- uSum+=u[i];
- }
- thetaTemp.pi=uSum/nSize;
- double uSum2=0;
- for (int i=0;i<nSize;i++)
- {
- uSum2+=u[i]*pData[i];
- }
- thetaTemp.p=uSum2/uSum;
- double uSum3=0;
- for (int i=0;i<nSize;i++)
- {
- uSum3+=pData[i];
- }
- thetaTemp.q=(uSum3-uSum2)/(nSize-uSum);
- cout<<thetaTemp.pi<<'\t'<<thetaTemp.p<<'\t'<<thetaTemp.q<<endl;
- iNum++;
- }
- delete []u;
- }