Jak dobrze R skaluje się do zadań klasyfikacji tekstu? [Zamknięte]

30

Próbuję przyspieszyć z R. W końcu chcę używać bibliotek R do klasyfikacji tekstu. Zastanawiałem się tylko, jakie są ludzkie doświadczenia w odniesieniu do skalowalności języka R, jeśli chodzi o klasyfikację tekstu.

Prawdopodobnie napotkam dane o dużych wymiarach (~ 300 tys. Wymiarów). Patrzę na wykorzystanie SVM i Random Forest w szczególności jako algorytmów klasyfikacji.

Czy biblioteki R byłyby skalowane do rozmiaru mojego problemu?

Dzięki.

EDYCJA 1: Żeby wyjaśnić, mój zestaw danych prawdopodobnie będzie miał 1000-3000 wierszy (być może nieco więcej) i 10 klas.

EDYCJA 2: Ponieważ jestem bardzo nowy w R, poproszę plakaty, aby były bardziej szczegółowe, tam gdzie to możliwe. Na przykład, jeśli sugerujesz przepływ pracy / potok, pamiętaj, aby w miarę możliwości wspomnieć biblioteki R zaangażowane w każdy krok. Niektóre dodatkowe wskaźniki (do przykładów, przykładowego kodu itp.) Byłyby wisienką na torcie.

EDYCJA 3: Po pierwsze, dziękuję wszystkim za komentarze. Po drugie przepraszam, być może powinienem był podać więcej informacji na temat problemu. Jestem nowy w R, ale nie tyle w klasyfikacji tekstu. Zrobiłem już wstępne przetwarzanie (usuwanie, usuwanie słów kluczowych, konwersję tf-idf itp.) Na niektórych częściach moich danych za pomocą pakietu tm , aby poszukać rzeczy. tm działał tak wolno nawet na około 200 dokumentach, że zaniepokoiłem się skalowalnością. Potem zacząłem grać w FSelector i nawet to było bardzo wolne. I w tym momencie dokonałem OP.

EDYCJA 4: Właśnie przyszło mi do głowy, że mam 10 klas i około 300 dokumentów szkoleniowych na klasę, i faktycznie buduję matrycę termXdoc z całego zestawu szkoleniowego, co skutkuje bardzo dużą wymiarowością. Ale co powiesz na sprowadzenie każdego problemu z klasyfikacją „jeden na dwa” do serii problemów z klasyfikacją binarną? To drastycznie zmniejszyłoby liczbę dokumentów szkoleniowych (a zatem i wymiarowość) na każdym etapie k-1, prawda? Czy to podejście jest dobre? Jak wypada pod względem dokładności w porównaniu do zwykłej implementacji wielu klas?

Andy
źródło
1
300 tys. Wymiarów przy ilu rzędach? Niestety, obiekty R muszą znajdować się w pamięci (przynajmniej chyba, że ​​rozważasz poważne poprawki, w zasadzie wymagające samodzielnego przepisania tych algorytmów). Oznacza to, że z, powiedzmy, 8 koncertami barana, nie sądzę, że można przechowywać więcej niż kilkaset rzędów z 300 tys. Kolumn.
crayola
@crayola: liczba rzędów może wynosić od 1000-3000.
Andy,
2
Obiekty R nie muszą znajdować się w pamięci. Mapowanie pamięci jest bardzo łatwe. Wymiary 300 tys. To nie problem. Zakładam również, że twoje dane są rzadkie, tak jak w przypadku prawie wszystkich problemów z tekstem.
Iterator
Właśnie zauważyłem powyższy komentarz: tylko 1000-3000 wierszy? To jest bardzo małe. Czy możesz wyjaśnić, jaki jest twój korpus? Partia e-maili? Opisy pakietów w CRAN? Możesz mieć więcej problemów statystycznych z P >> N niż z innymi problemami z pamięcią.
Iterator,
1
@Iterator: Mamy pewne zasoby edukacyjne (artykuły semestralne, eseje itp.), Które chcemy sklasyfikować.
Andy,

Odpowiedzi:

17

