算法逻辑在这里:

http://www.cnblogs.com/Azhu/p/4131733.html

贴之前先说下,本来呢是打算自己写一个的,在matlab 上,不过,实在是写不出来那么高效和健壮的,网上有很多实现的代码,例如上面参考里面的,那个代码明显有问题阿,然后因为那里面的代码与逻辑分析是一致的,那在其基础上修改看看,结果发现代码健壮性实在太差了,我的数据集是 70-by-2000 的矩阵,70个样本2000维,结果协方差的逆根本算不出来,全部是inf,那去前50维,还是算不出来,这个虽然逻辑是对的,但是这软件的局限阿。

那只能用其他方法了,有一个写的很好的,下面会贴出来,不过都是矩阵运算,看是能看懂的,不过数学计算实在写不出来,按这么来的也只是跟着其敲了一遍,敲之前还看了半天才懂其的数学计算,matlab 的内置函数也不算熟,这里就顺便写下来好了。

主函数:

  • 12-26 行是初始化类标号和其他参数,12行调用了初始标号的参数,实际上初始化的是R。
  • R 是一个n-by-k 矩阵,每项表示一个i-th 样本在 j-th GM 中的概率值,就是p(x|k)。
  • 因为是初始化,所以14行获取了当前类标号label。
  • 27 - 40 是迭代部分,通过判断是否收敛和迭代次数循环
  • 29 是m-step, 这跟我写的算法逻辑有点不同,不过不影响。
  • 29 m-step是假设知道了标号,训练GMM 模型参数,获得的是model。
  • 30 是 e-step,假设训练好了GMM ,计算样本的分配情况,其中loglikehood 是在e-step 中计算了。
  • 剩下的是收敛判断
 function [label, model, llh] = emgm(X, init)
% Perform EM algorithm for fitting the Gaussian mixture model.
% X: d x n data matrix
% init: k ( x ) or label ( x n, <=label(i)<=k) or center (d x k)
% Written by Michael Chen (sth4nth@gmail.com).
%% initialization
% fprintf('EM for Gaussian mixture: running ... \n');
% load('final_initlize');
% X = dataset().x';
% init = dataset().y';
% R n-by-k 矩阵,表示i-th 样本属于j-th 个类的概率,初始化时候为1、,迭代后变是权重化了。
R = initialization(X,init);
% label 表示n 个样本的类标号。
[~,label(,:)] = max(R,[],);
% 这句是为了处理类标号不连续的情况
R = R(:,unique(label)); %pect = zeros(size(label));
% tol 是阀值控制
tol = 1e-;
maxiter = ;
% loglikehood
llh = -inf(,maxiter);
converged = false;
% 当前迭代的标号
t = ;
while ~converged && t < maxiter
t = t+;
model = maximization(X,R);
[R, llh(t)] = expectation(X,model); [~,label(:)] = max(R,[],);
u = unique(label); % non-empty components
if size(R,) ~= size(u,)
R = R(:,u); % remove empty components
else
converged = llh(t)-llh(t-) < tol*abs(llh(t));
end end
llh = llh(:t);
% if converged
% fprintf('Converged in %d steps.\n',t-);
% llh = t-;
% else
% fprintf('Not converged in %d steps.\n',maxiter);
% llh = maxiter;
% end

初始化函数:

这个函数很简单,没什么好解释的。

 %% init
function R = initialization(X, init)
% 初始化一共用4中方式,一种是给定GMM 模型的参数初始值,一种是给定k 的个数,一种是给各sample 的标号,一种是给出类的中心点
[d,n] = size(X);
if isstruct(init) % initialize with a model
R = expectation(X,init);
elseif length(init) == % random initialization
k = init;
idx = randsample(n,k);
m = X(:,idx);
[~,label] = max(bsxfun(@minus,m'*X,dot(m,m,1)'/),[],);
[u,~,label] = unique(label);
while k ~= length(u)
idx = randsample(n,k);
m = X(:,idx);
[~,label] = max(bsxfun(@minus,m'*X,dot(m,m,1)'/),[],);
[u,~,label] = unique(label);
end
R = full(sparse(:n,label,,n,k,n));
elseif size(init,) == && size(init,) == n % initialize with labels
label = init;
k = max(label);
R = full(sparse(:n,label,,n,k,n));
elseif size(init,) == d %initialize with only centers
k = size(init,);
m = init;
[~,label] = max(bsxfun(@minus,m'*X,dot(m,m,1)'/),[],);
R = full(sparse(:n,label,,n,k,n));
else
error('ERROR: init is not valid.');
end

