深入淺出Mahout K-means (PART 4)- 產生與解讀分群結果

當確認如何取得k-means中心點的方法後,我們要開始將中心點放入HDFS中,回憶一下Kmeans的參數,其中第三個參數就是將資料的中心點放入。

KMeansDriver.run(confnew Path(“testdata/points")new Path(“testdata/clusters"),

new Path(“output")new EuclideanDistanceMeasure()0.00110,

truefalse);

為了要能夠先將中心點放到位於192.168.0.168:9000這台Hadoop的testdata/clusters這個位置,如果我們現在要在以放入資料的List<vector>中取得前k筆的資料當作中心點,中心點的呈現需要透過Cluster(org.apache.mahout.clustering.kmeans.Cluster)這個物件,在寫入中心點的檔案時,其序列化格式為-Text.class與Cluster.class這兩種。</vector>

所以會在SequenceFile.Writer中放入Text.class與Cluster.class。基本上Cluster.class是一個實作org.apache.hadoop.io.Writable的類別,因此可以成為一種序列化I/O輸出的格式。

    Configuration conf = new Configuration();

    FileSystem fs = FileSystem.get(URI.create(“hdfs://192.168.0.168:9000”),      

    conf);

    Path path = new Path(“testdata/clusters/part-00000“);

    SequenceFile.Writer writer = new SequenceFile.Writer(fs, conf, path,    

    Text.classCluster.class);

然而,若真的要能夠將實際點的數值放入,仍需要透過取得Vector的實際值,然後放在Cluster中,在下面程式碼可以看到建立Cluster物件時,需要資料點的向量(vec),第i群以及距離評估公式(new EuclideanDistanceMeasure()),當cluster產生後,writer.append就可以將text資料標記以及cluster物件寫入序列化的檔案。

for (int i = 0; i < k; i++) {

Vector vec = vectors.get(i);

Cluster cluster = new Cluster(vec, i, new EuclideanDistanceMeasure());

writer.append(new Text(cluster.getIdentifier()), cluster);

}

writer.close();

所以從PART-1到現在,三個外部輸入來源都已經確認了,包含:

(1) 外部要輸入的點data:hdfs://192.168.0.168:9000/user/$USER/iris.seq

(2) 我們給的中心點clusters:hdfs://192.168.0.168:9000/user/$USER/testdata/clusters

(3) 還要要輸出的點output:hdfs://192.168.0.168:9000/user/$USER/output/

Configuration conf=new Configuration();

conf.set(“mapred.job.tracker", “hadoop:9001″);

Path data=new Path(“hdfs://192.168.0.168:9000/user/$USER/iris.seq");

Path clusters =new Path(“hdfs://192.168.0.168:9000/user/$USER/testdata/clusters");

Path output =new Path(“hdfs://192.168.0.168:9000/user/$USER/output/");

其它參數給一給,就開始群聚運算了

KMeansDriver.run(confdata, clustersoutputnew EuclideanDistanceMeasure()0.00110,

truefalse);

輸出結果是放在: hdfs://192.168.0.168:9000/user/$USER/output/,其實在裡面的結構會是這樣:

output

– clusteredPoints

– clusters-1

– clusters-2

– clusters-3

我們要將群聚結果讀出,是要找clusteredPoints,在Cluster類別中給了一個參數-Cluster.CLUSTERED_POINTS_DIR,可以協助定位出實際群體位置。

SequenceFile.Reader reader = new SequenceFile.Reader(

fs, new Path(“output/" + Cluster.CLUSTERED_POINTS_DIR + “/part-m-00000″), conf)

最後讓人小感動的一刻出現了,我們只要透過reader.next(key,value)就可以逐筆找到value的值,然後,也可以找到其屬於的群的id。

IntWritable key = new IntWritable();

WeightedVectorWritable value = new WeightedVectorWritable();

while (reader.next(key, value)) {

System.out.println(value.toString() + " belongs to cluster “+ key.toString());

}

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s