NLTK WordNet Lemmatizer: не следует ли лемммировать все перегибы слова?
Я использую Лемматизатор NLTK WordNet для проекта тегов с частичной речью, сначала изменяя каждое слово в корпусе тренировки на его основу (на месте модификации), а затем тренируясь только на новом корпусе. Тем не менее, я обнаружил, что lemmatizer не работает, как я ожидал.
Например, слово loves
лемматизировано на love
, что верно, но слово loving
остается loving
даже после лемматизации. Здесь loving
является таким же, как в предложении "Я люблю его".
Является ли love
основой отклоненного слова loving
? Точно так же многие другие "формы" остаются такими же, как и после лемматизации. Это правильное поведение?
Каковы некоторые другие лемматизаторы, которые точны? (не нужно быть в NLTK) Существуют ли морфологические анализаторы или лемматизаторы, которые также учитывают слово "Часть речи" при решении слова "ствол"? Например, слово killing
должно быть kill
в качестве основы, если killing
используется в качестве глагола, но оно должно иметь killing
в качестве основы, если оно используется как существительное (как в the killing was done by xyz
),.
Ответы
Ответ 1
Лемматизатор WordNet учитывает тег POS, но он не волшебным образом определяет его:
>>> nltk.stem.WordNetLemmatizer().lemmatize('loving')
'loving'
>>> nltk.stem.WordNetLemmatizer().lemmatize('loving', 'v')
u'love'
Без тега POS он предполагает все, что вы кормите, это существительное. Итак, здесь он думает, что вы передаете ему существительное "любящее" (как в "сладкой любви" ).
Ответ 2
Лучший способ устранить эту проблему - фактически посмотреть в Wordnet. Посмотрите здесь: Любить в wordnet. Как вы можете видеть, на самом деле в Wordnet присутствует прилагательное "любящее". На самом деле даже наречие "с любовью": любовно в Wordnet. Поскольку wordnet фактически не знает, какую часть речи вы действительно хотите, она по умолчанию использует существительное ( "n" в Wordnet). Если вы используете набор тегов Penn Treebank, здесь есть удобная функция для преобразования тегов Penn в WN:
from nltk.corpus import wordnet as wn
def is_noun(tag):
return tag in ['NN', 'NNS', 'NNP', 'NNPS']
def is_verb(tag):
return tag in ['VB', 'VBD', 'VBG', 'VBN', 'VBP', 'VBZ']
def is_adverb(tag):
return tag in ['RB', 'RBR', 'RBS']
def is_adjective(tag):
return tag in ['JJ', 'JJR', 'JJS']
def penn_to_wn(tag):
if is_adjective(tag):
return wn.ADJ
elif is_noun(tag):
return wn.NOUN
elif is_adverb(tag):
return wn.ADV
elif is_verb(tag):
return wn.VERB
return None
Надеюсь, что это поможет.
Ответ 3
он более ясный и более эффективный, чем перечисление:
from nltk.corpus import wordnet
def get_wordnet_pos(self, treebank_tag):
if treebank_tag.startswith('J'):
return wordnet.ADJ
elif treebank_tag.startswith('V'):
return wordnet.VERB
elif treebank_tag.startswith('N'):
return wordnet.NOUN
elif treebank_tag.startswith('R'):
return wordnet.ADV
else:
return ''
def penn_to_wn(tag):
return get_wordnet_pos(tag)
Ответ 4
Аналогичные @bogs
Я использую dict:
from textblob.wordnet import NOUN, VERB, ADJ, ADV
pos_to_wornet_dict = {
'JJ': ADJ,
'JJR': ADJ,
'JJS': ADJ,
'RB': ADV,
'RBR': ADV,
'RBS': ADV,
'NN': NOUN,
'NNP': NOUN,
'NNS': NOUN,
'NNPS': NOUN,
'VB': VERB,
'VBG': VERB,
'VBD': VERB,
'VBN': VERB,
'VBP': VERB,
'VBZ': VERB,
}
Ответ 5
В качестве дополнения к принятому ответу из @Fred Foo
выше;
from nltk import WordNetLemmatizer, pos_tag, word_tokenize
lem = WordNetLemmatizer()
word = input("Enter word:\t")
# Get the single character pos constant from pos_tag like this:
pos_label = (pos_tag(word_tokenize(word))[0][1][0]).lower()
# pos_refs = {'n': ['NN', 'NNS', 'NNP', 'NNPS'],
# 'v': ['VB', 'VBD', 'VBG', 'VBN', 'VBP', 'VBZ'],
# 'r': ['RB', 'RBR', 'RBS'],
# 'a': ['JJ', 'JJR', 'JJS']}
if pos_label == 'j': pos_label = 'a' # 'j' <--> 'a' reassignment
if pos_label in ['r']: # For adverbs it a bit different
print(wordnet.synset(word+'.r.1').lemmas()[0].pertainyms()[0].name())
elif pos_label in ['a', 's', 'v']: # For adjectives and verbs
print(lem.lemmatize(word, pos=pos_label))
else: # For nouns and everything else as it is the default kwarg
print(lem.lemmatize(word))