【问题标题】:Mahout: CSV to vector and running the programMahout:CSV 到矢量并运行程序
【发布时间】:2012-11-19 18:10:00
【问题描述】:

我正在使用 Mahout 分析 k-means 算法。我将运行一些测试,观察性能,并对得到的结果进行一些统计。

我不知道如何在 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 这本书或这里的其他问题来解决这个问题。

【问题讨论】:

    标签: java apache hadoop mahout


    【解决方案1】:

    org.apache.mahout.clustering.conversion.InputDriver 是一个可用于创建稀疏向量的类。

    示例代码如下

    mahout org.apache.mahout.clustering.conversion.InputDriver -i testdata -o output1/data -v org.apache.mahout.math.RandomAccessSparseVector

    如果你运行 mahout org.apache.mahout.clustering.conversion.InputDriver 它会列出它所期望的参数。

    希望这会有所帮助。
    还有一篇我写的文章解释了我如何在 arff 文件上运行 kmeans 聚类
    http://mahout-hadoop.blogspot.com/2013/10/using-mahout-to-cluster-iris-data.html

    【讨论】:

      【解决方案2】:

      要使用 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();
          }
      

      希望对你有帮助!!

      【讨论】:

        【解决方案3】:

        我在运行上述代码时出现了一些问题,因此对语法进行了一些修改,这里是工作代码。

        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);
                    }
                }
        

        【讨论】:

          【解决方案4】:

          要以 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-means 聚类。您可以将命令行 Mahout 命令指向此目录作为输入。

          无论如何,这就是一般的想法。可能还有其他方法。

          【讨论】:

            【解决方案5】:

            我建议您实现一个程序,将 CSV 转换为 mahout 接受的稀疏矢量序列文件。
            您需要做的是了解 InputDriver 如何将包含以空格分隔的浮点数的文本文件转换为 VectorWritable 的 Mahout 序列文件,特别适用于集群作业的输入,以及通常需要此输入的任何 Mahout 作业。您将根据需要自定义代码。
            如果您已经下载了 Mahout 的源代码,则 InputDriver 位于包 org.apache.mahout.clustering.conversion。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-09-25
              • 2015-04-08
              • 2023-04-11
              • 1970-01-01
              • 1970-01-01
              • 2017-06-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多