1. 程式人生 > >用MATLAB做聚類分析

用MATLAB做聚類分析

期工作關係用到Matlab做聚類分析。所謂聚類分析,其目的在於將研究的資料樣本劃分為不同類別。Matlab的統計工具箱提供了相應的分析工具。相關概念在網上可以找到不少資料,這裡推薦兩個部落格供大家參考。

兩個部落格多傾向於聚類演算法的分析,因為聚類分析可劃歸為計算機人工智慧領域裡面無監督的學習。這裡不打算就演算法進行深入,需要的讀者可去諮詢上面兩位牛人。個人覺得漫談系列講解較通俗易懂,趙扶風的可當做進階。

本文中的例子較接近pluskid的漫談系列。Matlab本身帶有Cluster分析的例子。該例子也是經典的聚類分析案例——對IRIS資料聚類分析。可在Mathworks的主頁找到相關資料,地址:

本文重點是展示如何用Matlab來進行聚類分析。如果有需要解答的問題請留言,筆者會盡其所能地回答。

內容

展示如何使用MATLAB進行聚類分析

分別運用分層聚類、K均值聚類以及高斯混合模型來進行分析,然後比較三者的結果

生成隨機二維分佈圖形,三個中心

% 使用高斯分佈(正態分佈)
% 隨機生成3箇中心以及標準差
s = rng(5,'v5normal');
mu = round((rand(3,2)-0.5)*19)+1;
sigma = round(rand(3,2)*40)/10+1;
X = [mvnrnd(mu(1,:),sigma(1,:),200); ...
     mvnrnd(mu(2,:),sigma(2,:),300); ...
     mvnrnd(mu(3,:),sigma(3,:),400)];
% 作圖
P1 = figure;clf;
scatter(X(:,1),X(:,2),10,'ro');
title('研究樣本散點分佈圖')
   

K均值聚類

% 距離用傳統歐式距離,分成兩類
[cidx2,cmeans2,sumd2,D2] = kmeans(X,2,'dist','sqEuclidean');
P2 = figure;clf;
[silh2,h2] = silhouette(X,cidx2,'sqeuclidean');

從輪廓圖上面看,第二類結果比較好,但是第一類有部分資料表現不佳。有相當部分的點落在0.8以下。

分層聚類

eucD = pdist(X,'euclidean');
clustTreeEuc = linkage(eucD,'average');
cophenet(clustTreeEuc,eucD);

P3 = figure;clf;
[h,nodes] =  dendrogram(clustTreeEuc,20);
set(gca,'TickDir','out','TickLength',[.002 0],'XTickLabel',[]);

可以選擇dendrogram顯示的結點數目,這裡選擇20 。結果顯示可能可以分成三類

重新呼叫K均值法

改為分成三類

[cidx3,cmeans3,sumd3,D3] = kmeans(X,3,'dist','sqEuclidean');
P4 = figure;clf;
[silh3,h3] = silhouette(X,cidx3,'sqeuclidean');

圖上看,比前面的結果略有改善。

將分類的結果展示出來

P5 = figure;clf
ptsymb = {'bo','ro','go',',mo','c+'};
MarkFace = {[0 0 1],[.8 0 0],[0 .5 0]};
hold on
for i =1:3
    clust = find(cidx3 == i);
    plot(X(clust,1),X(clust,2),ptsymb{i},'MarkerSize',3,'MarkerFace',MarkFace{i},'MarkerEdgeColor','black');
    plot(cmeans3(i,1),cmeans3(i,2),ptsymb{i},'MarkerSize',10,'MarkerFace',MarkFace{i});
end
hold off

運用高斯混合分佈模型進行聚類分析

分別用分佈圖、熱能圖和概率圖展示結果 等高線

% 等高線
options = statset('Display','off');
gm = gmdistribution.fit(X,3,'Options',options);

P6 = figure;clf
scatter(X(:,1),X(:,2),10,'ro');
hold on
ezcontour(@(x,y) pdf(gm,[x,y]),[-15 15],[-15 10]);
hold off

P7 = figure;clf
scatter(X(:,1),X(:,2),10,'ro');
hold on
ezsurf(@(x,y) pdf(gm,[x,y]),[-15 15],[-15 10]);
hold off
view(33,24)

熱能圖
cluster1 = (cidx3 == 1);
cluster3 = (cidx3 == 2);
% 通過觀察,K均值方法的第二類是gm的第三類
cluster2 = (cidx3 == 3);
% 計算分類概率
P = posterior(gm,X);
P8 = figure;clf
plot3(X(cluster1,1),X(cluster1,2),P(cluster1,1),'r.')
grid on;hold on
plot3(X(cluster2,1),X(cluster2,2),P(cluster2,2),'bo')
plot3(X(cluster3,1),X(cluster3,2),P(cluster3,3),'g*')
legend('第 1 類','第 2 類','第 3 類','Location','NW')
clrmap = jet(80); colormap(clrmap(9:72,:))
ylabel(colorbar,'Component 1 Posterior Probability')
view(-45,20);
% 第三類點部分概率值較低,可能需要其他資料來進行分析。

% 概率圖
P9 = figure;clf
[~,order] = sort(P(:,1));
plot(1:size(X,1),P(order,1),'r-',1:size(X,1),P(order,2),'b-',1:size(X,1),P(order,3),'y-');
legend({'Cluster 1 Score' 'Cluster 2 Score' 'Cluster 3 Score'},'location','NW');
ylabel('Cluster Membership Score');
xlabel('Point Ranking');

通過AIC準則尋找最優的分類數

高斯混合模型法的最大好處是給出分類好壞的標準

AIC = zeros(1,4);
NlogL = AIC;
GM = cell(1,4);
for k = 1:4
    GM{k} = gmdistribution.fit(X,k);
    AIC(k)= GM{k}.AIC;
    NlogL(k) = GM{k}.NlogL;
end
[minAIC,numComponents] = min(AIC);
按AIC準則給出的最優分類數為: 3  對應的AIC值為: 8647.63

後記

(1)pluskid指出K均值演算法的初值對結果很重要,但是在執行時還沒有發現類似的結果。也許Mathworks對該演算法進行過優化。有時間會仔細研究下程式碼,將結果放上來。