如何在Mahout K-means聚类中维护数据条目id



我正在使用mahout运行k-means聚类,并且我在聚类时遇到了识别数据条目的问题,例如我有100个数据条目

id      data
0       0.1 0.2 0.3 0.4
1       0.2 0.3 0.4 0.5
...     ...
100     0.2 0.4 0.4 0.5

聚类后,我需要从聚类结果中获得id,以查看哪个点属于哪个集群,但似乎没有方法来维护id。

在聚类合成控制数据的官方mahout示例中,只向mahout输入没有id的数据,如

28.7812 34.4632 31.3381 31.2834 28.9207 ...
...
24.8923 25.741  27.5532 32.8217 27.8789 ...

和集群结果只有集群id和点值:

VL-539{n=38 c=[29.950, 30.459, ...
   Weight:  Point:
   1.0: [28.974, 29.026, 31.404, 27.894, 35.985...
   2.0: [24.214, 33.150, 31.521, 31.986, 29.064

但是没有point-id存在,所以,有没有人知道如何在做mahout集群时添加维护一个point-id ?非常感谢!

我使用NamedVectors。

如你所知,在对数据进行任何聚类之前,你必须对它进行矢量化。

这意味着您必须将数据转换为Mahout向量,因为这是聚类算法处理的数据类型。

向量化过程将取决于你的数据的性质,即向量化文本是不一样的向量化数值

你的数据似乎很容易矢量化,因为它只有一个ID和4个数值。

你可以写一个Hadoop Job来获取你的输入数据,例如,作为一个CSV文件,并输出一个已向量化数据的SequenceFile。

然后,将Mahout聚类算法应用于该输入,并将在聚类结果中保留每个向量的ID(向量名称)。

将数据向量化的示例作业可以使用以下类实现:

public class DenseVectorizationDriver extends Configured implements Tool{
    @Override
    public int run(String[] args) throws Exception {
        if (args.length != 2) {
            System.err.printf("Usage: %s [generic options] <input> <output>n", getClass().getSimpleName());
            ToolRunner.printGenericCommandUsage(System.err); return -1;
        }
        Job job = new Job(getConf(), "Create Dense Vectors from CSV input");
        job.setJarByClass(DenseVectorizationDriver.class);
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        job.setMapperClass(DenseVectorizationMapper.class);
        job.setReducerClass(DenseVectorizationReducer.class);
        job.setOutputKeyClass(LongWritable.class);
        job.setOutputValueClass(VectorWritable.class);
        job.setOutputFormatClass(SequenceFileOutputFormat.class);
        return job.waitForCompletion(true) ? 0 : 1;
    }
}

public class DenseVectorizationMapper extends Mapper<LongWritable, Text, LongWritable, VectorWritable>{
/*
 * This mapper class takes the input from a CSV file whose fields are separated by TAB and emits
 * the same key it receives (useless in this case) and a NamedVector as value.
 * The "name" of the NamedVector is the ID of each row.
 */
    @Override
    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String line = value.toString();
        System.out.println("LINE: "+line);
        String[] lineParts = line.split("t", -1);    
        String id = lineParts[0];
        //you should do some checks here to assure that this piece of data is correct
        Vector vector = new DenseVector(lineParts.length -1);
        for (int i = 1; i < lineParts.length -1; i++){
            String strValue = lineParts[i];
            System.out.println("VALUE: "+strValue);
            vector.set(i, Double.parseDouble(strValue));
        }
        vector =  new NamedVector(vector, id);
        context.write(key, new VectorWritable(vector));
    }
}

public class DenseVectorizationReducer extends Reducer<LongWritable, VectorWritable, LongWritable, VectorWritable>{
/*
 * This reducer simply writes the output without doing any computation.
 * Maybe it would be better to define this hadoop job without reduce phase.
 */
    @Override
    public void reduce(LongWritable key, Iterable<VectorWritable> values, Context context) throws IOException, InterruptedException{
        VectorWritable writeValue = values.iterator().next();
        context.write(key, writeValue);
    }
}

您的请求经常被自己不是从业者的程序员忽视…不幸的是。到目前为止,我还不知道如何做到这一点,但我从Apache-commons-math开始,它包含一个具有相同缺陷的K-means。我对它进行了修改,以满足你的要求。你可以在这里找到它:http://code.google.com/p/noolabsimplecluster/此外,不要忘记将数据(线性地)归一化到区间[0..]1],否则任何聚类算法都会产生垃圾!

由kmeans生成的clusteredPoints目录包含此映射。请注意,您应该使用-cl选项来获取这些数据。

相关内容

  • 没有找到相关文章

最新更新