2012-12-01 14 views
5

Analizuję algorytm k-średnich za pomocą Mahouta. Mam zamiar przeprowadzić kilka testów, obserwować wydajność i robić statystyki z uzyskanymi wynikami.Mahout: CSV do wektora i działający program

Nie mogę znaleźć sposobu na uruchomienie własnego programu w ramach Mahout. Jednak interfejs linii poleceń może wystarczyć.

Aby uruchomić program przykładowy zrobić

$ 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 

Zbiór danych jest jeden duży plik CSV. Każda linia jest rekordem. Funkcje są oddzielone przecinkami. Pierwsze pole to identyfikator. Z powodu formatu wejściowego nie mogę od razu używać seqdirectory. Próbuję zaimplementować odpowiedź na to pytanie How to perform k-means clustering in mahout with vector data stored as CSV? podobny ale nadal mam 2 pytania:

  1. Jak przekonwertować z CSV do SeqFile? Domyślam się, że mogę napisać własny program używając Mahouta, aby dokonać tej konwersji, a następnie użyć jej wyjścia jako wejścia dla seq2parse. Chyba mogę użyć CSVIterator (https://cwiki.apache.org/confluence/display/MAHOUT/File+Format+Integrations). Jakiej klasy należy używać do czytania i pisania?
  2. Jak zbudować i uruchomić nowy program? Nie mogłem tego rozgryźć z książką Mahout w akcji lub z innymi pytaniami tutaj.

Odpowiedz

5

Aby uzyskać dane w formacie SequenceFile, masz kilka strategii, które możesz zastosować. Oba obejmują pisanie własnego kodu - tj. Nie ściśle linii poleceń.

Strategia 1 Użyj klasy CSVVectorIterator Mahouta. Przekazujesz mu plik java.io.Reader i będzie on czytał w pliku CSV, zmieniając każdy z wierszy w DenseVector. Nigdy tego nie używałem, ale widziałem to w API. Wygląda na to wprost do przodu, jeśli używasz DenseVectors.

Strategia 2 Napisz własny parser. To naprawdę proste, ponieważ po prostu dzielisz każdą linię na "," i masz tablicę, przez którą możesz przechodzić. Dla każdej tablicy wartości w każdej linii, wektor instancję za pomocą czegoś takiego:

new DenseVector(<your array here>); 

i dodać go do listy (na przykład).

... Potem raz masz listę wektorów, można zapisać je do SequenceFiles korzystających coś takiego (używam NamedVectors w poniższym kodzie):

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); 
} 

Teraz masz katalogu "points" w formacie SequenceFile, który można wykorzystać do grupowania K-średnich. Możesz wskazać komendy Mahout w wierszu poleceń w tym katalogu jako dane wejściowe.

W każdym razie taki jest ogólny pomysł. Prawdopodobnie istnieją również inne podejścia.

0

Proponuję, abyś zaimplementował program do konwersji pliku CSV na rzadki plik sekwencji wektorowych, który mahout akceptuje.
Musisz zrozumieć, w jaki sposób InputDriver konwertuje pliki tekstowe zawierające liczby zmiennoprzecinkowe rozdzielone spacjami na pliki sekwencji Mahout w VectorWritable, odpowiednie do wprowadzania do zadań tworzenia klastrów, a także wszelkie prace Mahout wymagające tego wejścia w ogóle. Dostosujesz kody do swoich potrzeb.
Po pobraniu kodu źródłowego Mahout, InputDriver znajduje się w pakiecie org.apache.mahout.clustering.conversion.

1

Podczas pracy z powyższym kodem było kilka problemów, więc po kilku modyfikacjach w składni jest tutaj działający kod.

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

Aby uruchomić kmeans z pliku csv, najpierw trzeba stworzyć SequenceFile aby przekazać jako argument w KmeansDriver. Poniższy kod odczytuje każdy wiersz pliku CSV „points.csv” i konwertuje go do wektora i zapisać go do 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(); 
    } 

nadzieję, że pomoże !!

0

org.apache.mahout.clustering.conversion.InputDriver to klasa, której można używać do tworzenia wektorów rzadkich.

Przykładowy kod znajduje się poniżej

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

Jeśli uruchom mahout org.apache.mahout.clustering.conversion.InputDriver wyświetli listę parametrów, których oczekuje.

Mam nadzieję, że to pomoże.
Oto także artykuł, który napisałem, aby wyjaśnić, w jaki sposób udało mi się uruchomić klastrowanie na plik arff
http://mahout-hadoop.blogspot.com/2013/10/using-mahout-to-cluster-iris-data.html

Powiązane problemy