Zgodnie z prośbą w komentarzu, oto kilka wskazówek dotyczących kroków przetwarzania. Szereg narzędzi można znaleźć w widoku zadań CRAN dla przetwarzania języka naturalnego . Można również zajrzeć do tego artykułu na tm(górnictwo tekst) dla pakietu R .

  1. Przed przetworzeniem rozważ normalizację tokenów wyrazowych. openNLP(dla którego istnieje pakiet R) to jedna trasa.
  2. W przypadku przetwarzania tekstu powszechnym etapem wstępnego przetwarzania jest znormalizowanie danych za pomocą tf.idf- termin częstotliwość * odwrotna częstotliwość dokumentów - więcej informacji można znaleźć w Wikipedii . Istnieją inne nowsze normalizacje, ale jest to metoda oparta na chlebie i maśle, dlatego ważne jest, aby ją znać. Możesz go łatwo wdrożyć w R: po prostu zapisz (docID, wordID, freq1, freq2), gdzie freq1 to liczba wyświetleń słowa indeksowanego przez wordID w danym dokumencie, a freq2 to liczba dokumentów, w których się pojawia. Nie ma potrzeby przechowywania tego wektora dla słów, które nie pojawiają się w danym dokumencie. Następnie po prostu weź freq1 / freq2 i masz swoją wartość tf.idf.
  3. Po obliczeniu wartości tf.idf możesz pracować z pełną wymiarowością swoich danych lub odfiltrować te słowa, które są zasadniczo nieinformacyjne. Na przykład każde słowo, które pojawia się tylko w 1 dokumencie, nie da wiele wglądu. Może to znacznie zmniejszyć wymiar. Biorąc pod uwagę małą liczbę badanych dokumentów, może się okazać, że właściwe jest zmniejszenie do zaledwie 1K wymiarów.
  4. Nie chciałbym ponownie centrować danych (np. Dla PCA), ale możesz teraz przechowywać dane w macierzy terminów (gdzie wpisy są teraz wartościami tf.idf) z łatwością, używając rzadkich macierzy, obsługiwanych przez Matrixpakiet.

W tym momencie masz ładnie wstępnie przetworzony zestaw danych. Polecam kontynuowanie korzystania z narzędzi wymienionych w widoku zadań CRAN lub pakiecie eksploracji tekstu. Grupowanie danych, na przykład przez rzutowanie na pierwsze 4 lub 6 głównych komponentów, może być bardzo interesujące dla twojej grupy, gdy dane są drukowane.

Jeszcze jedno: może się okazać, że redukcja wymiarów wzdłuż linii PCA (*) może być pomocna przy stosowaniu różnych metod klasyfikacji, ponieważ zasadniczo agregujesz powiązane słowa. Pierwszych 10–50 głównych składników może być wszystkim, czego potrzebujesz do klasyfikacji dokumentów, biorąc pod uwagę wielkość próbki.

(*) Uwaga: PCA to tylko pierwszy krok. Może to być bardzo interesujące dla kogoś, kto dopiero zaczyna od eksploracji tekstu i PCA, ale w końcu może się okazać, że jest to trochę uciążliwe dla rzadkich zestawów danych. Najpierw jednak spójrz na to, szczególnie za pomocą funkcji prcompi princomp.

Aktualizacja: Nie podałem preferencji w tej odpowiedzi - prcompraczej polecam niż princomp.

