轉自:http://blog.csdn.net/abcjennifer/article/details/8198352html
在 聚類算法K-Means, K-Medoids, GMM, Spectral clustering,Ncut一文中咱們給出了GMM算法的基本模型與似然函數,在EM算法原理中對EM算法的實現與收斂性證實進行了詳細說明。本文主要針對如何用EM算法在混合高斯模型下進行聚類進行代碼上的分析說明。web
1. GMM模型:算法
每一個 GMM 由 K 個 Gaussian 分佈組成,每一個 Gaussian 稱爲一個「Component」,這些 Component 線性加成在一塊兒就組成了 GMM 的機率密度函數:app

根據上面的式子,若是咱們要從 GMM 的分佈中隨機地取一個點的話,實際上能夠分爲兩步:首先隨機地在這 K個Gaussian Component 之中選一個,每一個 Component 被選中的機率實際上就是它的係數 pi(k) ,選中了 Component 以後,再單獨地考慮從這個 Component 的分佈中選取一個點就能夠了──這裏已經回到了普通的 Gaussian 分佈,轉化爲了已知的問題。dom
那麼如何用 GMM 來作 clustering 呢?其實很簡單,如今咱們有了數據,假定它們是由 GMM 生成出來的,那麼咱們只要根據數據推出 GMM 的機率分佈來就能夠了,而後 GMM 的 K 個 Component 實際上就對應了 K 個 cluster 了。根據數據來推算機率密度一般被稱做 density estimation ,特別地,當咱們在已知(或假定)了機率密度函數的形式,而要估計其中的參數的過程被稱做「參數估計」。ide
2. 參數與似然函數:函數
如今假設咱們有 N 個數據點,並假設它們服從某個分佈(記做 p(x) ),如今要肯定裏面的一些參數的值,例如,在 GMM 中,咱們就須要肯定 影響因子pi(k)、各種均值pMiu(k) 和 各種協方差pSigma(k) 這些參數。 咱們的想法是,找到這樣一組參數,它所肯定的機率分佈生成這些給定的數據點的機率最大,而這個機率實際上就等於
,咱們把這個乘積稱做似然函數 (Likelihood Function)。一般單個點的機率都很小,許多很小的數字相乘起來在計算機裏很容易形成浮點數下溢,所以咱們一般會對其取對數,把乘積變成加和
,獲得 log-likelihood function 。接下來咱們只要將這個函數最大化(一般的作法是求導並令導數等於零,而後解方程),亦即找到這樣一組參數值,它讓似然函數取得最大值,咱們就認爲這是最合適的參數,這樣就完成了參數估計的過程。oop
下面讓咱們來看一看 GMM 的 log-likelihood function :post

因爲在對數函數裏面又有加和,咱們無法直接用求導解方程的辦法直接求得最大值。爲了解決這個問題,咱們採起以前從 GMM 中隨機選點的辦法:分紅兩步,實際上也就相似於K-means 的兩步。學習
3. 算法流程:
1. 估計數據由每一個 Component 生成的機率(並非每一個 Component 被選中的機率):對於每一個數據
來講,它由第
個 Component 生成的機率爲
其中N(xi | μk,Σk)就是後驗機率
。
2. 經過極大似然估計能夠經過求到令參數=0獲得參數pMiu,pSigma的值。具體請見這篇文章第三部分。

