用MATLAB做聚類分析時非常有用的自定義距離函數和標準化函數

聚類分析中,經常遇到觀測值缺失的情況.

例如統計歷史降水資料時,某個月的資料缺失了,這時用MATLAB做聚類分析時,

就需要自定義距離函數,處理nan的問題.

下面是相關的MATLAB函數,裏面有例子,可自行修改:

  1. function [ nandistance ] = nandistfun( X,Y,varargin)  
  2. %  A distance function  for pdist,ignoring NaNs  
  3. % [ nandistance ] = nandistfun( X,Y,varargin)  
  4. % arguments :  
  5. % X: 1-by-n vector  
  6. % Y:m-by-n vector  
  7. % nandistance::m-by-1,  whose kth element is the distance between X and Y(k,:).  
  8. %  
  9. %         methods = {'euclidean'; 'seuclidean'; 'cityblock'; 'chebychev'; ...  
  10. %           'mahalanobis'; 'minkowski'; 'cosine'; 'correlation'; ...  
  11. %            'spearman'; 'hamming'; 'jaccard'};  
  12. %  
  13. % Example:  
  14. % >> X =[9, nan, 2, 4, 7;  8, 2, 9, nan, 5;  2, 5, 8, nan, 6];  
  15. % >> D = pdist(X,@nandistfun)  
  16. % >> D= pdist(X,@(a,b)nandistfun(a,b,'seu'))  
  17. %  
  18. %   See also PDIST, SQUAREFORM, LINKAGE, SILHOUETTE, PDIST2.  
  19. %  
  20. %Author:Wu Xuping Date:2013-09-21 Version:1.0.0   
  21.   
  22. [xrow,xcolumn]=size(X);  
  23. [yrow,ycolumn]=size(Y);  
  24. %可變參數的個數  
  25. nVarargs = length(varargin);  
  26. %初始化距離  
  27. nandistance=zeros(yrow,1);  
  28.   
  29. if (xrow==1 && xcolumn==ycolumn)  
  30.     for m=1:yrow  
  31.         x1=X;%必須是行向量,不能是空向量  
  32.         y1=Y(m,:);%必須是行向量,不能是空向量  
  33.         b=( ~isnan(x1)) & (~isnan(y1)); %提取(x1,y1)中都不是nan的索引  
  34.         A=[];  
  35.         A(1,:)=x1(b);%必須是行向量,不能是空向量  
  36.         A(2,:)=y1(b);%必須是行向量,不能是空向量  
  37.         %計算距離  
  38.         if (nVarargs>0)  
  39.             nandistance(m,1) = pdist(A,varargin{:});  
  40.         else  
  41.             nandistance(m,1) = pdist(A); %默認'euc'  
  42.         end  
  43.     end  
  44. end  
  45.   
  46. end  
上面這個函數,包括了常用的各種距離函數.

看完了這個函數的實現方式,我想大家也可以自定義其它類型的距離函數了.

通常做聚類分析時先將數據標準化,matlab提供了zscore函數,不過不支持nans,

這時可以試試下面的函數:

  1. function [ z ] = nanzscore( x )  
  2. %[ z ] = nanzscore( x ),ignoring NaNs  
  3. %   類似於標準化函數[ z ] = zscore( x ),忽略NaNs  
  4. % Author:wuxuping,Date:2013-09-21  
  5.   
  6. nm=nanmean(x);  
  7. ns=nanstd(x);  
  8.   
  9. [xrow,xcolumn]=size(x);  
  10.   
  11. if ((xrow>1 )&&(xcolumn >1))  
  12.     %如果是多行多列的矩陣  
  13.     z=zeros(size(x));  
  14.     for m=1:xrow  
  15.         for n=1:xcolumn  
  16.             z(m,n) = (x(m,n)- nm(n))./ns(n);  
  17.         end  
  18.     end  
  19. else  
  20.     %如果是單行或單列的向量  
  21.     if (xrow==1)  
  22.         for m=1:numel(x)  
  23.             z(m) = (x(m)- nm)./ns;%行向量  
  24.         end  
  25.     else  
  26.         for m=1:numel(x)  
  27.             z(m,1) = (x(m)- nm)./ns;%列向量  
  28.         end  
  29.     end      
  30. end  

上面的標準化函數用起來和zscore是一樣的,只是忽略所有的NaNs.

下面給出是一般的聚類分析過程實例:

  1. x=dlmread(filename);%80*51,八十個站點,測量了51次降水量,現在對八十個站點的降水類型進行聚類分析  
  2. %即將降水類型相同的站點聚爲一類;不同類間的降水類型應該很不相同!  
  3. x=nanzscore( x );%標準化  
  4. %標準化主要是測量值可能爲多個項目如降水量和能見度等,而降水量和能見度的數值記錄相差可能太大.  
  5. %標準化其實就是把各種相差很大的量伸縮到同一個量級上來,否則計算距離時會出現大數吃小數的現象.  
  6. %如果只有降水量,且採用同樣的單位則無需標準化  
  7. D = pdist(x,@nandistfun);%計算距離向量,大小爲:(1*3160)  
  8. %Y = squareform(D,'tomatrix')%格式化距離向量爲矩陣,方便查看  
  9. Z=linkage(D,'average');%採用平均距離法計算聚類,獲取分層聚類樹  
  10. [H,T] =dendrogram(Z,'colorthreshold','default');%繪製聚類圖,返回圖像對象H和聚類表T  
  11. %size(T)應爲80*1  
  12. numCluster=numel(H);%分類的總數,如果numCluster爲29則表明將80個站點分爲29個降水類型  
  13. set(H,'LineWidth',2);%將所有類的線條都加粗爲2  
  14. set(H(5),'LineWidth',5);%將第五類的顏色加粗爲5  
  15. find(T==5)%顯示屬於第五類的索引值  

分層聚類樹圖如下:



剩下的問題是就是如何評價聚類的結果,也就是聚類的結果是否合理?對於合理的聚類,

我們知道同類的相似性一定要大,不同類之間的相似性一定要小.這個同樣也可用距離來度量,當然也有用置信係數或風險係數去度量的.

第一種評價方法:對於第i類,我們計算該類中心的位置,然後該類中的所有站點到中心的距離之和的平均值記爲di,

然後對所有的di求平均得dm,認爲di平均值最小的聚類中同類之間的相似性是最大的,即爲最合理的類.

第二種評價方法:將每一類的中心計算出來,然後將各類中心之間的距離累加,記爲DM,所得的結果最大則表明該種聚類中,各類之間的差異是最大的.

第三種評價方法綜合考慮同類相似性和異類的差異性,計算max(DM)/min(dm),該值取最大則表示該聚類是最合理的聚類.這在matlab中使用表象係數來求解即可.
發佈了9 篇原創文章 · 獲贊 15 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章