2016-12-24 2 views
3

Ich möchte in der Lage sein zu sagen, ob ein Satz in Python tatsächlich sinnvoll ist. Zum BeispielKlassifizieren von Text nach Satzstruktur in Python

Hello, how are you today? --> Correct 
Hello, are today are how --> Incorrect 

Bisher habe ich diesen Code, der Folgendes tut:

1 - Ruft 20 000 Sätze aus dem nltk.browns Korpus.
2 - Mischt die Worte der letzten 10 000 Sätze nach oben (für falsche Daten)
3 - Tags alle Sätze des Stanford PO Tagger

from nltk.corpus import brown 
from nltk.tokenize import sent_tokenize, word_tokenize 
from nltk.classify import accuracy 
from nltk.tag import StanfordPOSTagger 
from nltk import pos_tag 
import string 
import random 

PUNC = [x for x in string.punctuation] + ["''", "``"] 

def download_data(target_path): 
    brown_data = brown.sents() 
    i = 0; n = 0 
    with open(target_path, 'w') as data_file: 
     while n < 20000: 
      for sent in sent_tokenize(' '.join(brown_data[i])): 
       updated_list = [x for x in word_tokenize(sent) if x not in PUNC] 
       if n > 10000: 
        random.shuffle(updated_list) 
       sent = ' '.join(updated_list) + '\n' 
       if sent != '\n': 
        data_file.write(sent) 
        n += 1 
       i += 1 

def get_data(data_path): 
    with open(data_path, 'r') as data_file: 
     return [x for x in data_file.readlines()] 

def parse_data(data, tagger): 
    parsed_data = [] 
    for i in range(len(data)): 
     if i > 10000: 
      parsed_data.append((tagger.tag(word_tokenize(data[i].replace('\n', ''))), False)) 
     else: 
      parsed_data.append((tagger.tag(word_tokenize(data[i].replace('\n', ''))), True)) 
    random.shuffle(parsed_data) 
    return parsed_data[:15000], parsed_data[15000:] 

if __name__ == '__main__': 
    data_path = 'data.txt' 

    stanford_jar_path = 'stanford-postagger.jar' 
    stanford_model_path = 'models/english-bidirectional-distsim.tagger' 

    tagger = StanfordPOSTagger(model_filename=stanford_model_path, 
           path_to_jar=stanford_jar_path) 

    #download_data(data_path) 
    all_data = get_data(data_path) 
    train_data, test_data = parse_data(all_data, tagger) 

So Wie kann ich einen Klassifikator zum Beispiel trainieren, zu klassifizieren neue Texte als richtig oder falsch basierend auf den Daten, die ich zur Verfügung gestellt habe?

Wenn jemand bessere Vorschläge hat, bin ich auch offen.

+0

Der technisch richtige Weg, um solche Probleme zu lösen, ist natürlich, (a) ein Sprachmodell aus Texten der Domäne, an der Sie interessiert sind (eine Art RNN/LSTM, wenn Sie Spitzenarbeit sein wollen), dann zu trainieren (b) einen akzeptablen Wahrscheinlichkeits-Cutoff gegenüber einer bekannten Sammlung von guten und schlechten Sätzen aufstellen und schließlich (c) die Satzwahrscheinlichkeiten verwenden, die das Modell Ihnen auf neue, ungesehene Sätze gibt, um Ihren binären Fall zu trennen. Ähnlich wie bei den vorhandenen Antworten sollten Sie zuerst sicherstellen, dass sich dies alles jedoch lohnt, und zwar mit einem schnell und einfach zu bedienenden Bi- oder Tri-Gramm-Modell. – fnl

Antwort

0

Ich würde das Vorhandensein/Fehlen von Folgen von Wortarten betrachten. Ihre Beispiele lassen sich in folgende POS-Nachfolge-Sequenzen transformiert werden:

[('NNP', 'VBP'), ('VBP', 'NN'), ('NN', 'VBP'), ('VBP', 'WRB')] # incorrect 
[('NNP', 'WRB'), ('WRB', 'VBP'), ('VBP', 'PRP'), ('PRP', 'NN')] # correct 

Wenn Sie alle möglichen Kombinationen von zwei POSes bestellen und einen Merkmalsvektor von 0 und 1 bauen, können Sie diese Vektoren können Ihren Algorithmus trainieren.

0

Sie befinden sich auf dem Schritt, wenn Sie Funktionen für Ihr Trainingssatz erstellen müssen. Ich würde 2 und 3 Wort N-Gramm als Funktionen und möglicherweise 2 und 3 Länge N-Gramm POS verwenden. So würden Sie zum Beispiel alle Ihre Sätze nehmen und alle Bi/Trigramme finden und sie binärisieren (machen Sie sie 0, wenn der aktuelle Satz sie nicht enthält und 1, wenn sie es tut). Ich würde das gleiche für POS tun. Machen Sie Bi/Trigramme von POS und binarisieren Sie diese. Dann können Sie etwas wie naive Bayes verwenden, um zu sehen, ob irgendeine Vorhersagekraft existiert.

+0

würde das N-Gram als Features hinzufügen und die Pos-Gram als Features die Genauigkeit über nur Pos-Gramm verbessern? –

+0

Ich denke, dass es eine Vorhersagekraft geben würde, da 'Brauner Fuchs' viel häufiger vorkommen sollte als 'Fuchs braun'.Es gibt bestimmte Kombinationen von Wörtern, die niemals in einem Satz nebeneinander erscheinen würden. Natürlich sollten Sie das empirisch testen. –

+0

Wie würde ich sie binarisieren? würde ich mit einer langen Reihe von Nullen und Einsen enden? @TedPetrou –

0

Betrachten Sie Part-of-Speech-Tags ist eine gute, aber ich glaube, dass N-Gramm-Sprachmodell sollte gut genug für Ihre Aufgabe sein. Hier meine Annahme ist, dass POS-Tags sind nur wenige in Zahlen (36 nach Penn Treebank), so dass die Anzahl der Variationen wird weniger im Vergleich zu Wortschatz Größe des Korpus. Daher können POS-Tags Ihnen eine gute Leistung bringen, aber auch Ihren Klassifizierer in die Irre führen. (meine persönliche Meinung)

Sie können mit bis zu fünf Gramm Sprachmodell experimentieren. Alle N-Grams werden die Merkmale für den Klassifikator sein. Beachten Sie, dass eine höhere Anzahl von N-Gramm die Komplexität erhöht, aber zu mehr Genauigkeit führen sollte.

Zur Klassifizierung können Sie sowohl generative als auch diskriminative Modelle berücksichtigen. Für das generative Modell können Sie Naive-Bayes berücksichtigen und für das diskriminative Modell können Sie entweder SVM oder Logistische Regression berücksichtigen. Diese Klassifizierer funktionieren gut in Textklassifizierungsaufgaben.

Verwandte Themen