其中
,而且
也瓜熟蒂落地能夠估計爲
。
3. 重複迭代前面兩步,直到似然函數的值收斂爲止。
4. matlab實現GMM聚類代碼與解釋:
說明:fea爲訓練樣本數據,gnd爲樣本標號。算法中的思想和上面寫的如出一轍,在最後的判斷accuracy方面,因爲聚類和分類不一樣,只是獲得一些 cluster ,而並不知道這些 cluster 應該被打上什麼標籤,或者說。因爲咱們的目的是衡量聚類算法的 performance ,所以直接假定這一步能實現最優的對應關係,將每一個 cluster 對應到一類上去。一種辦法是枚舉全部可能的狀況並選出最優解,另外,對於這樣的問題,咱們還能夠用 Hungarian algorithm 來求解。具體的Hungarian代碼我放在了資源裏,調用方法已經寫在下面函數中了。
注意:資源裏我放的是Kmeans的代碼,你們下載的時候只要用bestMap.m等幾個文件就好~
1. gmm.m,最核心的函數,進行模型與參數肯定。
- function varargout = gmm(X, K_or_centroids)
- % ============================================================
- % Expectation-Maximization iteration implementation of
- % Gaussian Mixture Model.
- %
- % PX = GMM(X, K_OR_CENTROIDS)
- % [PX MODEL] = GMM(X, K_OR_CENTROIDS)
- %
- % - X: N-by-D data matrix.
- % - K_OR_CENTROIDS: either K indicating the number of
- % components or a K-by-D matrix indicating the
- % choosing of the initial K centroids.
- %
- % - PX: N-by-K matrix indicating the probability of each
- % component generating each point.
- % - MODEL: a structure containing the parameters for a GMM:
- % MODEL.Miu: a K-by-D matrix.
- % MODEL.Sigma: a D-by-D-by-K matrix.
- % MODEL.Pi: a 1-by-K vector.
- % ============================================================
- % @SourceCode Author: Pluskid (http:
- % @Appended by : Sophia_qing (http:
-
-
- %% Generate Initial Centroids
- threshold = 1e-15;
- [N, D] = size(X);
-
- if isscalar(K_or_centroids) %if K_or_centroid is a 1*1 number
- K = K_or_centroids;
- Rn_index = randperm(N); %random index N samples
- centroids = X(Rn_index(1:K), :); %generate K random centroid
- else % K_or_centroid is a initial K centroid
- K = size(K_or_centroids, 1);
- centroids = K_or_centroids;
- end
-
- %% initial values
- [pMiu pPi pSigma] = init_params();
-
- Lprev = -inf; %上一次聚類的偏差
-
- %% EM Algorithm
- while true
- %% Estimation Step
- Px = calc_prob();
-
- % new value for pGamma(N*k), pGamma(i,k) = Xi由第k個Gaussian生成的機率
- % 或者說xi中有pGamma(i,k)是由第k個Gaussian生成的
- pGamma = Px .* repmat(pPi, N, 1); %分子 = pi(k) * N(xi | pMiu(k), pSigma(k))
- pGamma = pGamma ./ repmat(sum(pGamma, 2), 1, K); %分母 = pi(j) * N(xi | pMiu(j), pSigma(j))對全部j求和
-
- %% Maximization Step - through Maximize likelihood Estimation
-
- Nk = sum(pGamma, 1); %Nk(1*k) = 第k個高斯生成每一個樣本的機率的和,全部Nk的總和爲N。
-
- % update pMiu
- pMiu = diag(1./Nk) * pGamma' * X; %update pMiu through MLE(經過令導數 = 0獲得)
- pPi = Nk/N;
-
- % update k個 pSigma
- for kk = 1:K
- Xshift = X-repmat(pMiu(kk, :), N, 1);
- pSigma(:, :, kk) = (Xshift' * ...
- (diag(pGamma(:, kk)) * Xshift)) / Nk(kk);
- end
-
- % check for convergence
- L = sum(log(Px*pPi'));
- if L-Lprev < threshold
- break;
- end
- Lprev = L;
- end
-
- if nargout == 1
- varargout = {Px};
- else
- model = [];
- model.Miu = pMiu;
- model.Sigma = pSigma;
- model.Pi = pPi;
- varargout = {Px, model};
- end
-
- %% Function Definition
-
- function [pMiu pPi pSigma] = init_params()
- pMiu = centroids; %k*D, 即k類的中心點
- pPi = zeros(1, K); %k類GMM所佔權重(influence factor)
- pSigma = zeros(D, D, K); %k類GMM的協方差矩陣,每一個是D*D的
-
- % 距離矩陣,計算N*K的矩陣(x-pMiu)^2 = x^2+pMiu^2-2*x*Miu
- distmat = repmat(sum(X.*X, 2), 1, K) + ... %x^2, N*1的矩陣replicateK列
- repmat(sum(pMiu.*pMiu, 2)', N, 1) - ...%pMiu^2,1*K的矩陣replicateN行
- 2*X*pMiu';
- [~, labels] = min(distmat, [], 2);%Return the minimum from each row
-
- for k=1:K
- Xk = X(labels == k, :);
- pPi(k) = size(Xk, 1)/N;
- pSigma(:, :, k) = cov(Xk);
- end
- end
-
- function Px = calc_prob()
- %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))
- Px = zeros(N, K);
- for k = 1:K
- Xshift = X-repmat(pMiu(k, :), N, 1); %X-pMiu
- inv_pSigma = inv(pSigma(:, :, k));
- tmp = sum((Xshift*inv_pSigma) .* Xshift, 2);
- coef = (2*pi)^(-D/2) * sqrt(det(inv_pSigma));
- Px(:, k) = coef * exp(-0.5*tmp);
- end
- end
- end
2. gmm_accuracy.m調用gmm.m,計算準確率:
- function [ Accuracy ] = gmm_accuracy( Data_fea, gnd_label, K )
- %Calculate the accuracy Clustered by GMM model
-
- px = gmm(Data_fea,K);
- [~, cls_ind] = max(px,[],1); %cls_ind = cluster label
- Accuracy = cal_accuracy(cls_ind, gnd_label);
-
- function [acc] = cal_accuracy(gnd,estimate_label)
- res = bestMap(gnd,estimate_label);
- acc = length(find(gnd == res))/length(gnd);
- end
-
- end
3. 主函數調用
gmm_acc = gmm_accuracy(fea,gnd,N_classes);
寫了本文進行總結後本身很受益,也但願你們能夠好好YM下上面pluskid的gmm.m,不光是算法,其中的矩陣處理代碼也寫的很簡潔,很值得學習。
另外看了兩份東西很是受益,一個是pluskid大牛的《漫談 Clustering (3): Gaussian Mixture Model》,一個是JerryLead的EM算法詳解,你們有興趣也能夠看一下,寫的很好