Expectation Maximization-EM(期望最大化)-算法以及源码
在统计计算中,最大期望(EM)算法是在概率(probabilistic)模型中寻找参数最大似然估计的算法,其中概率模型依赖于无法观测的隐藏变量(Latent Variable)。最大期望经常用在机器学习和计算机视觉的数据聚类(Data Clustering) 领域。最大期望算法经过两个步骤交替进行计算,第一步是计算期望(E),利用对隐藏变量的现有估计值,计算其最大似然估计值;第二步是最大化(M),最大 化在 E 步上求得的最大似然值来计算参数的值。M 步上找到的参数估计值被用于下一个 E 步计算中,这个过程不断交替进行。
最大期望值算法由 Arthur Dempster,Nan Laird和Donald Rubin在他们1977年发表的经典论文中提出。他们指出此方法之前其实已经被很多作者"在他们特定的研究领域中多次提出过"。
我们用 表示能够观察到的不完整的变量值,用 表示无法观察到的变量值,这样 和 一起组成了完整的数据。 可能是实际测量丢失的数据,也可能是能够简化问题的隐藏变量,如果它的值能够知道的话。例如,在混合模型(Mixture Model)中,如果“产生”样本的混合元素成分已知的话最大似然公式将变得更加便利(参见下面的例子)。
估计无法观测的数据
让 代表矢量 θ: 定义的参数的全部数据的概率分布(连续情况下)或者概率聚类函数(离散情况下),那么从这个函数就可以得到全部数据的最大似然值,另外,在给定的观察到的数据条件下未知数据的条件分布可以表示为:
EM算法有这么两个步骤E和M:
- Expectation step: Choose q to maximize F:
- Maximization step: Choose θ to maximize F:
举个例子吧:高斯混合
假设 x = (x1,x2,…,xn) 是一个独立的观测样本,来自两个多元d维正态分布的混合, 让z=(z1,z2,…,zn)是潜在变量,确定其中的组成部分,是观测的来源.
即:
- and
where
- and
目标呢就是估计下面这些参数了,包括混合的参数以及高斯的均值很方差:
似然函数:
where 是一个指示函数 ,f 是 一个多元正态分布的概率密度函数. 可以写成指数形式:
下面就进入两个大步骤了:
E-step
给定目前的参数估计 θ(t), Zi 的条件概率分布是由贝叶斯理论得出,高斯之间用参数 τ加权:
- .
因此,E步骤的结果:
M步骤
Q(θ|θ(t))的二次型表示可以使得 最大化θ相对简单. τ, (μ1,Σ1) and (μ2,Σ2) 可以单独的进行最大化.
首先考虑 τ, 有条件τ1 + τ2=1:
和MLE的形式是类似的,二项分布 , 因此:
下一步估计 (μ1,Σ1):
和加权的 MLE就正态分布来说类似
- and
对称的:
- and .
这个例子来自Answers.com的Expectation-maximization algorithm,由于还没有深入体验,心里还说不出一些更通俗易懂的东西来,等研究了并且应用了可能就有所理解和消化。另外,liuxqsmile也做了一些理解和翻译。
============
在网上的源码不多,有一个很好的EM_GM.m,是滑铁卢大学的Patrick P. C. Tsui写的,拿来分享一下:
运行的时候可以如下进行初始化:
% matlab code
X = zeros(,);
X(:,:) = normrnd(,,,);
X(:,:) = normrnd(,,,);
X(:,:) = normrnd(,,,);
[W,M,V,L] = EM_GM(X,,[],[],,[])
下面是程序源码:
%matlab code function [W,M,V,L] = EM_GM(X,k,ltol,maxiter,pflag,Init)
% [W,M,V,L] = EM_GM(X,k,ltol,maxiter,pflag,Init)
%
% EM algorithm for k multidimensional Gaussian mixture estimation
%
% Inputs:
% X(n,d) - input data, n=number of observations, d=dimension of variable
% k - maximum number of Gaussian components allowed
% ltol - percentage of the log likelihood difference between iterations ([] for none)
% maxiter - maximum number of iteration allowed ([] for none)
% pflag - for plotting GM for 1D or 2D cases only, otherwise ([] for none)
% Init - structure of initial W, M, V: Init.W, Init.M, Init.V ([] for none)
%
% Ouputs:
% W(,k) - estimated weights of GM
% M(d,k) - estimated mean vectors of GM
% V(d,d,k) - estimated covariance matrices of GM
% L - log likelihood of estimates
%
% Written by
% Patrick P. C. Tsui,
% PAMI research group
% Department of Electrical and Computer Engineering
% University of Waterloo,
% March,
% %%%% Validate inputs %%%%
if nargin <= ,
disp('EM_GM must have at least 2 inputs: X,k!/n')
return
elseif nargin == ,
ltol = 0.1; maxiter = ; pflag = ; Init = [];
err_X = Verify_X(X);
err_k = Verify_k(k);
if err_X | err_k, return; end
elseif nargin == ,
maxiter = ; pflag = ; Init = [];
err_X = Verify_X(X);
err_k = Verify_k(k);
[ltol,err_ltol] = Verify_ltol(ltol);
if err_X | err_k | err_ltol, return; end
elseif nargin == ,
pflag = ; Init = [];
err_X = Verify_X(X);
err_k = Verify_k(k);
[ltol,err_ltol] = Verify_ltol(ltol);
[maxiter,err_maxiter] = Verify_maxiter(maxiter);
if err_X | err_k | err_ltol | err_maxiter, return; end
elseif nargin == ,
Init = [];
err_X = Verify_X(X);
err_k = Verify_k(k);
[ltol,err_ltol] = Verify_ltol(ltol);
[maxiter,err_maxiter] = Verify_maxiter(maxiter);
[pflag,err_pflag] = Verify_pflag(pflag);
if err_X | err_k | err_ltol | err_maxiter | err_pflag, return; end
elseif nargin == ,
err_X = Verify_X(X);
err_k = Verify_k(k);
[ltol,err_ltol] = Verify_ltol(ltol);
[maxiter,err_maxiter] = Verify_maxiter(maxiter);
[pflag,err_pflag] = Verify_pflag(pflag);
[Init,err_Init]=Verify_Init(Init);
if err_X | err_k | err_ltol | err_maxiter | err_pflag | err_Init, return; end
else
disp('EM_GM must have 2 to 6 inputs!');
return
end %%%% Initialize W, M, V,L %%%%
t = cputime;
if isempty(Init),
[W,M,V] = Init_EM(X,k); L = ;
else
W = Init.W;
M = Init.M;
V = Init.V;
end
Ln = Likelihood(X,k,W,M,V); % Initialize log likelihood
Lo = *Ln; %%%% EM algorithm %%%%
niter = ;
while (abs(*(Ln-Lo)/Lo)>ltol) & (niter<=maxiter),
E = Expectation(X,k,W,M,V); % E-step
[W,M,V] = Maximization(X,k,E); % M-step
Lo = Ln;
Ln = Likelihood(X,k,W,M,V);
niter = niter + ;
end
L = Ln; %%%% Plot 1D or 2D %%%%
if pflag==,
[n,d] = size(X);
if d>,
disp('Can only plot 1 or 2 dimensional applications!/n');
else
Plot_GM(X,k,W,M,V);
end
elapsed_time = sprintf('CPU time used for EM_GM: %5.2fs',cputime-t);
disp(elapsed_time);
disp(sprintf('Number of iterations: %d',niter-));
end
%%%%%%%%%%%%%%%%%%%%%%
%%%% End of EM_GM %%%%
%%%%%%%%%%%%%%%%%%%%%% function E = Expectation(X,k,W,M,V)
[n,d] = size(X);
a = (*pi)^(0.5*d);
S = zeros(,k);
iV = zeros(d,d,k);
for j=:k,
if V(:,:,j)==zeros(d,d), V(:,:,j)=ones(d,d)*eps; end
S(j) = sqrt(det(V(:,:,j)));
iV(:,:,j) = inv(V(:,:,j));
end
E = zeros(n,k);
for i=:n,
for j=:k,
dXM = X(i,:)'-M(:,j);
pl = exp(-0.5*dXM'*iV(:,:,j)*dXM)/(a*S(j));
E(i,j) = W(j)*pl;
end
E(i,:) = E(i,:)/sum(E(i,:));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Expectation %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [W,M,V] = Maximization(X,k,E)
[n,d] = size(X);
W = zeros(,k); M = zeros(d,k);
V = zeros(d,d,k);
for i=:k, % Compute weights
for j=:n,
W(i) = W(i) + E(j,i);
M(:,i) = M(:,i) + E(j,i)*X(j,:)';
end
M(:,i) = M(:,i)/W(i);
end
for i=:k,
for j=:n,
dXM = X(j,:)'-M(:,i);
V(:,:,i) = V(:,:,i) + E(j,i)*dXM*dXM';
end
V(:,:,i) = V(:,:,i)/W(i);
end
W = W/n;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Maximization %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function L = Likelihood(X,k,W,M,V)
% Compute L based on K. V. Mardia, "Multivariate Analysis", Academic Press, , PP. -
% to enchance computational speed
[n,d] = size(X);
U = mean(X)';
S = cov(X);
L = ;
for i=:k,
iV = inv(V(:,:,i));
L = L + W(i)*(-0.5*n*log(det(*pi*V(:,:,i))) ...
-0.5*(n-)*(trace(iV*S)+(U-M(:,i))'*iV*(U-M(:,i))));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Likelihood %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%% function err_X = Verify_X(X)
err_X = ;
[n,d] = size(X);
if n<d,
disp('Input data must be n x d!/n');
return
end
err_X = ;
%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Verify_X %%%%
%%%%%%%%%%%%%%%%%%%%%%%%% function err_k = Verify_k(k)
err_k = ;
if ~isnumeric(k) | ~isreal(k) | k<,
disp('k must be a real integer >= 1!/n');
return
end
err_k = ;
%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Verify_k %%%%
%%%%%%%%%%%%%%%%%%%%%%%%% function [ltol,err_ltol] = Verify_ltol(ltol)
err_ltol = ;
if isempty(ltol),
ltol = 0.1;
elseif ~isreal(ltol) | ltol<=,
disp('ltol must be a positive real number!');
return
end
err_ltol = ;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Verify_ltol %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [maxiter,err_maxiter] = Verify_maxiter(maxiter)
err_maxiter = ;
if isempty(maxiter),
maxiter = ;
elseif ~isreal(maxiter) | maxiter<=,
disp('ltol must be a positive real number!');
return
end
err_maxiter = ;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Verify_maxiter %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [pflag,err_pflag] = Verify_pflag(pflag)
err_pflag = ;
if isempty(pflag),
pflag = ;
elseif pflag~= & pflag~=,
disp('Plot flag must be either 0 or 1!/n');
return
end
err_pflag = ;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Verify_pflag %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [Init,err_Init] = Verify_Init(Init)
err_Init = ;
if isempty(Init),
% Do nothing;
elseif isstruct(Init),
[Wd,Wk] = size(Init.W);
[Md,Mk] = size(Init.M);
[Vd1,Vd2,Vk] = size(Init.V);
if Wk~=Mk | Wk~=Vk | Mk~=Vk,
disp('k in Init.W(1,k), Init.M(d,k) and Init.V(d,d,k) must equal!/n')
return
end
if Md~=Vd1 | Md~=Vd2 | Vd1~=Vd2,
disp('d in Init.W(1,k), Init.M(d,k) and Init.V(d,d,k) must equal!/n')
return
end
else
disp('Init must be a structure: W(1,k), M(d,k), V(d,d,k) or []!');
return
end
err_Init = ;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Verify_Init %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [W,M,V] = Init_EM(X,k)
[n,d] = size(X);
[Ci,C] = kmeans(X,k,'Start','cluster', ...
'Maxiter',, ...
'EmptyAction','drop', ...
'Display','off'); % Ci(nx1) - cluster indeices; C(k,d) - cluster centroid (i.e. mean)
while sum(isnan(C))>,
[Ci,C] = kmeans(X,k,'Start','cluster', ...
'Maxiter',, ...
'EmptyAction','drop', ...
'Display','off');
end
M = C';
Vp = repmat(struct('count',,'X',zeros(n,d)),,k);
for i=:n, % Separate cluster points
Vp(Ci(i)).count = Vp(Ci(i)).count + ;
Vp(Ci(i)).X(Vp(Ci(i)).count,:) = X(i,:);
end
V = zeros(d,d,k);
for i=:k,
W(i) = Vp(i).count/n;
V(:,:,i) = cov(Vp(i).X(:Vp(i).count,:));
end
%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Init_EM %%%%
%%%%%%%%%%%%%%%%%%%%%%%% function Plot_GM(X,k,W,M,V)
[n,d] = size(X);
if d>,
disp('Can only plot 1 or 2 dimensional applications!/n');
return
end
S = zeros(d,k);
R1 = zeros(d,k);
R2 = zeros(d,k);
for i=:k, % Determine plot range as x standard deviations
S(:,i) = sqrt(diag(V(:,:,i)));
R1(:,i) = M(:,i)-*S(:,i);
R2(:,i) = M(:,i)+*S(:,i);
end
Rmin = min(min(R1));
Rmax = max(max(R2));
R = [Rmin:0.001*(Rmax-Rmin):Rmax];
clf, hold on
if d==,
Q = zeros(size(R));
for i=:k,
P = W(i)*normpdf(R,M(:,i),sqrt(V(:,:,i)));
Q = Q + P;
plot(R,P,'r-'); grid on,
end
plot(R,Q,'k-');
xlabel('X');
ylabel('Probability density');
else % d==
plot(X(:,),X(:,),'r.');
for i=:k,
Plot_Std_Ellipse(M(:,i),V(:,:,i));
end
xlabel('1^{st} dimension');
ylabel('2^{nd} dimension');
axis([Rmin Rmax Rmin Rmax])
end
title('Gaussian Mixture estimated by EM');
%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Plot_GM %%%%
%%%%%%%%%%%%%%%%%%%%%%%% function Plot_Std_Ellipse(M,V)
[Ev,D] = eig(V);
d = length(M);
if V(:,:)==zeros(d,d),
V(:,:) = ones(d,d)*eps;
end
iV = inv(V);
% Find the larger projection
P = [,;,]; % X-axis projection operator
P1 = P * *sqrt(D(,)) * Ev(:,);
P2 = P * *sqrt(D(,)) * Ev(:,);
if abs(P1()) >= abs(P2()),
Plen = P1();
else
Plen = P2();
end
count = ;
step = 0.001*Plen;
Contour1 = zeros(,);
Contour2 = zeros(,);
for x = -Plen:step:Plen,
a = iV(,);
b = x * (iV(,)+iV(,));
c = (x^) * iV(,) - ;
Root1 = (-b + sqrt(b^ - *a*c))/(*a);
Root2 = (-b - sqrt(b^ - *a*c))/(*a);
if isreal(Root1),
Contour1(count,:) = [x,Root1] + M';
Contour2(count,:) = [x,Root2] + M';
count = count + ;
end
end
Contour1 = Contour1(:count-,:);
Contour2 = [Contour1(,:);Contour2(:count-,:);Contour1(count-,:)];
plot(M(),M(),'k+');
plot(Contour1(:,),Contour1(:,),'k-');
plot(Contour2(:,),Contour2(:,),'k-');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% End of Plot_Std_Ellipse %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
from: http://www.zhizhihu.com/html/y2010/2109.html
Expectation Maximization-EM(期望最大化)-算法以及源码的更多相关文章
- EM 期望最大化算法
(EM算法)The EM Algorithm EM是我一直想深入学习的算法之一,第一次听说是在NLP课中的HMM那一节,为了解决HMM的参数估计问题,使用了EM算法.在之后的MT中的词对齐中也用到了. ...
- GWO(灰狼优化)算法MATLAB源码逐行中文注解(转载)
以优化SVM算法的参数c和g为例,对GWO算法MATLAB源码进行了逐行中文注解. tic % 计时器 %% 清空环境变量 close all clear clc format compact %% ...
- SURF算法与源码分析、下
上一篇文章 SURF算法与源码分析.上 中主要分析的是SURF特征点定位的算法原理与相关OpenCV中的源码分析,这篇文章接着上篇文章对已经定位到的SURF特征点进行特征描述.这一步至关重要,这是SU ...
- 6种基础排序算法java源码+图文解析[面试宝典]
一.概述 作为一个合格的程序员,算法是必备技能,特此总结6大基础算法.java版强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步:1.思想2.图 ...
- 十大基础排序算法[java源码+动静双图解析+性能分析]
一.概述 作为一个合格的程序员,算法是必备技能,特此总结十大基础排序算法.java版源码实现,强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步: ...
- SURF算法与源码分析、上
如果说SIFT算法中使用DOG对LOG进行了简化,提高了搜索特征点的速度,那么SURF算法则是对DoH的简化与近似.虽然SIFT算法已经被认为是最有效的,也是最常用的特征点提取的算法,但如果不借助于硬 ...
- 三种排序算法python源码——冒泡排序、插入排序、选择排序
最近在学习python,用python实现几个简单的排序算法,一方面巩固一下数据结构的知识,另一方面加深一下python的简单语法. 冒泡排序算法的思路是对任意两个相邻的数据进行比较,每次将最小和最大 ...
- Java数据结构和算法 - TreeMap源码理解红黑树
前言 本篇将结合JDK1.6的TreeMap源码,来一起探索红-黑树的奥秘.红黑树是解决二叉搜索树的非平衡问题. 当插入(或者删除)一个新节点时,为了使树保持平衡,必须遵循一定的规则,这个规则就是红- ...
- faster rcnn算法及源码及论文解析相关博客
1. 通过代码理解faster-RCNN中的RPN http://blog.csdn.net/happyflyy/article/details/54917514 2. faster rcnn详解 R ...
随机推荐
- 面试题41:和为s的两个数字 || 和为s的连续正数序列
和为s的两个数字 题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s.如果有多对数字的和等于s,输出任意一对即可. 有点类似于夹逼的思想 注意两个int相加的和要用lo ...
- Django实战(21):使用内置的Amin管理用户
到目前为止,我们开发的所有功能都是匿名访问的,这显然不够安全.通常我们会要求注册的用户通过用户名和密码登录,只有登录后的用户才可以管理产品.套用专业的说法就是:第一步是认证,验证用户是否是他所宣称的那 ...
- JFinal框架使用
表单直接提交页面,不用ajax 后台; /** * 修改 */ public void edit() { String id=getPara("id"); String job=g ...
- 解释一下什么是servlet?
Servlet是一种独立于平台和协议的服务器端的Java技术,可以用来生成动态的Web页面.与传统的CGI(计算机图形接口)和许多其他类似CGI技术相比,Servlet具有更好的可移植性.更强大的功能 ...
- jQuery中bind,live,delegate,on的区别
bind(),live()都是调用on()函数,只不过传递的参数不同. 一.$(selector).bind(event,data,fn); $('#J_btn').bind('click',func ...
- 防止sql注入的几种方法
一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体 ...
- Django-url反向解析与csrf-token设置
url反向解析 在使用Django 项目时,一个常见的需求是获得URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等). 人们强烈希望不要硬 ...
- 韩梦飞沙Android应用集合 想法
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 那些收藏的图片 那些收藏的微博 那些收藏的音乐 定时短信 音乐列表汇 每天都是快乐的
- uoj407 【IOI2018】狼人
link 题意: 给一张n个点m条边的无向图,有q个询问,每次询问给出s,t,l,r,问你能否从s走到t,并且初始为人形,结束时必须为狼形,你是人形的时候必须避开$[1,l)$的节点,狼形的时候必须避 ...
- Windows Server 2008 R2的web服务器nginx和Apache的比较
因为很喜欢nginx,所以也想尝试在Windows下使用nginx,前面安装配置都挺顺利,把域名解析尽量后,通过域名代理访问jboss,却异常的慢,起码有3秒的时间才显示页面,而这个页面是jboss的 ...