То, что вы хотите, это лемматизатор вместо стеммера. Разница неуловима.
Обычно стеммер отбрасывает суффиксы в максимально возможной степени, а в некоторых случаях обрабатывает список исключений слов для слов, которые не могут найти нормализованную форму, просто удаляя суффиксы.
Лемматизатор пытается найти «базовую» / корневую / инфинитивную форму слова, и обычно для этого требуются специальные правила для разных языков.
См.
Лемматизация с использованием реализации NLTK лемматизатора морфий требует правильной метки части речи (POS), чтобы быть достаточно точной.
Избегайте (или фактически никогда) пытайтесь лемматизировать отдельные слова в отдельности. Попробуйте лемматизировать полностью помеченное POS-предложение, например,
from nltk import word_tokenize, pos_tag
from nltk import wordnet as wn
def penn2morphy(penntag, returnNone=False, default_to_noun=False):
morphy_tag = {'NN':wn.NOUN, 'JJ':wn.ADJ,
'VB':wn.VERB, 'RB':wn.ADV}
try:
return morphy_tag[penntag[:2]]
except:
if returnNone:
return None
elif default_to_noun:
return 'n'
else:
return ''
С помощью вспомогательной функции penn2morphy вам нужно преобразовать POS-тег из pos_tag()
в морфи-теги, и тогда вы сможете:
>>> from nltk.stem import WordNetLemmatizer
>>> wnl = WordNetLemmatizer()
>>> sent = "He got up in bed at 8am."
>>> [(token, penn2morphy(tag)) for token, tag in pos_tag(word_tokenize(sent))]
[('He', ''), ('got', 'v'), ('up', ''), ('in', ''), ('bed', 'n'), ('at', ''), ('8am', ''), ('.', '')]
>>> [wnl.lemmatize(token, pos=penn2morphy(tag, default_to_noun=True)) for token, tag in pos_tag(word_tokenize(sent))]
['He', 'get', 'up', 'in', 'bed', 'at', '8am', '.']
Для удобства вы также можете попробовать pywsd
лемматизатор .
>>> from pywsd.utils import lemmatize_sentence
Warming up PyWSD (takes ~10 secs)... took 7.196984529495239 secs.
>>> sent = "He got up in bed at 8am."
>>> lemmatize_sentence(sent)
['he', 'get', 'up', 'in', 'bed', 'at', '8am', '.']
См. Также https://stackoverflow.com/a/22343640/610569