Stoppwortentfernung mit NLTK

76

Ich versuche, einen vom Benutzer eingegebenen Text durch Entfernen von Stoppwörtern mit dem nltk-Toolkit zu verarbeiten, aber beim Entfernen von Stoppwörtern werden die Wörter "und", "oder", "nicht" entfernt. Ich möchte, dass diese Wörter nach dem Entfernen des Stoppworts vorhanden sind, da es sich um Operatoren handelt, die für die spätere Verarbeitung von Text als Abfrage erforderlich sind. Ich weiß nicht, welche Wörter Operatoren in Textabfragen sein können, und ich möchte auch unnötige Wörter aus meinem Text entfernen.

Grahesh Parkar
quelle
Mögliches Duplikat der Liste "Stoppwörter" für Englisch?
Alvas
3
Wenn Sie nicht wissen, welche Wörter Operatoren sein können, können Sie keine Liste von Stoppwörtern angeben. Andernfalls sollten Sie die Stoppwörter, die Sie behalten möchten, aus der nltk-Liste in der Antwort von @alvas entfernen, und das sollte es tun.
aab

Antworten:

70

Ich schlage vor, Sie erstellen eine eigene Liste von Operatorwörtern, die Sie aus der Stoppwortliste entfernen. Sätze können bequem subtrahiert werden, also:

operators = set(('and', 'or', 'not'))
stop = set(stopwords...) - operators

Dann können Sie einfach testen, ob ein Wort inoder not indie Menge vorhanden ist, ohne sich darauf verlassen zu müssen, ob Ihre Operatoren Teil der Stoppwortliste sind. Sie können später zu einer anderen Stoppwortliste wechseln oder einen Operator hinzufügen.

if word.lower() not in stop:
    # use word
otus
quelle
143

Es gibt eine integrierte Stoppwortliste NLTKmit 2.400 Stoppwörtern für 11 Sprachen (Porter et al.), Siehe http://nltk.org/book/ch02.html

>>> from nltk import word_tokenize
>>> from nltk.corpus import stopwords
>>> stop = set(stopwords.words('english'))
>>> sentence = "this is a foo bar sentence"
>>> print([i for i in sentence.lower().split() if i not in stop])
['foo', 'bar', 'sentence']
>>> [i for i in word_tokenize(sentence.lower()) if i not in stop] 
['foo', 'bar', 'sentence']

Ich empfehle, tf-idf zum Entfernen von Stoppwörtern zu verwenden, siehe Auswirkungen von Stemming auf den Begriff Häufigkeit?

Alvas
quelle
2
@alves Ich verwende bereits die obige Methode für meine Aufgabe. Ich wollte nur wissen, welche Wörter als Operatoren aus der Stoppwortliste fungieren könnten.
Grahesh Parkar
2
Die "ideale" Stoppwortliste hängt von der Art der Aufgabe ab. Sie müssen sich also fragen, was das ultimative Ziel Ihrer Aufgabe ist. und dann fragen Sie einen Linguisten, was er herausfiltern soll, um mein Ziel zu erreichen. Ansonsten können Sie sich auch an die statistischen Methoden halten, zB tf-idf filter.
Alvas
4
Übrigens kann die Verwendung von Stop als listlangsam sein. Ich schlage vor, es in ein umzuwandeln set, not indamit es viel billiger wird.
Baskaya
34

Die Antwort von @ alvas erledigt den Job, kann aber viel schneller erledigt werden. Angenommen, Sie haben documents: eine Liste von Zeichenfolgen.

from nltk.corpus import stopwords
from nltk.tokenize import wordpunct_tokenize

stop_words = set(stopwords.words('english'))
stop_words.update(['.', ',', '"', "'", '?', '!', ':', ';', '(', ')', '[', ']', '{', '}']) # remove it if you need punctuation 

for doc in documents:
    list_of_words = [i.lower() for i in wordpunct_tokenize(doc) if i.lower() not in stop_words]

Beachten Sie, dass aufgrund der Tatsache, dass Sie hier in einem Satz (nicht in einer Liste) suchen, die Geschwindigkeit theoretisch len(stop_words)/2mal schneller ist, was wichtig ist, wenn Sie viele Dokumente bearbeiten müssen.

Bei 5000 Dokumenten mit jeweils ungefähr 300 Wörtern beträgt der Unterschied zwischen 1,8 Sekunden für mein Beispiel und 20 Sekunden für @ alvas.

PS In den meisten Fällen müssen Sie den Text in Wörter unterteilen, um einige andere Klassifizierungsaufgaben auszuführen, für die tf-idf verwendet wird. Also wäre es höchstwahrscheinlich besser, auch Stemmer zu verwenden:

from nltk.stem.porter import PorterStemmer
porter = PorterStemmer()

und [porter.stem(i.lower()) for i in wordpunct_tokenize(doc) if i.lower() not in stop_words]innerhalb einer Schleife zu verwenden.

Salvador Dali
quelle
14

@alvas hat eine gute Antwort. Aber auch hier hängt es von der Art der Aufgabe ab, zum Beispiel möchten Sie in Ihrer Anwendung alle conjunctionzB und, oder, wenn, während und alle determinerzB die, a, einige, die meisten, alle, nein berücksichtigen als Stoppwörter berücksichtigen, die alle berücksichtigen Wenn andere Teile der Sprache als legitim gelten, sollten Sie sich diese Lösung ansehen, bei der das Teil-der-Sprache-Tagset zum Verwerfen von Wörtern verwendet wird. Überprüfen Sie Tabelle 5.1 :

import nltk

STOP_TYPES = ['DET', 'CNJ']

text = "some data here "
tokens = nltk.pos_tag(nltk.word_tokenize(text))
good_words = [w for w, wtype in tokens if wtype not in STOP_TYPES]
Aamir Adnan
quelle
6

Sie können string.punctuation mit der integrierten NLTK-Stoppwortliste verwenden:

from nltk.tokenize import word_tokenize, sent_tokenize
from nltk.corpus import stopwords
from string import punctuation

words = tokenize(text)
wordsWOStopwords = removeStopWords(words)

def tokenize(text):
        sents = sent_tokenize(text)
        return [word_tokenize(sent) for sent in sents]

def removeStopWords(words):
        customStopWords = set(stopwords.words('english')+list(punctuation))
        return [word for word in words if word not in customStopWords]

Liste der vollständigen NLTK-Stoppwörter

UsmanZ
quelle