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);
}
}
no ir a través de todo el código, pero su primera línea era suficiente. "NamedVector"! –