zoukankan      html  css  js  c++  java
  • [转载]GMM的EM算法实现

    聚类算法K-Means, K-Medoids, GMM, Spectral clustering,Ncut一文中我们给出了GMM算法的基本模型与似然函数,在EM算法原理中对EM算法的实现与收敛性证明进行了详细说明。本文主要针对如何用EM算法在混合高斯模型下进行聚类进行代码上的分析说明。

    1. GMM模型:

    每个 GMM 由 K 个 Gaussian 分布组成,每个 Gaussian 称为一个“Component”,这些 Component 线性加成在一起就组成了 GMM 的概率密度函数:

    根据上面的式子,如果我们要从 GMM 的分布中随机地取一个点的话,实际上可以分为两步:首先随机地在这 K个Gaussian Component 之中选一个,每个 Component 被选中的概率实际上就是它的系数 pi(k) ,选中了 Component 之后,再单独地考虑从这个 Component 的分布中选取一个点就可以了──这里已经回到了普通的 Gaussian 分布,转化为了已知的问题。

    那么如何用 GMM 来做 clustering 呢?其实很简单,现在我们有了数据,假定它们是由 GMM 生成出来的,那么我们只要根据数据推出 GMM 的概率分布来就可以了,然后 GMM 的 K 个 Component 实际上就对应了 K 个 cluster 了。根据数据来推算概率密度通常被称作 density estimation ,特别地,当我们在已知(或假定)了概率密度函数的形式,而要估计其中的参数的过程被称作“参数估计”。

    2. 参数与似然函数:

    现在假设我们有 N 个数据点,并假设它们服从某个分布(记作 p(x) ),现在要确定里面的一些参数的值,例如,在 GMM 中,我们就需要确定 影响因子pi(k)、各类均值pMiu(k) 和 各类协方差pSigma(k) 这些参数。 我们的想法是,找到这样一组参数,它所确定的概率分布生成这些给定的数据点的概率最大,而这个概率实际上就等于 ,我们把这个乘积称作似然函数 (Likelihood Function)。通常单个点的概率都很小,许多很小的数字相乘起来在计算机里很容易造成浮点数下溢,因此我们通常会对其取对数,把乘积变成加和 sum_{i=1}^N log p(x_i),得到 log-likelihood function 。接下来我们只要将这个函数最大化(通常的做法是求导并令导数等于零,然后解方程),亦即找到这样一组参数值,它让似然函数取得最大值,我们就认为这是最合适的参数,这样就完成了参数估计的过程。

    下面让我们来看一看 GMM 的 log-likelihood function :

    由于在对数函数里面又有加和,我们没法直接用求导解方程的办法直接求得最大值。为了解决这个问题,我们采取之前从 GMM 中随机选点的办法:分成两步,实际上也就类似于K-means 的两步。

    3. 算法流程:

    1.  估计数据由每个 Component 生成的概率(并不是每个 Component 被选中的概率):对于每个数据 x_i 来说,它由第 k 个 Component 生成的概率为

    其中N(xi | μk,Σk)就是后验概率

    2. 通过极大似然估计可以通过求到令参数=0得到参数pMiu,pSigma的值。具体请见这篇文章第三部分。

    其中 N_k = sum_{i=1}^N gamma(i, k) ,并且 pi_k 也顺理成章地可以估计为 N_k/N

    3. 重复迭代前面两步,直到似然函数的值收敛为止。

    4. matlab实现GMM聚类代码与解释:


    说明:fea为训练样本数据,gnd为样本标号。算法中的思想和上面写的一模一样,在最后的判断accuracy方面,由于聚类和分类不同,只是得到一些 cluster ,而并不知道这些 cluster 应该被打上什么标签,或者说。由于我们的目的是衡量聚类算法的 performance ,因此直接假定这一步能实现最优的对应关系,将每个 cluster 对应到一类上去。一种办法是枚举所有可能的情况并选出最优解,另外,对于这样的问题,我们还可以用 Hungarian algorithm 来求解。具体的Hungarian代码我放在了资源里,调用方法已经写在下面函数中了。

    注意:资源里我放的是Kmeans的代码,大家下载的时候只要用bestMap.m等几个文件就好~


    1. gmm.m,最核心的函数,进行模型与参数确定。

    [cpp] view plaincopy

    1. function varargout = gmm(X, K_or_centroids) 
    2. % ============================================================ 
    3. % Expectation-Maximization iteration implementation of 
    4. % Gaussian Mixture Model. 
    5. % PX = GMM(X, K_OR_CENTROIDS) 
    6. % [PX MODEL] = GMM(X, K_OR_CENTROIDS) 
    7. %  - X: N-by-D data matrix. 
    8. %  - K_OR_CENTROIDS: either K indicating the number of 
    9. %       components or a K-by-D matrix indicating the 
    10. %       choosing of the initial K centroids. 
    11. %  - PX: N-by-K matrix indicating the probability of each 
    12. %       component generating each point. 
    13. %  - MODEL: a structure containing the parameters for a GMM: 
    14. %       MODEL.Miu: a K-by-D matrix. 
    15. %       MODEL.Sigma: a D-by-D-by-K matrix. 
    16. %       MODEL.Pi: a 1-by-K vector. 
    17. % ============================================================ 
    18. % @SourceCode Author: Pluskid (http://blog.pluskid.org)
    19. % @Appended by : Sophia_qing (http://blog.csdn.net/abcjennifer)
    20. %% Generate Initial Centroids 
    21.     threshold = 1e-15; 
    22.     [N, D] = size(X); 
    23. if isscalar(K_or_centroids) %if K_or_centroid is a 1*1 number 
    24.         K = K_or_centroids; 
    25.         Rn_index = randperm(N); %random index N samples 
    26.         centroids = X(Rn_index(1:K), :); %generate K random centroid 
    27. else % K_or_centroid is a initial K centroid 
    28.         K = size(K_or_centroids, 1);  
    29.         centroids = K_or_centroids; 
    30.     end 
    31.     %% initial values 
    32.     [pMiu pPi pSigma] = init_params(); 
    33.     Lprev = -inf; %上一次聚类的误差 
    34.     %% EM Algorithm 
    35. while true
    36.         %% Estimation Step 
    37.         Px = calc_prob(); 
    38.         % new value for pGamma(N*k), pGamma(i,k) = Xi由第k个Gaussian生成的概率 
    39.         % 或者说xi中有pGamma(i,k)是由第k个Gaussian生成的 
    40.         pGamma = Px .* repmat(pPi, N, 1); %分子 = pi(k) * N(xi | pMiu(k), pSigma(k)) 
    41.         pGamma = pGamma ./ repmat(sum(pGamma, 2), 1, K); %分母 = pi(j) * N(xi | pMiu(j), pSigma(j))对所有j求和 
    42.         %% Maximization Step - through Maximize likelihood Estimation 
    43.         Nk = sum(pGamma, 1); %Nk(1*k) = 第k个高斯生成每个样本的概率的和,所有Nk的总和为N。 
    44.         % update pMiu 
    45.         pMiu = diag(1./Nk) * pGamma' * X; %update pMiu through MLE(通过令导数 = 0得到) 
    46.         pPi = Nk/N; 
    47.         % update k个 pSigma 
    48. for kk = 1:K  
    49.             Xshift = X-repmat(pMiu(kk, :), N, 1); 
    50.             pSigma(:, :, kk) = (Xshift' * ... 
    51.                 (diag(pGamma(:, kk)) * Xshift)) / Nk(kk); 
    52.         end 
    53.         % check for convergence 
    54.         L = sum(log(Px*pPi')); 
    55. if L-Lprev < threshold 
    56. break; 
    57.         end 
    58.         Lprev = L; 
    59.     end 
    60. if nargout == 1 
    61.         varargout = {Px}; 
    62. else
    63.         model = []; 
    64.         model.Miu = pMiu; 
    65.         model.Sigma = pSigma; 
    66.         model.Pi = pPi; 
    67.         varargout = {Px, model}; 
    68.     end 
    69.     %% Function Definition 
    70.     function [pMiu pPi pSigma] = init_params() 
    71.         pMiu = centroids; %k*D, 即k类的中心点 
    72.         pPi = zeros(1, K); %k类GMM所占权重(influence factor) 
    73.         pSigma = zeros(D, D, K); %k类GMM的协方差矩阵,每个是D*D的 
    74.         % 距离矩阵,计算N*K的矩阵(x-pMiu)^2 = x^2+pMiu^2-2*x*Miu 
    75.         distmat = repmat(sum(X.*X, 2), 1, K) + ... %x^2, N*1的矩阵replicateK列 
    76.             repmat(sum(pMiu.*pMiu, 2)', N, 1) - ...%pMiu^2,1*K的矩阵replicateN行 
    77.             2*X*pMiu'; 
    78.         [~, labels] = min(distmat, [], 2);%Return the minimum from each row 
    79. for k=1:K 
    80.             Xk = X(labels == k, :); 
    81.             pPi(k) = size(Xk, 1)/N; 
    82.             pSigma(:, :, k) = cov(Xk); 
    83.         end 
    84.     end 
    85.     function Px = calc_prob()  
    86.         %Gaussian posterior probability  
    87.         %N(x|pMiu,pSigma) = 1/((2pi)^(D/2))*(1/(abs(sigma))^0.5)*exp(-1/2*(x-pMiu)'pSigma^(-1)*(x-pMiu)) 
    88.         Px = zeros(N, K); 
    89. for k = 1:K 
    90.             Xshift = X-repmat(pMiu(k, :), N, 1); %X-pMiu 
    91.             inv_pSigma = inv(pSigma(:, :, k)); 
    92.             tmp = sum((Xshift*inv_pSigma) .* Xshift, 2); 
    93.             coef = (2*pi)^(-D/2) * sqrt(det(inv_pSigma)); 
    94.             Px(:, k) = coef * exp(-0.5*tmp); 
    95.         end 
    96.     end 
    97. end 

    2. gmm_accuracy.m调用gmm.m,计算准确率:

    [cpp] view plaincopy

    1. function [ Accuracy ] = gmm_accuracy( Data_fea, gnd_label, K ) 
    2. %Calculate the accuracy Clustered by GMM model 
    3. px = gmm(Data_fea,K); 
    4. [~, cls_ind] = max(px,[],1); %cls_ind = cluster label  
    5. Accuracy = cal_accuracy(cls_ind, gnd_label); 
    6.     function [acc] = cal_accuracy(gnd,estimate_label) 
    7.         res = bestMap(gnd,estimate_label); 
    8.         acc = length(find(gnd == res))/length(gnd); 
    9.     end 
    10. end 

    3. 主函数调用

    gmm_acc = gmm_accuracy(fea,gnd,N_classes);

    写了本文进行总结后自己很受益,也希望大家可以好好YM下上面pluskid的gmm.m,不光是算法,其中的矩阵处理代码也写的很简洁,很值得学习。

    另外看了两份东西非常受益,一个是pluskid大牛的漫谈 Clustering (3): Gaussian Mixture Model》,一个是JerryLead的EM算法详解,大家有兴趣也可以看一下,写的很好。

    关于Machine Learning更多的学习资料与相关讨论将继续更新,敬请关注本博客和新浪微博Sophia_qing

  • 相关阅读:
    命名空间 和 class_exist() 问题
    浏览器中打开文件
    memcach 安装
    MySQL事务机制
    Xcode10更新报错:library not found for -lstdc++.6.0.9
    appium-chromedriver@3.0.1 npm ERR! code ELIFECYCLE npm ERR! errno 1
    npm audit fix
    使用WebStorm/IDEA上传本地项目到GitHub
    vue-cli(vue脚手架)超详细教程
    [Swift 开发] 使用闭包传值(typealias)
  • 原文地址:https://www.cnblogs.com/jiayouwyhit/p/3173166.html
Copyright © 2011-2022 走看看