J'essaie de traiter un texte saisi par un utilisateur en supprimant les mots vides à l'aide de nltk toolkit, mais avec stopword-removal, les mots tels que 'et', 'ou', 'non' sont supprimés. Je veux que ces mots soient présents après le processus de suppression des mots vides, car ce sont des opérateurs requis pour le traitement ultérieur du texte en tant que requête. Je ne sais pas quels mots peuvent être des opérateurs dans une requête de texte et je souhaite également supprimer les mots inutiles de mon texte.
Je vous suggère de créer votre propre liste de mots opérateurs que vous retirez de la liste de mots vides. Les ensembles peuvent être facilement soustraits, ainsi:
operators = set(('and', 'or', 'not'))
stop = set(stopwords...) - operators
Ensuite, vous pouvez simplement tester si un mot est in
ou not in
l'ensemble sans que vos opérateurs fassent partie de la liste des mots vides. Vous pourrez ensuite basculer vers une autre liste de mots vides ou ajouter un opérateur.
if Word.lower() not in stop:
# use Word
Il existe une liste intégrée de mots vides dans NLTK
composée de 2 400 mots vides pour 11 langues (Porter et al), voir 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']
Je recommande de regarder avec tf-idf pour supprimer les mots vides, voir Effets de la formation de pied sur la fréquence de terme?
La réponse de @ alvas fait le travail mais cela peut être fait beaucoup plus rapidement. En supposant que vous ayez documents
: une liste de chaînes.
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]
Notez qu'en raison du fait que vous recherchez ici dans un ensemble (et non dans une liste), la vitesse serait théoriquement len(stop_words)/2
fois plus rapide, ce qui est significatif si vous devez utiliser plusieurs documents.
Pour 5000 documents d'environ 300 mots chacun, la différence est comprise entre 1,8 seconde pour mon exemple et 20 secondes pour @ alvas.
P.S. dans la plupart des cas, vous devez diviser le texte en mots pour effectuer d'autres tâches de classification pour lesquelles tf-idf est utilisé. Donc, il serait probablement préférable d'utiliser également stemmer:
from nltk.stem.porter import PorterStemmer
porter = PorterStemmer()
et d'utiliser [porter.stem(i.lower()) for i in wordpunct_tokenize(doc) if i.lower() not in stop_words]
à l'intérieur d'une boucle.
@alvas a une bonne réponse. Mais là encore, cela dépend de la nature de la tâche. Par exemple, dans votre application, vous souhaitez prendre en compte tous les paramètres conjunction
par exemple. et, ou, mais, si, tandis que et tous les determiner
par ex. le, a, certains, la plupart, tous, aucun en tant que mots vides considérant toutes les autres parties du discours comme légitimes, alors vous voudrez peut-être examiner cette solution qui utilisent un jeu d’étiquettes de parole partielle pour supprimer des mots, voir le tableau 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]
Vous pouvez utiliser string.punctuation avec la liste intégrée de mots vides NLTK:
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]
Mots finaux NLTK complets liste