2012-12-01 55 views
5

我正在用Mahout分析k-means算法。我將運行一些測試,觀察性能,並根據我得到的結果進行一些統計。Mahout:CSV矢量和運行程序

我想不出在Mahout中運行我自己的程序的方式。但是,命令行界面可能就足夠了。

運行示例程序我做

$ mahout seqdirectory --input uscensus --output uscensus-seq 
$ mahout seq2sparse -i uscensus-seq -o uscensus-vec 
$ mahout kmeans -i reuters-vec/tfidf-vectors -o uscensus-kmeans-clusters -c uscensus-kmeans-centroids -dm org.apache.mahout.common.distance.CosineDistanceMeasure -x 5 -ow -cl -k 25 

數據集是一個大的CSV文件。每條線都是一條記錄。功能以逗號分隔。第一個字段是一個ID。 由於輸入格式,我無法立即使用seqdirectory。 我想實現這個問題的答案類似的問題How to perform k-means clustering in mahout with vector data stored as CSV?但我仍然有2個問題:

  1. 如何從CSV轉換爲SeqFile?我想我可以使用Mahout編寫自己的 程序進行此轉換,然後使用其輸出 作爲seq2parse的輸入。我想我可以使用CSVIterator(https://cwiki.apache.org/confluence/display/MAHOUT/File+Format+Integrations)。我應該用什麼課程來閱讀和寫作?
  2. 如何構建並運行我的新程序?我無法在Mahout這本書的行動或其他問題中弄清楚。

回答

5

爲了以SequenceFile格式獲取數據,您可以採取幾項策略。兩者都涉及編寫自己的代碼 - 即不嚴格的命令行。

策略1 使用Mahout的CSVVectorIterator類。您將它傳遞給一個java.io.Reader,它將讀取您的CSV文件,將每行轉換爲DenseVector。我從來沒有使用過,但在API中看到它。如果你對DenseVectors有好處,看起來很簡單。

策略2 編寫您自己的解析器。這很簡單,因爲您只需將每行分割爲「,」並且您可以循環訪問數組。對於每一行的值的每個陣列,則使用這樣的實例化一個矢量:

new DenseVector(<your array here>); 

並將其添加到列表(例如)。

然後......一旦你有載體列表,你可以把它們寫到使用這樣的事情SequenceFiles(我用下面的代碼NamedVectors):

FileSystem fs = null; 
SequenceFile.Writer writer; 
Configuration conf = new Configuration(); 

List<NamedVector> vectors = <here's your List of vectors obtained from CSVVectorIterator>; 

// Write the data to SequenceFile 
try { 
    fs = FileSystem.get(conf); 

    Path path = new Path(<your path> + <your filename>); 
    writer = new SequenceFile.Writer(fs, conf, path, Text.class, VectorWritable.class); 

    VectorWritable vec = new VectorWritable(); 
    for (NamedVector vector : dataVector) { 

     vec.set(vector); 
     writer.append(new Text(vector.getName()), vec); 

    } 
    writer.close(); 

} catch (Exception e) { 
    System.out.println("ERROR: "+e); 
} 

現在你有一個目錄SequenceFile格式的「點」,可用於K均值聚類。你可以將命令行Mahout命令指向這個目錄作爲輸入。

無論如何,這是一般的想法。也可能有其他方法。

0

我建議你實現一個程序,將CSV轉換爲Mahout接受的稀疏矢量序列文件。
您需要做的是瞭解InputDriver如何將包含空格分隔浮點數的文本文件轉換爲適用於輸入到特定羣集作業的VectorWritable Mahout序列文件以及任何需要此輸入的Mahout作業。您將根據您的需求定製代碼。
如果您已經下載了Mahout的源代碼,InputDriver位於org.apache.mahout.clustering.conversion包。

1

當我運行上述代碼時,出現了一些問題,因此在這裏對語法進行一些修改就是工作代碼。

String inputfiledata = Input_file_path; 
      String outputfile = output_path_for_sequence_file; 
      FileSystem fs = null; 
      SequenceFile.Writer writer; 
      Configuration conf = new Configuration(); 
      fs = FileSystem.get(conf); 
      Path path = new Path(outputfile);`enter code here` 
      writer = new SequenceFile.Writer(fs, conf, path, Text.class, VectorWritable.class); 
      VectorWritable vec = new VectorWritable(); 
      List<NamedVector> vects = new ArrayList<NamedVector>(); 
      try { 
       fr = new FileReader(inputfiledata); 
       br = new BufferedReader(fr); 
       s = null; 
       while((s=br.readLine())!=null){ 

        // My columns are split by tabs with each entry in a new line as rows 
        String spl[] = s.split("\\t"); 
        String key = spl[0]; 
        Integer val = 0; 
        for(int k=1;k<spl.length;k++){ 
           colvalues[val] = Double.parseDouble(spl[k]); 
           val++; 
         } 
        } 
        NamedVector nmv = new NamedVector(new DenseVector(colvalues),key); 
        vec.set(nmv); 
        writer.append(new Text(nmv.getName()), vec); 
       } 
          writer.close(); 

      } catch (Exception e) { 
       System.out.println("ERROR: "+e); 
      } 
     } 
3

要用csv文件運行kmeans,首先必須創建一個SequenceFile作爲KmeansDriver中的參數傳遞。下面的代碼讀取CSV文件「points.csv」的每一行,並將其轉換爲載體,並寫入SequenceFile「points.seq」

try (
      BufferedReader reader = new BufferedReader(new FileReader("testdata2/points.csv")); 
      SequenceFile.Writer writer = new SequenceFile.Writer(fs, conf,new Path("testdata2/points.seq"), LongWritable.class, VectorWritable.class) 
     ) { 
      String line; 
      long counter = 0; 
      while ((line = reader.readLine()) != null) { 
       String[] c = line.split(","); 
       if(c.length>1){ 
        double[] d = new double[c.length]; 
        for (int i = 0; i < c.length; i++) 
          d[i] = Double.parseDouble(c[i]); 
        Vector vec = new RandomAccessSparseVector(c.length); 
        vec.assign(d); 

       VectorWritable writable = new VectorWritable(); 
       writable.set(vec); 
       writer.append(new LongWritable(counter++), writable); 
      } 
     } 
     writer.close(); 
    } 

希望它可以幫助!

0

org.apache.mahout.clustering.conversion.InputDriver是一個可用於創建稀疏向量的類。下面

象夫org.apache.mahout.clustering.conversion.InputDriver -i TESTDATA -o輸出1 /數據-v org.apache.mahout.math.RandomAccessSparseVector

示例代碼給出如果您運行mahout org.apache.mahout.clustering.conversion.InputDriver 它將列出它所期望的參數。

希望這會有所幫助。
另外這裏是一篇文章,我寫了解釋我如何運行kmeans聚類在一個arff文件上
http://mahout-hadoop.blogspot.com/2013/10/using-mahout-to-cluster-iris-data.html