2012-12-01 11 views
5

Sto analizzando l'algoritmo k-means con Mahout. Ho intenzione di eseguire alcuni test, osservare le prestazioni e fare alcune statistiche con i risultati che ottengo.Mahout: CSV per il vettore e l'esecuzione del programma

Non riesco a capire il modo di eseguire il mio programma all'interno di Mahout. Tuttavia, l'interfaccia della riga di comando potrebbe essere sufficiente.

Per eseguire il programma di esempio che faccio

$ mahout seqdirectory --input uscensus --output uscensus-seq 
$ mahout seq2sparse -i uscensus-seq -o uscensus-vec 
$ mahout kmeans -i reuters-vec/tfidf-vectors -o uscensus-kmeans-clusters -c uscensus-kmeans-centroids -dm org.apache.mahout.common.distance.CosineDistanceMeasure -x 5 -ow -cl -k 25 

Il set di dati è un unico grande file CSV. Ogni riga è un record. Le funzionalità sono separate da virgola. Il primo campo è un ID. A causa del formato di input non posso usare subito seqdirectory. Sto cercando di implementare la risposta a questa domanda simile How to perform k-means clustering in mahout with vector data stored as CSV? ma ho ancora 2 Domande:

  1. Come si converte da CSV a SeqFile? Credo di poter scrivere il mio programma usando Mahout per fare questa conversione e quindi usare l'output come input per seq2parse. Credo di poter usare CSVIterator (https://cwiki.apache.org/confluence/display/MAHOUT/File+Format+Integrations). Quale classe dovrei usare per leggere e scrivere?
  2. Come posso creare ed eseguire il mio nuovo programma? Non riuscivo a capirlo con il libro Mahout in azione o con altre domande qui.

risposta

5

Per ottenere i dati in formato SequenceFile, è possibile adottare un paio di strategie. Entrambi implicano la scrittura del proprio codice, ad esempio non strettamente sulla riga di comando.

Strategia 1 Utilizzare la classe CSVVectorIterator di Mahout. Passa un java.io.Reader e leggerà nel tuo file CSV, trasforma ogni riga in un DenseVector. Non l'ho mai usato, ma l'ho visto nell'API. Sembra abbastanza semplice se stai bene con DenseVectors.

Strategia 2 Scrivi il tuo parser. Questo è veramente facile, dal momento che hai diviso ogni riga su "," e hai un array che puoi scorrere. Per ogni matrice di valori in ogni riga, si crea un'istanza di un vettore utilizzando qualcosa di simile:

new DenseVector(<your array here>); 

e lo si aggiunge a un elenco (per esempio).

Poi ... una volta che hai un elenco di vettori, è possibile scriverli SequenceFiles utilizzando qualcosa di simile (sto usando NamedVectors nel codice qui sotto):

FileSystem fs = null; 
SequenceFile.Writer writer; 
Configuration conf = new Configuration(); 

List<NamedVector> vectors = <here's your List of vectors obtained from CSVVectorIterator>; 

// Write the data to SequenceFile 
try { 
    fs = FileSystem.get(conf); 

    Path path = new Path(<your path> + <your filename>); 
    writer = new SequenceFile.Writer(fs, conf, path, Text.class, VectorWritable.class); 

    VectorWritable vec = new VectorWritable(); 
    for (NamedVector vector : dataVector) { 

     vec.set(vector); 
     writer.append(new Text(vector.getName()), vec); 

    } 
    writer.close(); 

} catch (Exception e) { 
    System.out.println("ERROR: "+e); 
} 

Ora avete un elenco di "punti" nel formato SequenceFile che puoi usare per il tuo cluster K-means. È possibile puntare i comandi Mahout della riga di comando in questa directory come input.

In ogni caso, questa è l'idea generale. Probabilmente ci sono anche altri approcci.

0

Suggerirei di implementare un programma per convertire il file CSV in file di sequenza vettoriale sparse che accetta mahout.
quello che devi fare è capire come InputDriver converte i file di testo contenenti numeri in virgola mobile delimitati da spazi in file di sequenza Mahout di VectorWritable adatti per l'input ai lavori di clustering in particolare e qualsiasi lavoro di Mahout che richiede questo input in generale. Personalizzerai i codici in base alle tue esigenze.
Se hai scaricato il codice sorgente di Mahout, InputDriver si trova nel pacchetto org.apache.mahout.clustering.conversion.

1

Ci sono stati alcuni problemi durante l'esecuzione del codice precedente, quindi con alcune modifiche nella sintassi, ecco il codice funzionante.

String inputfiledata = Input_file_path; 
      String outputfile = output_path_for_sequence_file; 
      FileSystem fs = null; 
      SequenceFile.Writer writer; 
      Configuration conf = new Configuration(); 
      fs = FileSystem.get(conf); 
      Path path = new Path(outputfile);`enter code here` 
      writer = new SequenceFile.Writer(fs, conf, path, Text.class, VectorWritable.class); 
      VectorWritable vec = new VectorWritable(); 
      List<NamedVector> vects = new ArrayList<NamedVector>(); 
      try { 
       fr = new FileReader(inputfiledata); 
       br = new BufferedReader(fr); 
       s = null; 
       while((s=br.readLine())!=null){ 

        // My columns are split by tabs with each entry in a new line as rows 
        String spl[] = s.split("\\t"); 
        String key = spl[0]; 
        Integer val = 0; 
        for(int k=1;k<spl.length;k++){ 
           colvalues[val] = Double.parseDouble(spl[k]); 
           val++; 
         } 
        } 
        NamedVector nmv = new NamedVector(new DenseVector(colvalues),key); 
        vec.set(nmv); 
        writer.append(new Text(nmv.getName()), vec); 
       } 
          writer.close(); 

      } catch (Exception e) { 
       System.out.println("ERROR: "+e); 
      } 
     } 
3

Per eseguire Kmeans con file CSV, in primo luogo è necessario creare un SequenceFile di passare come argomento in KmeansDriver. Il codice seguente legge ogni riga del file CSV "points.csv" e lo converte in vettoriale e scrivere al SequenceFile "points.seq"

try (
      BufferedReader reader = new BufferedReader(new FileReader("testdata2/points.csv")); 
      SequenceFile.Writer writer = new SequenceFile.Writer(fs, conf,new Path("testdata2/points.seq"), LongWritable.class, VectorWritable.class) 
     ) { 
      String line; 
      long counter = 0; 
      while ((line = reader.readLine()) != null) { 
       String[] c = line.split(","); 
       if(c.length>1){ 
        double[] d = new double[c.length]; 
        for (int i = 0; i < c.length; i++) 
          d[i] = Double.parseDouble(c[i]); 
        Vector vec = new RandomAccessSparseVector(c.length); 
        vec.assign(d); 

       VectorWritable writable = new VectorWritable(); 
       writable.set(vec); 
       writer.append(new LongWritable(counter++), writable); 
      } 
     } 
     writer.close(); 
    } 

Speranza che aiuta !!

0

org.apache.mahout.clustering.conversion.InputDriver è una classe che è possibile utilizzare per creare vettori sparse.

codice di esempio si riporta

mahout org.apache.mahout.clustering.conversion.InputDriver -i testdata -o output1/dati -v org.apache.mahout.math.RandomAccessSparseVector

Se eseguire mahout org.apache.mahout.clustering.conversion.InputDriver elencherà i parametri previsti.

Spero che questo aiuti.
qui è anche un articolo che ho scritto per spiegare come mi sono imbattuto Kmeans il clustering su un file ARFF
http://mahout-hadoop.blogspot.com/2013/10/using-mahout-to-cluster-iris-data.html

Problemi correlati