深入淺出Mahout K-means (PART 2)- 匯入IRIS資料到Hadoop與Mahout的世界

我們先開始想辦法把IRIS資料(http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data) 匯入到Mahout體系的資料結構中,Mahout這個騎著Hadoop大象的男人,必須要先將問題轉化成Hadoop所看得懂的資料結構,也就是Hadoop的Sequence File格式。

我們為了要將純文字的IRIS資料放入,須確認下述幾件事情:
1. 資料要放的Hadoop平台的位置,並且要能取得Writer過去的權限
要將資料寫到HDFS中,必須要取得HDFS的Writer,SequenceFile.Writer (屬於org.apache.hadoop.io.SequenceFile套件),建構的方法如下:
public SequenceFile.Writer(FileSystem fs,
                           Configuration conf,
                           Path name,
                           Class keyClass,
                           Class valClass)
假設我們要寫入位於192.168.0.168:9000的Hadoop HDFS的使用者家目錄中(例如:在HDFS中使用者ericmao的家目錄會是-/user/ericmao),底下的iris.seq這個序列檔案,序列檔案須包含Key與Value,其中Key的格式為長整數,這個長整數需要是HADOOP的LongWritable,Value的格式為Mahout的向量VectorWritable,所以我們必須先在Writer的建構子當中宣告LongWritable.class與VectorWritable.class這兩個型態。 這邊要強調的是,LongWritable.class是屬於Hadoop套件的資料形態(
org.apache.hadoop.io.LongWritable),而VectorWritable.class是屬於Mahout套件的型態(
org.apache.mahout.math.VectorWritable)。

至於fs參數,是要透過URI的指引取得HDFS的參考,所以如下:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(“hdfs://192.168.0.168:9000”), conf);
SequenceFile.Writer writer = new SequenceFile.Writer(fs, conf, path, LongWritable.class, VectorWritable.class);

這樣就可以取得SequenceFile.Writer的Writer,並且可以繼續後續資料寫入的動作。

2. 資料要轉換成Mahout的向量呈現方式,並且把這些向量以Sequence File的key-value方式寫入Hadoop的HDFS中。

這是IRIS的資料內容:

5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa
5.4,3.9,1.7,0.4,Iris-setosa
4.6,3.4,1.4,0.3,Iris-setosa

因為K-means是非監督是學習,因此我們暫時不需要最後的類別欄位,透過簡單的Java reader我們把資料讀進來。資料抓出來後,我們需要把這些double陣列row的值放入Mahout的RandomAccessSparseVector中,RandomAccessSparseVector是實作Mahout Vector界面的一個專門處理稀疏向量的類別,要建立時只需給予向量長度即可,並且直接將一維陣列(在本例是-row)assgin給他即可,語法如下:

Vector v = new RandomAccessSparseVector(row.length);
v.assign(row);

在此補充說明一下,稀疏向量呈現方式,除了透過RandomAccessSparseVector外,還有SequentialAccessSparseVector,而密集向量則可透過DenseVector,若想要深入瞭解,可參考Mahout in Action的附錄二。

並且為了要把資料透過Writer寫道HDFS中,需把該向量放入VectorWritable中,語法如下:

VectorWritable vec = new VectorWritable();
vec.set(v);

此外,我們也需要將Writer所需寫入Sequence File的Key值產生出來,範例如下:

LongWritable key = new LongWritable(); 
key.set(10); //假設值為10

所以這完整的code整合後如下:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(“hdfs://192.168.0.168:9000”), conf);SequenceFile.Writer writer = new SequenceFile.Writer(fs, conf, path, LongWritable.class, VectorWritable.class);
BufferedReader br = new BufferedReader(new FileReader(“iris.data"));

String temp="";

int value = 0;
while((temp=br.readLine())!=null){
      //取得循序的key值
      LongWritable key = new LongWritable();
      key.set(value++); 

      //取得內容向量
      double[] row = new double[4];
      row[0] =  Double.parseDouble(temp.split(“,")[0]);
      row[1] = Double.parseDouble(temp.split(“,")[1]);
      row[2] = Double.parseDouble(temp.split(“,")[2]);
      row[3] = Double.parseDouble(temp.split(“,")[3]);

      Vector v = new RandomAccessSparseVector(row.length); 
      v.assign(row);
      VectorWritable vec = new VectorWritable();
      vec.set(v);

      //透過writer寫入HDFS中

      writer.append(key,vec);

}

藉此,我們已經把iris.data的資料寫在位於hdfs://192.168.0.168:9000/user/$USER/iris.seq中。

最後在Mahout in Action的第七章的範例 Listing 7.2 The Hello World clustering code,page 123裡面,就有把寫入HDFS的code獨立為一個方法,在這個範例中,List<Vector> points是將Vector存放為ArrayList集合,一堆向量規規矩矩地放在一起就是矩陣了。

public static void writePointsToFile(List<Vector> points,String fileName,FileSystem fs,Configuration conf) throws IOException {

Path path = new Path(fileName);

SequenceFile.Writer writer = new SequenceFile.Writer(fs, conf, path, LongWritable.class, VectorWritable.class);

long recNum = 0;

VectorWritable vec = new VectorWritable();

for (Vector point : points) {

vec.set(point);

writer.append(new LongWritable(recNum++), vec);

}

writer.close();

}

發表迴響

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

WordPress.com 標誌

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

Google+ photo

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

Twitter picture

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

Facebook照片

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

連結到 %s