Frage

Ich habe über 300k Dokumente bekommt in einer Postgres-Datenbank gespeichert, die mit Themenkategorie markiert sind (es gibt etwa 150 Kategorien insgesamt). Ich habe eine andere 150k Dokumente, die noch keine Kategorien haben. Ich versuche, den besten Weg zu finden, um programmaticly sie kategorisieren.

Ich habe zu erforschen NLTK und seinen Bayes-Klassifikator. Es scheint wie ein guten Ausgangspunkt (wenn Sie einen besseren Klassifikationsalgorithmus für diese Aufgabe vorschlagen können, ich bin ganz Ohr).

Mein Problem ist, dass ich nicht genug RAM, um die NaiveBayesClassifier auf alle 150 categoies / 300k Dokumente auf einmal zu trainieren (Training auf 5 Kategorien verwendete 8 GB). Des Weiteren kann die Genauigkeit der Klassifikator scheint, als ich auf mehr Kategorien (90% Genauigkeit mit 2 Kategorien, 81% mit 5, 61% mit 10) trainieren zu fallen.

Soll ich trainieren nur einen Klassifikator auf 5 Kategorien zu einer Zeit, und führen Sie alle 150k Dokumente durch den Klassifizierer zu sehen, ob es Übereinstimmungen sind? Es scheint, wie dies funktionieren würde, mit der Ausnahme, dass es eine Menge Fehlalarme sein würde, wo Dokumente, die nur Schuh-gehörnte eine der Kategorien nicht wirklich passen in auf dem Klassifikator bekommen, weil es das beste Spiel verfügbar ... ist Gibt es ein Weg für den Klassifikator, falls nur eine „keine der oben genannte“ Option, um das Dokument nicht in eine der Kategorien paßt?

Hier ist meine Testklasse http://gist.github.com/451880

War es hilfreich?

Lösung

Sie sollten beginnen, indem Sie Ihre Dokumente Umwandlung in TF-log (1 + IDF) Vektoren : Begriff Frequenzen sind spärlich, so dass Sie python dict mit dem Begriff als Schlüssel verwendet werden sollen und als Werte zählen und dann durch die Gesamtzahl teilen die globalen Frequenzen zu erhalten.

Eine weitere Lösung ist es, die abs (hash (term)) beispielsweise als positive ganze Zahl Schlüssel zu verwenden. Dann wird eine Sie verwenden scipy.sparse Vektoren, die handlicher sind und effizienter linearen Algebra Betrieb als Python dict auszuführen.

baut auch die 150 Frequenzen Vektoren, die durch die Frequenzen aller markierten Dokumente im Durchschnitt zu der gleichen Kategorie gehören. Dann gilt für neues Dokument Etikett, können Sie die Kosinusähnlichkeit zwischen dem Dokumentenvektor und jeder Kategorie Vektor berechnen und wählen Sie die ähnlichste Kategorie als Label für das Dokument aus.

Wenn das nicht gut genug ist, dann sollten Sie versuchen, ein logistisches Regressionsmodell mit einer L1 Strafe zu trainieren, wie in dieses Beispiel von scikit-Learn (dies als ein Wrapper für liblinear durch @ephes erklärt). Die Vektoren verwendet, um Ihre logistischen Regressionsmodell zu trainieren, sollte die zuvor eingeführten TD-log (1 + IDF) Vektoren eine gute Leistung (Precision und Recall) zu bekommen sein. Die scikit lernen lib bietet ein sklearn.metrics mit Routinen Modul jene Punktzahl für ein bestimmtes Modell und gegebenen Datensatz zu berechnen.

Für größere Datensätze: Sie sollten versuchen, die vowpal wabbit das ist wahrscheinlich auch das schnellste Kaninchen auf der Erde für große Skala Dokumentenklassifizierung Probleme (aber nicht einfach zu verwenden python-Wrapper AFAIK).

Andere Tipps

