我正在使用NLTK WordNet Lemmatizer进行词性标注项目,首先将训练语料库中的每个单词修改为其词干(就地修改),然后仅对新语料库进行训练。但是,我发现lemmatizer没有按照我的预期运行。
例如,单词loves
被词形化为love
,这是正确的,但即使在词形还原后,单词loving
仍然是loving
。这里loving
与句子“我喜欢它”一样。
love
不是词loving
的词干吗?同样,许多其他“ing”形式仍然存在于词形还原之后。这是正确的行为吗?
哪些其他引理器准确无误? (不需要在NLTK中)是否有形态分析器或词形变换器在决定单词词干时还考虑了单词的词性标记?例如,如果将killing
用作动词,则kill
一词应为killing
,但如果将killing
用作词干,则应将the killing was done by xyz
作为词干。名词(如{{1}})。
答案 0 :(得分:56)
WordNet引理器确实考虑了POS标签,但它没有神奇地决定它:
>>> nltk.stem.WordNetLemmatizer().lemmatize('loving')
'loving'
>>> nltk.stem.WordNetLemmatizer().lemmatize('loving', 'v')
u'love'
如果没有POS标签,它会假定您提供的所有内容都是名词。所以在这里它认为你传给它名词“爱”(如“甜蜜的爱”)。
答案 1 :(得分:27)
解决此问题的最佳方法是实际查看Wordnet。看看这里:Loving in wordnet。正如你所看到的,实际上有一个形容词" loving"存在于Wordnet中。事实上,甚至有一个副词"爱心":lovingly in 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
希望这有帮助。
答案 2 :(得分:2)
它比枚举更清晰,更有效:
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)
答案 3 :(得分:0)
作为上面@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's 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))