m-step函数:

  • 输入参数 R解释参考上面。
  • 7 计算各类的sample 个数和,一个1-by-k matrix。
  • 8 7中的值除以样本总数就是 GM 的权重,同样是1-by-k matrix。
  • 9 计算GM 样本均值,mu 是个d-by-k matrix,每列表示 k-th GM 的样本均值。
  • 19 计算sqrtR 是为了 15-17行的计算中 结果刚好是R。
  • 15-17 sigma
  • 18行 应该是为了避免sigma 不能逆。
 %% m-step
function model = maximization(X, R)
[d,n] = size(X);
% k 为类个数
k = size(R,);
% 各类的sample个数
nk = sum(R,);
w = nk/n;
mu = bsxfun(@times, X*R, ./nk); Sigma = zeros(d,d,k);
% 这个值是为了下面计算时候得到R,
sqrtR = sqrt(R);
for i = :k
Xo = bsxfun(@minus,X,mu(:,i));
Xo = bsxfun(@times,Xo,sqrtR(:,i)');
Sigma(:,:,i) = Xo*Xo'/nk(i);
Sigma(:,:,i) = Sigma(:,:,i)+eye(d)*(1e-); % add a prior for numerical stability
end model.mu = mu;
model.Sigma = Sigma;
model.weight = w;

e-step:

  • e step 需要解释很多阿。
  • 9 logRho,首先我们知道R 是每项表示一个i-th 样本在 j-th GM 中的概率值,计算公式如下,公式中x是d-by-1 的sample,也就是gamma 中的N()
  • %Gaussian posterior probability
    %N(x|pMiu,pSigma) = 1/((2pi)^(D/2))*(1/(abs(sigma))^0.5)*exp(-1/2*(x-pMiu)'pSigma^(-1)*(x-pMiu))

  • 问题是上面公式不一定能按步求出来阿,例如 sigma^-1,不一定解得出来阿,所以对上面得N()log 一下,后计算,同时避开计算sigma^-1,这个矩阵就是logRho
  • 20-31 便是12 行的函数调用,其中涉及了一堆矩阵转换,验证过没有错,计算的就是log 后的 N()
  • 14 上面公式 gamma 的分子部分。
  • 15-16 是计算当前的loglikehood。
  • 17 计算R 矩阵的log 形式。
  • 18 反计算R。
 %% e-step
function [R, llh] = expectation(X, model)
mu = model.mu;
Sigma = model.Sigma;
w = model.weight; n = size(X,);
k = size(mu,);
logRho = zeros(n,k); for i = :k
logRho(:,i) = loggausspdf(X,mu(:,i),Sigma(:,:,i));
end
logRho = bsxfun(@plus,logRho,log(w));
T = logsumexp(logRho,);
llh = sum(T)/n; % loglikelihood
logR = bsxfun(@minus,logRho,T);
R = exp(logR);
%% log pdf
function y = loggausspdf(X, mu, Sigma) d = size(X,);
X = bsxfun(@minus,X,mu);
[U,p]= chol(Sigma);
if p ~=
error('ERROR: Sigma is not PD.');
end
Q = U'\X;
q = dot(Q,Q,); % quadratic term (M distance)
c = d*log(*pi)+*sum(log(diag(U))); % normalization constant
y = -(c+q)/;

GMM 的EM 实现的更多相关文章

  1. GMM及EM算法

    GMM及EM算法 标签(空格分隔): 机器学习 前言: EM(Exception Maximizition) -- 期望最大化算法,用于含有隐变量的概率模型参数的极大似然估计: GMM(Gaussia ...

  2. 高斯混合模型GMM与EM算法的Python实现

    GMM与EM算法的Python实现 高斯混合模型(GMM)是一种常用的聚类模型,通常我们利用最大期望算法(EM)对高斯混合模型中的参数进行估计. 1. 高斯混合模型(Gaussian Mixture ...

  3. 【机器学习】GMM和EM算法

    机器学习算法-GMM和EM算法 目录 机器学习算法-GMM和EM算法 1. GMM模型 2. GMM模型参数求解 2.1 参数的求解 2.2 参数和的求解 3. GMM算法的实现 3.1 gmm类的定 ...

  4. GMM的EM算法实现

    转自:http://blog.csdn.net/abcjennifer/article/details/8198352 在聚类算法K-Means, K-Medoids, GMM, Spectral c ...

  5. [转载]GMM的EM算法实现

    在聚类算法K-Means, K-Medoids, GMM, Spectral clustering,Ncut一文中我们给出了GMM算法的基本模型与似然函数,在EM算法原理中对EM算法的实现与收敛性证明 ...

  6. GMM的EM算法

    在聚类算法K-Means, K-Medoids, GMM, Spectral clustering,Ncut一文中我们给出了GMM算法的基本模型与似然函数,在EM算法原理中对EM算法的实现与收敛性证明 ...

  7. GMM与EM共舞

    GMM,即高斯混合模型(Gaussian Mixture Model),简单地讲,就是将多个高斯模型混合起来,作为一个新的模型,这样就可以综合运用多模型的表达能力.EM,指的是均值最大化算法(expe ...

  8. GMM与EM算法

    用EM算法估计GMM模型参数 参考  西瓜书 再看下算法流程

  9. 机器学习(七)EM算法、GMM

    一.GMM算法 EM算法实在是难以介绍清楚,因此我们用EM算法的一个特例GMM算法作为引入. 1.GMM算法问题描述 GMM模型称为混合高斯分布,顾名思义,它是由几组分别符合不同参数的高斯分布的数据混 ...

随机推荐

  1. 微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)

    微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞 ...

  2. JavaScript之map与parseInt的陷阱

    问题来源 ​ 这个问题的来源是学习廖雪峰老师JS教程.问题如下:小明希望利用map()把字符串变成整数,他写的代码很简洁: 'use strict'; var arr = ['1', '2', '3' ...

  3. Centos 6版本Device eth0 does not seem to be present,delaying initialization.故障处理

    1.1  故障现象 2019年06月14日晚上,公司项目组说有台业务服务器连接不上,比较着急,我通过vpn拨入的方式远程登录到管理控制台查看发现网卡没有获取到IP地址,我尝试重启来重新启动,重启的时候 ...

  4. tcl之list操作-llength/lindex/lrange/linsert/lreplace

  5. php下关于Cannot use a scalar value as an array的解决办法

    今天在测试php程序的时候,出现了一个错误提示:Cannot use a scalar value as an array,这个错误提示前几天也出过,当时好像稍微调了一下就好了,也没深究,今天却又出现 ...

  6. javascript 计算倒计时

    function timeDown(second) { var month = '', day = '', hour = '', minute = ''; if (second >= 86400 ...

  7. 子窗体与父窗体调用对方js方法

    有时候为了减少一个页面内的代码量,会将部分内容放到子窗体中,如后台管理中用iframe来进行管理 <div> <iframe id="dviframe" src= ...

  8. IntentService和Service执行子线程对比

    1.为何要用子程序 服务是在主线程中执行的,直接在服务中执行耗时操作明显不可取,于是安卓官方增加了IntentService类来方便使用 在Service中执行子程序代码如下 @Override pu ...

  9. WPF学习笔记(8):DataGrid单元格数字为空时避免验证问题的解决

    原文:WPF学习笔记(8):DataGrid单元格数字为空时避免验证问题的解决 如下图,在凭证编辑窗体中,有的单元格不需要数字,但如果录入数字后再删除,会触发数字验证,单元格显示红色框线,导致不能执行 ...

  10. 关于spark入门报错 java.io.FileNotFoundException: File file:/home/dummy/spark_log/file1.txt does not exist

    不想看废话的可以直接拉到最底看总结 废话开始: master: master主机存在文件,却报 执行spark-shell语句:  ./spark-shell  --master spark://ma ...