2011-12-20 12 views
5

Sto usando mahout per eseguire il clustering k-means e ho riscontrato un problema di identificazione della voce di dati durante il clustering, ad esempio ho 100 voci di datiCome mantenere l'ID di immissione dati in Mahout K-significa clustering

dopo il clustering, ho bisogno di recuperare l'id dal risultato del cluster per vedere quale punto appartiene a quale cluster, ma non sembra esserci alcun metodo per mantenere l'id.

Nell'esempio ufficiale mahout di clustering di dati di controllo sintetici, solo i dati sono stati immessi a mahout senza id come

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

e il risultato del cluster solo hanno cluster id e valore del punto:

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 

ma nessun point-id esiste, quindi, qualcuno può avere un'idea su come aggiungere mantenere un point-id quando si fa il clustering di mahout? Grazie mille!

risposta

0

La richiesta viene spesso trascurata dai programmatori che non sono loro stessi professionisti ... sfortunatamente. Non so come farlo Mahout (finora), ma ho iniziato con Apache-commons-math, che include un K-means con lo stesso difetto. L'ho adattato in modo tale che la tua richiesta sia soddisfatta. Lo trovi qui: http://code.google.com/p/noolabsimplecluster/ Inoltre, non dimenticare di normalizzare (linearmente) i dati all'intervallo [0..1], altrimenti qualsiasi clustering algo produrrà spazzatura!

0

La directory clusterPoints prodotta dai kmea contiene questa mappatura. Si prega di notare che avresti dovuto usare l'opzione -cl per ottenere questi dati.

2

Per raggiungere tale obiettivo, utilizzo NamedVectors.

Come sapete, prima di effettuare qualsiasi clusterizzazione con i vostri dati, dovete vettorializzare.

Ciò significa che è necessario trasformare i dati in vettori Mahout, poiché questo è il tipo di dati con cui gli algoritmi di clusterizzazione funzionano.

Il processo di vettorizzazione dipenderà dalla natura dei dati, ovvero il testo di vettorizzazione non è lo stesso per vectorize valori numerici.

I dati sembrano essere facilmente vettorizzabili, poiché hanno solo un ID e 4 valori numerici.

È possibile scrivere un lavoro Hadoop che prende i dati di input, ad esempio, come file CSV, e genera un SequenceFile con i dati già vettorizzati.

Quindi, si applicano gli algoritmi di clustering di Mahout a questo input e si manterrà l'ID (nome vettoriale) di ciascun vettore nei risultati del clustering.

Un lavoro esempio per vettorizzare i vostri dati potrebbero essere attuate con le seguenti classi:

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

non sono andato attraverso tutto il codice, ma la prima linea è stato sufficiente. "NamedVector"! –