mahout:csv到vector并运行程序

jfewjypa  于 2021-06-03  发布在  Hadoop
关注(0)|答案(5)|浏览(353)

我在用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。我试图实现这个类似问题的答案:如何在mahout中使用存储为csv的向量数据执行k-means聚类?但我还有两个问题:
如何从csv转换为seqfile?我想我可以使用mahout编写自己的程序来进行转换,然后将其输出用作seq2parse的输入。我想我可以用电脑(https://cwiki.apache.org/confluence/display/mahout/file+format+integrations). 我应该用什么课来读和写?
如何构建和运行我的新程序?我不明白这本书的作者在行动或其他问题在这里。

kmpatx3s

kmpatx3s1#

为了以sequencefile格式获取数据,您可以采取一些策略。两者都涉及编写自己的代码——也就是说,不是严格意义上的命令行。
策略1使用mahout的csvvectoriterator类。你给它一个java.io.reader,它会读入你的csv文件,把每一行变成一个densevector。我从未使用过这个,但在api中看到过。如果你对densevectors还满意的话,就直接向前看吧。
策略2编写自己的解析器。这真的很容易,因为你只需要在“,”上分割每一行,你就有一个数组可以循环通过。对于每行中的每个值数组,您可以使用如下方式示例化一个向量:

new DenseVector(<your array here>);

并将其添加到列表中(例如)。
然后。。。一旦你有了一个向量列表,你就可以用这样的方法将它们写到SequenceFile中(我在下面的代码中使用namedVector):

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格式的“points”目录,可以用于k-means聚类。您可以将此目录下的命令行mahout命令作为输入。
总之,这是总的想法。可能还有其他方法。

jhiyze9q

jhiyze9q2#

当我运行上面的代码时,出现了一些问题,因此在语法上做了一些修改,这里就是工作代码。

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

6yt4nkrj3#

要用csv文件运行kmeans,首先必须创建一个sequencefile作为kmeansdriver中的参数传递。下面的代码读取csv文件“points.csv”的每一行,并将其转换为向量,然后将其写入序列文件“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();
    }

希望有帮助!!

wljmcqd8

wljmcqd84#

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

egdjgwm8

egdjgwm85#

我建议您实现一个程序,将csv转换为mahout接受的稀疏向量序列文件。
您需要做的是了解inputdriver如何将包含空格分隔的浮点数的文本文件转换为适合集群作业输入的向量可写的mahout序列文件,以及通常需要此输入的任何mahout作业。您将根据需要自定义代码。
如果您下载了mahout的源代码,那么inputdriver位于org.apache.mahout.clustering.conversion包中。

相关问题