4 Stimmen

Berechnung der Punkt-weisen gegenseitigen Information (PMI) für n-Gramme in Python

Ich habe einen großen Korpus von n-Grammen und mehrere externe n-Gramme. Ich möchte den PMI-Score jedes externen n-Grams auf der Grundlage dieses Korpus (der Zählungen) berechnen.

Gibt es irgendwelche Werkzeuge, um dies zu tun, oder kann jemand mir ein Stück Code in Python, die dies tun kann?

Das Problem ist, dass meine n-Gramme 2-Gramme, 3-Gramme, 4-Gramme und 5-Gramme sind. Die Berechnung der Wahrscheinlichkeiten für 3-Gramme und mehr ist also sehr zeitaufwändig.

5voto

Gareth McCaughan Punkte 19600

Wenn ich Ihr Problem richtig verstehe, wollen Sie Dinge berechnen wie log { P("x1 x2 x3 x4 x5") / P("x1") P("x2") ... P("x5") }, wobei P die Wahrscheinlichkeit misst, dass ein bestimmtes 5-Gramm oder 1-Gramm eine bestimmte Sache ist (und im Grunde ein Verhältnis der Anzahlen ist, vielleicht mit Laplace-ähnlichen Offsets). Machen Sie also einen einzigen Durchgang durch Ihren Korpus und speichern Sie die Zählungen von (1) jedem 1-Gramm, (2) jedem n-Gramm (verwenden Sie für letzteres ein Diktat), und dann führen Sie für jedes externe n-Gramm ein paar Diktatabfragen durch, ein bisschen Arithmetik, und schon sind Sie fertig. Ein Durchlauf durch den Korpus zu Beginn, dann ein fester Arbeitsaufwand pro externem n-Gramm.

(Anmerkung: Eigentlich bin ich mir nicht sicher, wie man PMI für mehr als zwei Zufallsvariablen definiert; vielleicht ist es so etwas wie log P(a)P(b)P(c)P(abc) / P(ab)P(bc)P(a_c). Aber wenn es irgendetwas in dieser Richtung ist, können Sie es auf dieselbe Weise machen: Sie iterieren durch Ihren Korpus und zählen viele Dinge, und dann sind alle Wahrscheinlichkeiten, die Sie brauchen, einfach Verhältnisse der Zählungen, vielleicht mit Laplace-artigen Korrekturen).

Wenn Ihr Korpus so groß ist, dass Sie das n-Gramm-Diktat nicht im Speicher unterbringen können, dann teilen Sie es in speichergroße Stücke auf, berechnen Sie n-Gramm-Diktate für jedes Stück und speichern Sie sie auf der Festplatte in einer Form, die es Ihnen ermöglicht, jeden beliebigen n-Gramm-Eintrag einigermaßen effizient zu erreichen; gehen Sie dann für jedes externe n-Gramm die Stücke durch und addieren Sie die Zählungen.

Welche Form? Das bleibt Ihnen überlassen. Eine einfache Möglichkeit: in lexikographischer Reihenfolge des n-Grams (Anmerkung: wenn Sie mit Wörtern statt mit Buchstaben arbeiten, sollten Sie damit beginnen, Wörter in Zahlen umzuwandeln; dazu benötigen Sie einen einzigen Vorlauf über Ihren Korpus); dann ist das Finden des gewünschten n-Grams eine binäre Suche oder etwas in der Art, was bei Chunks von 1 GB Größe etwa 15-20 Suchvorgänge pro Chunk bedeuten würde; Sie könnten etwas zusätzliche Indizierung hinzufügen, um dies zu reduzieren. Oder: Verwenden Sie eine Hash-Tabelle auf der Festplatte, mit Berkeley DB oder ähnlichem; in diesem Fall können Sie auf das Chunking verzichten. Oder, wenn das Alphabet klein ist (z.B. wenn es sich eher um Buchstaben-N-Gramme als um Wort-N-Gramme handelt und Sie einfachen englischen Text verarbeiten), speichern Sie sie einfach in einem großen Array, mit direktem Nachschlagen -- aber in diesem Fall können Sie das Ganze wahrscheinlich sowieso im Speicher unterbringen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X