Видалення зупинних слів за допомогою NLTK


76

Я намагаюся обробити введений користувачем текст, видаляючи стоп-слова за допомогою набору інструментів nltk, але при видаленні стоп-слова такі слова, як «та», «або», «не», видаляються. Я хочу, щоб ці слова були присутні після процесу видалення зупинки, оскільки вони є операторами, які потрібні для подальшої обробки тексту як запиту. Я не знаю, які слова можуть бути операторами в текстовому запиті, і я також хочу видалити непотрібні слова зі свого тексту.



3
Якщо ви не знаєте, які слова можуть бути операторами, неможливо вказати список стоп-слів. В іншому випадку вам слід видалити стоп-слова, які ви хочете зберегти, зі списку nltk у відповіді @alvas, і це має зробити.
aab,

Відповіді:


70

Я пропоную вам створити власний список операторських слів, які ви вилучаєте зі списку термінів. Набори можна зручно віднімати, тому:

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

Тоді ви можете просто перевірити, чи є слово inчи not inнабір, не покладаючись на те, чи є ваші оператори частиною списку стоп-слів. Потім можна пізніше переключитися на інший список сторвордів або додати оператора.

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

143

Існує вбудований список сторвордів, NLTKщо складається з 2 400 стоп-слів для 11 мов (Портер та ін.), Див. 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']

Я рекомендую поглянути на використання tf-idf для видалення зупинних слів, див. Ефекти стримування на термін частота?


2
@alves Я вже використовую вищезазначений метод для свого завдання. Я просто хотів дізнатись, які можуть бути слова, які будуть діяти як оператори зі списку термінів.
Грахеш Паркар,

2
«Ідеальний» список стоп-слова залежить від характеру завдання. тож ви повинні запитати себе, яка кінцева мета вашого завдання? а потім запитайте у лінгвіста, що відфільтрувати для досягнення моєї мети. В іншому випадку ви також можете дотримуватися статистичних методів, наприклад, фільтр tf-idf.
alvas

4
до речі, використання зупинки як a listможе бути повільним. Я пропоную перетворити його на setтак, що not inбуде набагато дешевше.
Баська,

34

Відповідь @ alvas робить свою справу, але це можна зробити набагато швидше. Якщо припустити, що у вас є documents: список рядків.

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]

Зверніть увагу, що через те, що тут ви шукаєте в наборі (а не в списку), швидкість теоретично буде в len(stop_words)/2рази вищою, що є значним, якщо вам потрібно оперувати багатьма документами.

Для 5000 документів приблизно по 300 слів різниця становить від 1,8 секунди для мого прикладу до 20 секунд для @ alvas.

PS у більшості випадків потрібно розділити текст на слова, щоб виконати деякі інші класифікаційні завдання, для яких використовується tf-idf. Тож, швидше за все, було б краще також використовувати стеммер:

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

і використовувати [porter.stem(i.lower()) for i in wordpunct_tokenize(doc) if i.lower() not in stop_words]всередині циклу.


14

@alvas має гарну відповідь. Але знову ж таки це залежить від характеру завдання, наприклад, у вашій програмі ви хочете розглянути всі conjunctionнаприклад, і, або, але, якщо, в той час як і всі, determinerнаприклад , a, деякі, більшість, кожен, ні як слова зупинки, враховуючи всі інші частини мови як правомірні, тоді ви можете розглянути це рішення, яке використовує тег часткової мови для відкидання слів, перевірте таблицю 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]

6

Ви можете використовувати string.punctuation із вбудованим списком стовпців 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]

Повний список стоп-речей NLTK

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.