Ответ 1
Python-реализации алгоритмов stemming Porter, Porter2, Paice-Husk и Lovins для английского языка доступны в пакете stemming
Я пробовал все методы nltk для создания, но это дает мне странные результаты с некоторыми словами.
Примеры
Он часто прерывает слова, когда он не должен этого делать:
или не является очень хорошим:
Знаете ли вы, что в python есть другие libring, или хороший словарь?
спасибо
Python-реализации алгоритмов stemming Porter, Porter2, Paice-Husk и Lovins для английского языка доступны в пакете stemming
Результаты, которые вы получаете (как правило) ожидаются для английского языка. Вы говорите, что пробовали "все методы nltk", но когда я пробую ваши примеры, похоже, это не так.
Вот несколько примеров использования PorterStemmer
import nltk
ps = nltk.stemmer.PorterStemmer()
ps.stem('grows')
'grow'
ps.stem('leaves')
'leav'
ps.stem('fairly')
'fairli'
Результатами являются "grow", "leav" и "fairli", которые, даже если они того, что вы хотели, являются основополагающими версиями оригинального слова.
Если мы переключимся на стеммер Snowball, мы должны указать язык в качестве параметра.
import nltk
sno = nltk.stem.SnowballStemmer('english')
sno.stem('grows')
'grow'
sno.stem('leaves')
'leav'
sno.stem('fairly')
'fair'
Результаты такие же, как и раньше, для "растет" и "уходит", но "справедливо" сводится к "честному"
Таким образом, в обоих случаях (а в nltk доступно более двух модулей), слова, которые вы говорите, на самом деле не основаны. LancasterStemmer вернет "easy", если в качестве входных данных указано "easy" или "easy".
Может быть, вы действительно хотели лемматизатор? Это вернет "статью" и "пудель" без изменений.
import nltk
lemma = nltk..wordnet.WordNetLemmatizer()
lemma.lemmatize('article')
'article'
lemma.lemmatize('leaves')
'leaf'
Все эти стволовые клетки, которые обсуждались здесь, являются алгоритмическими, поэтому они всегда могут давать неожиданные результаты, такие как
In [3]: from nltk.stem.porter import *
In [4]: stemmer = PorterStemmer()
In [5]: stemmer.stem('identified')
Out[5]: u'identifi'
In [6]: stemmer.stem('nonsensical')
Out[6]: u'nonsens'
Чтобы правильно получить корневые слова, нужен словарь-основатель, такой как Hunspell Stemmer. Вот его реализация на основе python в следующей ссылке. Пример кода здесь
>>> import hunspell
>>> hobj = hunspell.HunSpell('/usr/share/myspell/en_US.dic', '/usr/share/myspell/en_US.aff')
>>> hobj.spell('spookie')
False
>>> hobj.suggest('spookie')
['spookier', 'spookiness', 'spooky', 'spook', 'spoonbill']
>>> hobj.spell('spooky')
True
>>> hobj.analyze('linked')
[' st:link fl:D']
>>> hobj.stem('linked')
['link']
Стемминг - это удаление суффиксов (как правило, только суффиксы, поскольку, как я пытался, ни один из стеммеров nltk не может удалить префикс, забудьте об инфиксах). Таким образом, мы можем четко назвать стемминг глупой/не очень умной программой. Он не проверяет, имеет ли слово значение до или после Например, Если вы попытаетесь остановить "xqaing", хотя это не слово, оно удалит "-ing" и выдаст "xqa".
Таким образом, чтобы использовать более разумную систему, можно использовать лемматизаторы. Лемматизаторы используют правильно сформированные леммы (слова) в форме словосочетания и словарей. Так что всегда возвращается и принимает правильное слово. Тем не менее, это медленно, потому что он проходит через все слова, чтобы найти соответствующее.
Стеммеры различаются по своей агрессивности. Портер является одним из самых агрессивных монстров для английского языка. Я нахожу, что обычно болит больше, чем помогает. На более легкой стороне вы можете использовать лемматизатор, как уже предлагалось, или более легкий алгоритмический стеммер. Недостатком лемматизаторов является то, что они не могут обрабатывать неизвестные слова.
Лично мне нравится стеммер Krovetz, который представляет собой гибридное решение, сочетающее лемматизатор словаря и облегченный стеммер для словарных слов. Krovetz также вариант kstem
или light_stemmer
в Elasticsearch. В pypi есть https://pypi.org/project/KrovetzStemmer/ реализация Python, хотя я не использовал ее.
Другой вариант - лемматизатор в spaCy
. После обработки с помощью spaCy
каждый токен имеет атрибут lemma_
. (обратите внимание, подчеркивание lemma
содержит числовой идентификатор lemma_
) - https://spacy.io/api/token
Вот несколько работ, сравнивающих различные алгоритмы
В моем проекте чат-бота я использовал PorterStemmer, однако LancasterStemmer также служит этой цели. Конечная цель состоит в том, чтобы свести слово к его корню, чтобы мы могли искать и сравнивать вводимые слова.
Например: из nltk.stem import PorterStemmer ps = PorterStemmer()
def SrchpattrnStmmed(self):
KeyWords =[]
SrchpattrnTkn = word_tokenize(self.input)
for token in SrchpattrnTkn:
if token not in stop_words:
KeyWords.append(ps.stem(token))
continue
#print(KeyWords)
return KeyWords
Надеюсь, это поможет..