Wie groß (Anzahl der Worte) sind Ihre Dokumente? Speicherverbrauch bei 150K trainingdocs sollte kein Problem sein.

Naive Bayes ist eine gute Wahl, besonders wenn Sie viele Kategorien mit nur wenigen Trainingsbeispiele oder sehr laut haben Trainieren Data die Trainieren. Aber im allgemeinen linearen Support Vector Machines Sie führen viel besser.

Ist Ihr Problem mehrklassige (ein Dokument exclusiv nur zu einer Kategorie gehört) oder Multilabel (ein Dokument zu einer oder mehreren Kategorien gehört)?

Die Genauigkeit ist eine schlechte Wahl zu beurteilen Klassifikator Leistung. Sie sollten eher Präzision vs Rückruf, Präzision Rückruf Break-even-Punkt (prbp) verwenden, f1, auc und haben an der Präzision vs Rückruf Kurve zu suchen, wo Rückruf (x) gegen Präzision (y) aufgetragen wird basierend auf dem Wert Ihres Vertrauens-Schwelle (ob ein Dokument gehört zu einer Kategorie oder nicht). Normalerweise würde man einen binären Klassifikator pro Kategorie (positive Trainingsbeispiele einer Kategorie vs alle anderen trainingexamples die dies nicht tun, gehören in Ihre aktuelle Kategorie) bauen. Sie müssen eine optimale Vertrauensschwelle für eine Kategorie wählen. Wenn Sie diese Einzelmaßnahmen pro Kategorie in eine globale Leistungsmessung kombinieren wollen, müssen Sie zu Mikro haben (summieren alle wahren Positiven, Fehlalarme, falsche Negative und wahre Negative und calc kombiniert Noten) oder Makro (ber Punktzahl pro Kategorie und Durchschnitt dann diese Werte über alle Kategorien) Durchschnitt.

Wir haben einen Korpus von zig Millionen Dokumente, Millionen von Trainingsbeispielen und Tausende von Kategorien (Multilabel). Da wir ernsthafte Trainingszeit mit Problemen konfrontiert (die Anzahl der Dokumente neu, aktualisiert oder gelöscht pro Tag ist recht hoch), verwenden wir eine modifizierte Version von liblinear . Aber für kleinere Probleme mit einer der Python-Wrapper um liblinear ( liblinear2scipy oder scikit-Learn ) sollte gut funktionieren.

  

Gibt es eine Möglichkeit, eine „keine der haben   oben“Option für den Klassifikator nur   den Fall, dass das Dokument passen in nicht   eine der Kategorien?

Sie können diesen Effekt erhalten einfach durch eine „keine der oben genannte“ pseudo-Kategorie jedes Mal trainiert. Wenn die max Sie trainieren 5 Kategorien ist (obwohl ich bin mir nicht sicher, warum es frisst ganz so viel RAM), Zug 4 tatsächliche Kategorien von ihren tatsächlichen 2K docs je und ein „keine der oben genannten“ eins mit seiner 2K Dokumente zufällig aus allen anderen 146 Kategorien (etwa 13 bis 14 von jedem, wenn Sie den „geschichteten Stichprobe“ Ansatz wollen, die Klopfer sein kann) genommen.

fühlt sich immer noch wie ein bisschen eine Flickschusterei und Sie vielleicht besser mit einem völlig anderen Ansatz aus - ein mehrdimensionales doc Maß finden, die Ihre 300K pre-markierten Dokumente in 150 hinreichend sicher trennen Cluster definiert, weisen Sie dann nur jeweils die andere noch-nicht markierte Text & Tabellen zu den entsprechenden Cluster als somit bestimmt. Ich glaube nicht, NLTK alles direkt zur Verfügung hat diese Art der Sache zu unterstützen, aber, hey, NLTK ist so schnell gewachsen, dass ich mag wohl etwas verpasst haben ...; -)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top