第九章聚類算法
9.1 K-means聚類
K-means需要用戶設定一個聚類個數(k)作為輸入數據,有時k值可能非常大(10,000),這是Mahout閃光的(shines)地方,它確保聚類的可測量性。
為了用k-means達到高質量的聚類,需要估計一個k值。估計k值一種近似的方法是根據你需要的聚類個數。比如100萬篇文章,如果平均500篇分為一類,k值可以取2000(1000000/500)。這種估計聚類個數非常模糊,但k-means算法就是生成這種近似的聚類。
9.1.1 All you need to know about k-means
下面看一下k-means算法的細節,K-means算法是硬聚類算法,是典型的局域原型的目標函數聚類方法的代表,它是數據點到原型的某種距離作為優化的目標函數,利用函數求極值的方法得到迭代運算的調整規則。算法采用誤差平方和准則函數作為聚類准則函數。K-means算法是很典型的基於距離的聚類算法,采用距離作為相似性的評價指標,即認為兩個對象的距離越近,其相似度就越大。該算法認為簇是由距離靠近的對象組成的,因此把得到緊湊且獨立的簇作為最終目標。k個初始類聚類中心點的選取對聚類結果具有較大的。
算法步驟:
(1)隨機選取任意k個對象作為初始聚類中心,初始代表一個簇;
(2)計算點到質心的距離,並把它歸到最近的質心的類;
(3)重新計算已經得到的各個類的質心;
(4)迭代2~3步直至新的質心與原質心相等或小於指定閾值,算法結束。
這種兩步算法是最大期望算法(EM)的典型例子,
第一步是計算期望(E),利用對隱藏變量的現有估計值,計算其最大似然估計值;
第二步是最大化(M),最大化在 E 步上求得的最大似然值來計算參數的值。
M 步上找到的參數估計值被用於下一個 E 步計算中,這個過程不斷交替進行。
9.1.2 Running k-means clustering
K-mean聚類用到KMeansClusterer或KMeansDriver類,前一個是在內存(in-memory)里對節點聚類,后者采用MapReduce任務執行。這兩種方法都可以就像一個普通的Java程序運行,並且可以從硬盤讀取和寫入數據。它們也可以在hadoop上執行聚類,通過分布式文件系統讀寫數據。
下面舉例,使用一個隨機點生成器函數來創建一些點。這些點生成矢量格式的點作為一個正態分布圍繞着一個中心。使用Mahout的in-memory K-means 聚類方法對這些點聚類。
創建節點:generateSamples方法,取(1,1)為中心點,標准差為2,400個圍繞着(1,1)的隨機點,近似於正態分布。另外又取了2個數據集,中心分別為(1,0)和(0,2),標准差分別為0.5和0.1。
KMeansClusterer.clusterPoints()方法用到一下參數:
- List<Vector>作為輸入;
- 距離算法DistanceMeasure采用EuclideanDistanceMeasure;
- 聚類的閾值Threshold為0.01;
- 聚類的個數為3;
- 聚類的中心點采用RandomPointsUtil,隨機選取的節點。
Mahout-example里的DisplayKMeans類可以直觀的看到該算法在二維平面的結果,9.2節將介紹運行一個Java Swing application的DisplayKMeans。
如果數據量很大時,應采取MapReduce運行方式,將聚類算法運行在多個機器上,每個mapper得到一個子集的點,每個子集運行一個mapper。這些mapper任務計算出最近的集群作為輸入流。
K-means聚類的MapReduce Job
采用KMeansDriver類的run()方法,需要輸入的參數有:
- Hadoop的配置conf;
- 輸入Vectors的路徑,SequenceFile格式;
- 初始化聚類中心的路徑,SequenceFile格式;
- 輸出結果的路徑,SequenceFile格式;
- 求相似距離時采用的方法,這里采用EuclideanDistanceMeasure;
- 收斂的閾值,沒有超過該閾值的點可移動時,停止迭代;
- 最大迭代次數,這是硬性限制,到達該最大迭代次數時,聚類停止;
- true-迭代結束后聚類;
- true-串行執行該算法,false-並行執行該算法;
public static void run(Configuration conf,Path input,Path clustersIn,Path output,
DistanceMeasure measure,
double convergenceDelta,
int maxIterations,
boolean runClustering,
boolean runSequential)
采用SparseVectorsFromSequenceFile工具,將sequenceFile轉換成Vector,因為K-means算法需要用戶初始化k個質心。