2011-12-20 12 views
5

Estoy usando mahout para ejecutar k-means clustering, y tuve un problema al identificar la entrada de datos cuando se clustering, por ejemplo Tengo 100 entradas de datosCómo mantener la identificación de entrada de datos en Mahout K-means clustering

Después de la agrupación en clúster, necesito recuperar la identificación del resultado del clúster para ver qué punto pertenece a cada clúster, pero no parece haber ningún método para mantener la identificación.

En el ejemplo oficial mahout de la agrupación de datos de control sintéticos, sólo los datos fueron introducidos a MAHOUT sin ID como

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

y el resultado de clúster sólo tener cluster-ID y valor de puntos:

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 

pero no existe ID de punto, entonces, ¿alguien puede tener idea de cómo agregar mantener una ID de punto cuando se hace una agrupación de mahout? ¡muchas gracias!

Respuesta

0

Su solicitud a menudo se pasa por alto por los programadores que no son ellos mismos practicantes ... desafortunadamente. No sé cómo hacerlo Mahout (hasta ahora), pero comencé con Apache-commons-math, que incluye un K-means con el mismo defecto. Lo adapté de tal manera que su solicitud está satisfecha. Lo encontrará aquí: http://code.google.com/p/noolabsimplecluster/ Además, no olvide normalizar (linealmente) los datos en el intervalo [0..1], de lo contrario, cualquier algoritmo de agrupamiento generará basura.

0

El directorio clusteredPoints producido por kmeans contiene esta asignación. Tenga en cuenta que debería haber usado la opción -cl para obtener esta información.

2

Para lograr eso, uso NamedVectors.

Como sabes, antes de hacer una agrupación con tus datos, debes vectorizarla.

Esto significa que debe transformar sus datos en vectores Mahout, porque ese es el tipo de datos con los que trabajan los algoritmos de clusterización.

El proceso de vectorización dependerá de la naturaleza de sus datos, es decir, vectorizar texto no es lo mismo que vectorizar valores numéricos.

Sus datos parecen ser fácilmente vectorizables, ya que solo tienen una ID y 4 valores numéricos.

Puede escribir un trabajo de Hadoop que tome sus datos de entrada, por ejemplo, como un archivo CSV, y muestre un archivo de secuencia con sus datos ya vectorizados.

Luego, aplica los algoritmos de agrupamiento de Mahout a esta entrada y mantendrá el ID (nombre del vector) de cada vector en los resultados de la agrupación.

Un trabajo de ejemplo para vectorizar sus datos podrían implementarse con las siguientes clases:

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

no ir a través de todo el código, pero su primera línea era suficiente. "NamedVector"! –

Cuestiones relacionadas