Как сохранить идентификатор ввода данных в кластере Mahout K-means - PullRequest
5 голосов
/ 20 декабря 2011

Я использую mahout для запуска кластеризации k-средних, и у меня возникла проблема с идентификацией ввода данных при кластеризации, например, у меня есть 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

после кластеризации, мне нужночтобы вернуть идентификатор из результата кластера, чтобы увидеть, какая точка принадлежит какому кластеру, но, похоже, нет способа сохранить идентификатор.

В официальном примере mahout кластеризации синтетических контрольных данных только данные были введены вmahout без идентификатора, подобного

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

, и результат кластера имеет только идентификатор кластера и значение точки:

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

, но идентификатор точки не существует, так что любой может иметь представление о том, какдобавить поддерживать идентификатор точки при выполнении кластеризации mahout?большое спасибо!

Ответы [ 3 ]

2 голосов
/ 12 февраля 2013

Для этого я использую NamedVectors.

Как вы знаете, прежде чем выполнять какую-либо кластеризацию с вашими данными, вы должны векторизовать их.

Это означает, что вы должны преобразовать свои данные в векторы Махоута, потому что это данные, с которыми работают алгоритмы кластеризации.

Процесс векторизации будет зависеть от характера ваших данных, то есть векторизация текста не совпадает с векторизовать числовые значения.

Ваши данные кажутся легко векторизованными, поскольку они имеют только ID и 4 числовых значения.

Вы можете написать задание Hadoop, которое принимает ваши входные данные, например, в виде файла CSV, и выводит SequenceFile с уже векторизованными данными.

Затем вы применяете алгоритмы кластеризации Mahout к этому входу и сохраняете идентификатор (имя вектора) каждого вектора в результатах кластеризации.

Пример работы по векторизации ваших данных может быть реализован со следующими классами:

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);
    }
}
0 голосов
/ 02 апреля 2012

Каталог clusterteredPoints, который создается kmeans, содержит это отображение. Обратите внимание, что вы должны использовать опцию -cl для получения этих данных.

0 голосов
/ 26 февраля 2012

Ваш запрос часто игнорируется программистами, которые сами не практикующие ... к сожалению. Я не знаю, как это сделать, Mahout (пока), но я начал с Apache-commons-math, который включает в себя K-means с тем же дефектом. Я адаптировал его так, чтобы ваш запрос был удовлетворен. Вы найдете это здесь: http://code.google.com/p/noolabsimplecluster/ Кроме того, не забудьте нормализовать (линейно) данные в интервале [0..1], иначе любой алгоритм кластеризации будет создавать мусор!

...