博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【EM】代码理解
阅读量:5331 次
发布时间:2019-06-14

本文共 4390 字,大约阅读时间需要 14 分钟。

本来想自己写一个EM算法的,但是操作没两步就进行不下去了。对那些数学公式着实不懂。只好从网上找找代码,看看别人是怎么做的。

 

代码:来自 经验证可用

%EMM=3;          % M个高斯分布混合N=600;        % 样本数th=0.000001;  % 收敛阈值K=2;          % 样本维数% 待生成数据的参数a_real =[2/3;1/6;1/6];%混合模型中基模型高斯密度函数的权重mu_real=[3 4 6;5 3 7];%均值cov_real(:,:,1)=[5 0;0 0.2];%协方差cov_real(:,:,2)=[0.1 0;0 0.1];cov_real(:,:,3)=[0.1 0;0 0.1];                    %生成符合标准的样本数据(每一列为一个样本)x=[ mvnrnd( mu_real(:,1) , cov_real(:,:,1) , round(N*a_real(1)) )' ,...    mvnrnd( mu_real(:,2) , cov_real(:,:,2) , round(N*a_real(2)) )' ,...    mvnrnd( mu_real(:,3) , cov_real(:,:,3) , round(N*a_real(3)) )' ]; %初始化参数a=[1/3;1/3;1/3];mu=[1 2 3;2 1 4];cov(:,:,1)=[1 0;0 1];cov(:,:,2)=[1 0;0 1];cov(:,:,3)=[1 0;0 1];t=inf;while t>=th    a_old  = a;    mu_old = mu;    cov_old= cov;         rznk_temp=zeros(M,N);    for k=1:M        for n=1:N            %计算P(x|mu_cm,cov_cm)            rznk_temp(k,n)=exp(-1/2*(x(:,n)-mu(:,k))'*inv(cov(:,:,k))*(x(:,n)-mu(:,k)));        end        rznk_temp(k,:)=rznk_temp(k,:)/sqrt(det(cov(:,:,k)));    end    rznk_temp=rznk_temp*(2*pi)^(-K/2);%E step    %求rznk    rznk=zeros(M,N);    for n=1:N        for k=1:M            rznk(k,n)=a(k)*rznk_temp(k,n);        end        rznk(:,n)=rznk(:,n)/sum(rznk(:,n));    end% M step    %求Nk    nk=zeros(1,M);    nk=sum(rznk');       % 求a    a=nk/N;           % 求MU    for k=1:M        mu_k_sum=0;        for n=1:N            mu_k_sum=mu_k_sum+rznk(k,n)*x(:,n);        end        mu(:,k)=mu_k_sum/nk(k);    end       % 求COV      for k=1:M        cov_k_sum=0;        for n=1:N            cov_k_sum=cov_k_sum+rznk(k,n)*(x(:,n)-mu(:,k))*(x(:,n)-mu(:,k))';        end        cov(:,:,k)=cov_k_sum/nk(k);    end          t=max([norm(a_old(:)-a(:))/norm(a_old(:));norm(mu_old(:)-mu(:))/norm(mu_old(:));norm(cov_old(:)-cov(:))/norm(cov_old(:))]); end

 

分解说明:

M=3;          % M个高斯分布混合N=600;        % 样本数th=0.000001;  % 收敛阈值K=2;          % 样本维数% 待生成数据的参数a_real =[2/3;1/6;1/6];%混合模型中基模型高斯密度函数的权重mu_real=[3 4 6;5 3 7];%均值cov_real(:,:,1)=[5 0;0 0.2];%协方差cov_real(:,:,2)=[0.1 0;0 0.1];cov_real(:,:,3)=[0.1 0;0 0.1];                    %生成符合标准的样本数据(每一列为一个样本)x=[ mvnrnd( mu_real(:,1) , cov_real(:,:,1) , round(N*a_real(1)) )' ,...    mvnrnd( mu_real(:,2) , cov_real(:,:,2) , round(N*a_real(2)) )' ,...    mvnrnd( mu_real(:,3) , cov_real(:,:,3) , round(N*a_real(3)) )' ];

这一部分是产生原始的数据。有600个样本,产生自3个高斯模型,每个模型样本数的比重为 2/3、  1/6、  1/6。

 

%初始化参数a=[1/3;1/3;1/3];mu=[1 2 3;2 1 4];cov(:,:,1)=[1 0;0 1];cov(:,:,2)=[1 0;0 1];cov(:,:,3)=[1 0;0 1];

EM算法第一步,初始化参数。注意,隐含有多少类是要提前知道的。即这里,我们必须知道有3类。

需要初始化的有:三个模型所占的比例、三个模型的均值、三个模型的协方差

 

之后进入大循环,不断迭代E步和M步

rznk_temp=zeros(M,N);    for k=1:M        for n=1:N            %计算P(x|mu_cm,cov_cm)            rznk_temp(k,n)=exp(-1/2*(x(:,n)-mu(:,k))'*inv(cov(:,:,k))*(x(:,n)-mu(:,k)));        end        rznk_temp(k,:)=rznk_temp(k,:)/sqrt(det(cov(:,:,k)));    end    rznk_temp=rznk_temp*(2*pi)^(-K/2);

rznk_temp是一个3行600列的矩阵。每列对应一个样本,每列中的一个数据表示这个样本从第k个高斯模型中抽取到的概率。

比如第100个样本,那rznk_temp(1,100)表示该样本从第1个高斯分布中被抽中的概率。具体求解就是代入高斯模型。

 

%E step    %求rznk    rznk=zeros(M,N);    for n=1:N        for k=1:M            rznk(k,n)=a(k)*rznk_temp(k,n);        end        rznk(:,n)=rznk(:,n)/sum(rznk(:,n));    end

E步:

从原理上:根据参数初始值或上一次迭代的模型参数来计算出隐性变量的后验概率,其实就是隐性变量的期望。作为隐藏变量的现估计值:

                                         

就是我们要根据现有数据求出这600个样本分别来自某一个高斯分布的概率。

代码上:

rznk(k,n)=a(k)*rznk_temp(k,n);   计算选中第k个高斯模型,且抽中样本n的概率

rznk(:,n)=rznk(:,n)/sum(rznk(:,n));   计算第n个模型属于这三个模型概率的百分比。即对于第n个模型来说,它分别属于第1个模型、第2个模型、第3个模型的概率,这三个值加起来为1。

 

% M step    %求Nk    nk=zeros(1,M);    nk=sum(rznk');       % 求a    a=nk/N;           % 求MU    for k=1:M        mu_k_sum=0;        for n=1:N            mu_k_sum=mu_k_sum+rznk(k,n)*x(:,n);        end        mu(:,k)=mu_k_sum/nk(k);    end       % 求COV      for k=1:M        cov_k_sum=0;        for n=1:N            cov_k_sum=cov_k_sum+rznk(k,n)*(x(:,n)-mu(:,k))*(x(:,n)-mu(:,k))';        end        cov(:,:,k)=cov_k_sum/nk(k);    end

M步:

原理上:将似然函数最大化以获得新的参数值,就是最大似然估计。

    

 

公式看起来非常的复杂。

代码上:没有用那个复杂的公式,只是单纯的用得到的rznk更新比例,均值和方差。

nk=sum(rznk'); 综合这600个数据,每个模型被选中的概率和
a=nk/N;  每个模型被选中的概率 除以600是因为之前的和加起来等于600 我们需要归一化
for k=1:M   mu_k_sum=0;   for n=1:N       mu_k_sum=mu_k_sum+rznk(k,n)*x(:,n);    end
mu(:,k)=mu_k_sum/nk(k); 每个模型的均值估计是通过 sum(样本均值*样本被该模型抽中的概率)/sum(样本被该模型抽中的概率)
end

方差同理。

t=max([norm(a_old(:)-a(:))/norm(a_old(:));norm(mu_old(:)-mu(:))/norm(mu_old(:));norm(cov_old(:)-cov(:))/norm(cov_old(:))]);

最后,计算新的值与过去的值的变化率。作为是否迭代完成的条件。

 

转载于:https://www.cnblogs.com/dplearning/p/3981208.html

你可能感兴趣的文章
分层图最短路【bzoj2763】: [JLOI2011]飞行路线
查看>>
FastReport.Net使用:[18]形状(Shape)控件用法
查看>>
linux下编译复数类型引发的错误:expected unqualified-id before '(' token
查看>>
codeforces 1041A Heist
查看>>
字典常用方法
查看>>
Spring Cloud Stream消费失败后的处理策略(三):使用DLQ队列(RabbitMQ)
查看>>
python的猴子补丁monkey patch
查看>>
架构模式: API网关
查看>>
正则验证积累
查看>>
Linux学习-汇总
查看>>
jQuery瀑布流+无限加载图片
查看>>
83. 删除排序链表中的重复元素
查看>>
bzoj1048 [HAOI2007]分割矩阵
查看>>
python中的__init__ 、__new__、__call__等内置函数的剖析
查看>>
Java中的编码
查看>>
PKUWC2018 5/6
查看>>
As-If-Serial 理解
查看>>
MYSQL SHOW VARIABLES简介
查看>>
雷林鹏分享:Redis 简介
查看>>
自卑都是自己不踏实做事的表现
查看>>