接上一篇,上一篇主要是計算tfidf,下篇主要是文檔向量的建立以及kmeas的實現。
四 網頁向量以及初始中心點選取
網頁向量以及初始中心點的選取在 DocumentVetorBuid 中的一個 Mapreduce 中完成,中間過程如下表所示。輸出類似如下:
16 26272:0.00587873/22456:0.00264058/22502:0.00289516/23702:0.00278015/
五 Kmeans 聚類實現
DocTool 功能簡介
爲了簡化 Kmeans 過程中的代碼,將計算網頁向量與中心點向量之間的餘弦距離,並根據最大的餘弦距離判斷網頁屬於哪一類的方法抽象出來, Kmeans 的迭代過程中可以直接在調用,簡化了 Kmeans 主類的代碼複雜度。其中,DocTool類中主要方法爲:
public static int returnNearestCentNum(Map<Long, Double> doc,Map<Integer, Map<Long, Double>> centers, long dictSize)
輸入:doc 指代網頁向量,centers 指代所有的中心點向量的集合,dictSize 指代詞表中詞的總數。
輸出:網頁所歸屬的中心點編號。
詳細請見github代碼https://github.com/shenguojun/hadoop/blob/master/WebKmeans/src/edu/sysu/shen/hadoop/DocTool.javaKmeans 主要 Mapreduce 介紹
Kmeans 主類由兩個 Mapreduce 組成,一個是在迭代過程中更新中心點,一個是生成最後的結果,這兩個 Mapreduce 的 Mapper 和 Rducer 的詳細說明如下面兩表所示。輸出類似如下:
16 26272:0.00587873/22456:0.00264058/22502:0.00289516/23702:0.00278015/
上述的 Mapreduce 是在迭代過程的進行的,輸入的是網頁向量,並藉助中心點向量通過計算後得到新的中心點向量作爲輸出。在迭代完畢後,需要最後一個 Mapreduce 輸出符合格式的最終文件。最後一個 Mapreduce 詳細說明如下表。
輸出類似如下:
2977 34
2978 46
2979 36
2980 34
2981 34
2982 34
2983 34
KmeansDriver 流程
KmeansDriver 負責控制所有 MapduceJob 的執行流程,以及建立 configuration 傳入每個Mapreduce 所需要的參數。控制流程如第一部分的實現流程圖所示。其中較爲關鍵是 Kmeans過程中的迭代過程,在迭代過程中由兩個因素控制循環的結束,一個是輸入參數中的最大迭代次數,當達到最大迭代次數後循環就會結束。另一個是判斷新生成的中心點與就的中心點是否相等,如果相等的話就會提前結束,在實驗中,設置 20 箇中心點,平均在迭代 10 次左右就會達到收斂條件。
其中判斷中心點是否收斂的代碼如下。
詳細代碼請見https://github.com/shenguojun/hadoop/blob/master/WebKmeans/src/edu/sysu/shen/hadoop/KmeansDriver.java
//計算是否提前結束
StringBuilder oldCentroid = new StringBuilder();
StringBuilder newCentroid = new StringBuilder();
Path oldCenPath = new Path(tmpPath + "/clustering/depth_"+ (iteration - 1) + "/part-r-00000");
SequenceFile.Reader oldReader = new Reader(fs5, oldCenPath, conf);
IntWritable key = new IntWritable();
Text value = new Text();
//得到舊的中心點向量
while (oldReader.next(key, value)) {
oldCentroid.append(key.toString() + value.toString());
}
oldReader.close();
Path newCenPath = new Path(tmpPath + "/clustering/depth_"+ (iteration) + "/part-r-00000");
SequenceFile.Reader newReader = new Reader(fs5, newCenPath, conf);
IntWritable key1 = new IntWritable();
Text value1 = new Text();
//得到新的中心點向量
while (newReader.next(key1, value1)) {
newCentroid.append(key1.toString() + value1.toString());
}
newReader.close();
iteration++;
//如果聚類中心不變,提前結束迭代
if (newCentroid.toString().equals(oldCentroid.toString()))
break;
六 運行結果
實驗中僞分佈方式對一萬個網站進行聚類,設置 50 箇中心點,執行 5 次迭代,得到運行時間如下表。實驗成功輸出了每個網頁所屬的聚類編號。需要進一步處理的地方是建立網頁向量時維度很大,容易造成維數災難,進一步需要考慮如何降低維數。七 參考
書籍:
《大數據:互聯網大規模數據挖掘與分佈式處理》《Mahout in Action》
《Hadoop in Action》
《Hadoop: The Definitive Guide》
論文:
Weizhong Zhao, Huifang Ma, Qing He.Parallel K-Means Clustering Based on MapReduce .2009Jiang Xiaoping, Li Chenghua, Xiang Wen, Zhang Xinfang, Yan Haitao.k-means 聚 類 算 法 的
MapReduce 並行化實現
網站:
http://codingwiththomas.blogspot.com/2011/05/k-means-clustering-with-mapreduce.htmlhttps://github.com/thomasjungblut/thomasjungblut-common/tree/master/src/de/jungblut/clustering
/mapreduce
http://code.google.com/p/hadoop-clusternet/wiki/RunningMapReduceExampleTFIDF