Iterator
źródło
+1 ładna odpowiedź; Jestem tylko ciekawy, dlaczego mówicie, że niewielka liczba doków implikuje mniejszą liczbę ważnych zmiennych - czy nie wydaje się to trochę za nieodpowiednie?
Nie jestem pewien, czy rozumiem, co masz na myśli. Z pewnością utrzymywanie ich w nadmiarze jest niewystarczające, więc zmienne te zostałyby wyeliminowane w każdej rozsądnej regularyzacji. Co więcej, słownictwo (P) rośnie wraz z liczbą dokumentów lub próbek (N), więc za pierwszym razem, gdy pojawia się termin, niewiele to wskazuje. Kontynuuj dodawanie dokumentów, a następnie powtórzenie terminu w dokumentach stanie się pouczające.
Iterator,
@Iterator: Dziękujemy za odpowiedź. Więc prcompi / lub princompskaluje się do tego rodzaju danych, które według ciebie? Właśnie edytowałem moje pytanie i dodałem dodatkowe informacje.
Andy,
Nie, prawdopodobnie nie skalują się, gdy trafisz 300 000 kolumn. :) (Wystarczy zaznaczyć: X'X w tym przypadku będzie miał 90B wpisów - problem z pamięcią.) Zamiast tego najpierw przefiltruj według tf.idf. Jeśli istnieje tylko, powiedzmy, 10 różnych klas, to mała wielokrotność 10 powinna być odpowiednia dla większych wymiarów dla rozdzielenia klas. Tak więc 1000 wymiarów powinno wystarczyć. Obie metody PCA (btw, polecam prcomp) będą w porządku.
Iterator,
Kiedy ograniczysz się do 1000 wymiarów lub może kilku innych (np. 2K) i wykonasz PCA, możesz wziąć projekcje na powiedzmy 100 wymiarów (co może być przesadą, ale nie ma w tym zbytniej szkody), a następnie dokonać klasyfikacji. W tym momencie nie dzieje się nic ekscytującego.
Iterator,
5

Po pierwsze witamy! Przetwarzanie tekstu to świetna zabawa, a robienie tego w języku R jest coraz łatwiejsze.

Krótka odpowiedź: tak - narzędzia w R są teraz całkiem dobre do radzenia sobie z tego rodzaju danymi. W rzeczywistości nie ma nic specjalnego w R, C ++, Groovy, Scala ani żadnym innym języku, jeśli chodzi o przechowywanie danych w pamięci RAM: każdy język przechowuje 8-bajtowy podwójny pływak ... poczekaj na to ... poczekaj na to. .. 8 bajtów!

Algorytmy i ich implementacja mają znaczenie, zwłaszcza jeśli są bardzo słabo implementowane w odniesieniu do struktur danych i złożoności obliczeniowej. Jeśli wdrażasz własne algorytmy, po prostu zachowaj ostrożność. Jeśli używasz innego kodu, obowiązuje emptor z zastrzeżeniami, tak jak ma to miejsce w każdym środowisku.

W przypadku R należy rozważyć:

  1. Twoja reprezentacja danych (spójrz na rzadkie macierze, szczególnie w Matrixpakiecie)
  2. Przechowywanie danych (być może pamięć zmapowana, przy użyciu bigmemorylub ff; lub rozproszona, przy użyciu Hadoop)
  3. Twoje partycjonowanie danych (ile możesz zmieścić w pamięci RAM, zależy od ilości pamięci RAM)

Ostatni punkt jest naprawdę pod twoją kontrolą.

Jeśli chodzi o tę wymiarowość, nie jest już szczególnie duża. Liczba obserwacji będzie miała większy wpływ, ale możesz podzielić dane na partycje, aby dostosować je do użycia pamięci RAM, więc naprawdę nie musisz się zbytnio martwić.

Iterator
źródło
3

Zgadzam się z kredką, że liczba rzędów jest tutaj kluczowa. Do RF potrzebujesz co najmniej 3 razy więcej pamięci RAM niż wagi zestawu danych i prawdopodobnie dużo czasu (taka liczba atrybutów zwykle wymaga dużej liczby drzew w lesie - i pamiętaj, że nie ma równoległej implementacji RF w R).

Jeśli chodzi o SVM, wątpię, aby dobrze było walczyć z wymiarami 300k, podczas gdy prawdopodobnie możesz opracować funkcję jądra, która będzie równoważna z deskryptorami tekstu.

EDYCJA: Matryca 3k x 30k (prawdziwa) zajmowałaby około 7 Gb, więc wszystko, co musisz zrobić RF (używając randomForest) na tych danych, to komputer z 16 GB pamięci RAM, trochę szczęścia i sporo czasu lub po prostu komputer z 24 GB RAM i sporo czasu.


źródło
Cóż, z pewnością zamierzałem dokonać wyboru funkcji (chi kwadrat, oparty na entropii), ale znowu nie mogłem znaleźć żadnej biblioteki R, która skalowałaby się do tego zadania. Biorąc to wszystko pod uwagę, czy słuszne jest zatem stwierdzenie, że być może powinienem zacząć szukać rozwiązań innych niż R?
Andy,
1
„zauważ, że nie ma równoległej implementacji RF w R”. Jest to tylko częściowo poprawne, ponieważ foreachpakiet ładnie współpracuje z randomForestpakietem. Myślę, że jest jeden taki przykład winiety dla foreach. (A może doMC.)
kredka
@Andy Chodzi o to, że oprócz przepisywania algorytmów w języku programowania niskiego poziomu, nie jestem pewien, jakie oprogramowanie będzie w stanie zastosować te algorytmy do twoich danych. Gdybym był w twojej sytuacji, myślę, że trzymałbym się R i przepisałam części randomForesttak, aby sprawdzał losowo wybrane kolumny z, na przykład, bazy danych SQL przy każdej iteracji (tak, aby całe 300k wymiarów nigdy nie miało być w baranie). Ale to prawdopodobnie głównie dlatego, że wiem więcej o R niż o innych możliwych opcjach.
kredka
Co dokładnie masz na myśli, twierdząc, że nie możesz znaleźć biblioteki, która by to skalowała? Takie filtry to podstawowa algebra, które powinny działać bez problemów (pod warunkiem, że masz wystarczającą ilość pamięci RAM).
@crayola To prawda, ale łącząca się część jest okropna. Co więcej, nie jest to paralelizm współdzielonej pamięci, więc prawdopodobnie byłoby to bolesne (jeśli nie niemożliwe) w tym otoczeniu.