Python NLTK Лемматизация слова "далее" с помощью wordnet
Я работаю над лемматизатором, используя python, NLTK и WordNetLemmatizer. Вот случайный текст, который выводит то, что я ожидал
from nltk.stem import WordNetLemmatizer
from nltk.corpus import wordnet
lem = WordNetLemmatizer()
lem.lemmatize('worse', pos=wordnet.ADJ) // here, we are specifying that 'worse' is an adjective
Выход: 'bad'
lem.lemmatize('worse', pos=wordnet.ADV) // here, we are specifying that 'worse' is an adverb
Выход: 'worse'
Ну, все здесь хорошо. Поведение такое же, как и у других прилагательных, таких как 'better'
(для неправильной формы) или 'older'
(обратите внимание, что тот же тест с 'elder'
никогда не будет выводить 'old'
, но я думаю, что wordnet не является исчерпывающим списком всех существующих английских слов)
Мой вопрос возникает при попытке со словом 'furter'
:
lem.lemmatize('further', pos=wordnet.ADJ) // as an adjective
Выход: 'further'
lem.lemmatize('further', pos=wordnet.ADV) // as an adverb
Выход: 'far'
Это совершенно противоположное поведение одного для 'worse'
слово!
Кто-нибудь может объяснить мне, почему? Является ли это ошибкой, исходящей из данных наборов слов в Wordnet, или из-за моего неправильного понимания грамматики английского языка?
Прошу прощения, если на вопрос уже дан ответ, я ищу в Google и SO, но при указании ключевого слова "далее" я могу найти что-нибудь связанное, кроме беспорядка, из-за популярности этого слова...
Заранее спасибо, Ромен Г.
1 ответ
WordNetLemmatizer
использует ._morphy
функция доступа к лемме слова; с http://www.nltk.org/_modules/nltk/stem/wordnet.html и возвращает возможные леммы с минимальной длиной.
def lemmatize(self, word, pos=NOUN):
lemmas = wordnet._morphy(word, pos)
return min(lemmas, key=len) if lemmas else word
И ._morphy
функция применяет правила итеративно, чтобы получить лемму; правила продолжают сокращать длину слова и заменять аффиксы MORPHOLOGICAL_SUBSTITUTIONS
, тогда он видит, есть ли другие слова, которые короче, но такие же, как сокращенное слово:
def _morphy(self, form, pos):
# from jordanbg:
# Given an original string x
# 1. Apply rules once to the input to get y1, y2, y3, etc.
# 2. Return all that are in the database
# 3. If there are no matches, keep applying rules until you either
# find a match or you can't go any further
exceptions = self._exception_map[pos]
substitutions = self.MORPHOLOGICAL_SUBSTITUTIONS[pos]
def apply_rules(forms):
return [form[:-len(old)] + new
for form in forms
for old, new in substitutions
if form.endswith(old)]
def filter_forms(forms):
result = []
seen = set()
for form in forms:
if form in self._lemma_pos_offset_map:
if pos in self._lemma_pos_offset_map[form]:
if form not in seen:
result.append(form)
seen.add(form)
return result
# 0. Check the exception lists
if form in exceptions:
return filter_forms([form] + exceptions[form])
# 1. Apply rules once to the input to get y1, y2, y3, etc.
forms = apply_rules([form])
# 2. Return all that are in the database (and check the original too)
results = filter_forms([form] + forms)
if results:
return results
# 3. If there are no matches, keep applying rules until we find a match
while forms:
forms = apply_rules(forms)
results = filter_forms(forms)
if results:
return results
# Return an empty list if we can't find anything
return []
Однако, если слово находится в списке исключений, оно вернет фиксированное значение, сохраненное в exceptions
, увидеть _load_exception_map
в http://www.nltk.org/_modules/nltk/corpus/reader/wordnet.html:
def _load_exception_map(self):
# load the exception file data into memory
for pos, suffix in self._FILEMAP.items():
self._exception_map[pos] = {}
for line in self.open('%s.exc' % suffix):
terms = line.split()
self._exception_map[pos][terms[0]] = terms[1:]
self._exception_map[ADJ_SAT] = self._exception_map[ADJ]
Возвращаясь к вашему примеру, worse
-> bad
а также further
-> far
Не может быть достигнуто из правил, поэтому он должен быть из списка исключений. Поскольку это список исключений, возможны несоответствия.
Список исключений хранится в ~/nltk_data/corpora/wordnet/adv.exc
а также ~/nltk_data/corpora/wordnet/adv.exc
,
От adv.exc
:
best well
better well
deeper deeply
farther far
further far
harder hard
hardest hard
От adj.exc
:
...
worldliest worldly
wormier wormy
wormiest wormy
worse bad
worst bad
worthier worthy
worthiest worthy
wrier wry
...