Ich verwende den NLTK-WordNet-Lemmatizer für ein Spracherkennungsprojekt "Part-of-Speech", indem ich zunächst jedes Wort im Trainingskorpus an seinem Stamm (in situ-Änderung) änderte und dann nur den neuen Korpus trainiere. Ich stellte jedoch fest, dass der Lemmatizer nicht wie erwartet funktioniert.
Beispielsweise wird das Wort loves
auf love
lemmatisiert, was korrekt ist, das Wort loving
bleibt jedoch auch nach der Lemmatisierung loving
. Hier ist loving
wie im Satz "Ich liebe es".
Ist love
nicht der Stamm des gebeugten Wortes loving
? In ähnlicher Weise bleiben viele andere "ing" -Formen so, wie sie nach der Lemmatisierung sind. Ist das das richtige Verhalten?
Was sind andere Lemmatizer, die genau sind? (muss nicht in NLTK sein) Gibt es Morphologieanalysatoren oder Lemmatizer, die bei der Entscheidung über den Wortstamm auch das Wort "Part Of Speech" von Word berücksichtigen? Beispielsweise sollte das Wort killing
kill
als Stamm haben, wenn killing
als Verb verwendet wird, es sollte jedoch killing
als Stamm haben, wenn es als Nomen verwendet wird (wie in the killing was done by xyz
).
Der WordNet-Lemmatizer does berücksichtigt das POS-Tag, bestimmt es aber nicht magisch:
>>> nltk.stem.WordNetLemmatizer().lemmatize('loving')
'loving'
>>> nltk.stem.WordNetLemmatizer().lemmatize('loving', 'v')
u'love'
Ohne ein POS-Tag wird davon ausgegangen, dass alles, was Sie füttern, ein Substantiv ist. Hier also denkt man, man übergibt das Substantiv "Lieben" (wie "süße Lieben").
Der beste Weg zur Fehlerbehebung besteht darin, tatsächlich in Wordnet zu suchen. Schauen Sie hier: Lieben in Wordnet . Wie Sie sehen, gibt es in Wordnet tatsächlich ein Adjektiv "Lieben". Tatsächlich gibt es sogar das Adverb "liebevoll": liebevoll in Wordnet . Da wordnet nicht genau weiß, welchen Teil der Sprache Sie eigentlich wollen, wird standardmäßig Nomen ('n' in Wordnet) verwendet. Wenn Sie den Penn Treebank-Tag-Satz verwenden, finden Sie hier einige nützliche Funktionen zum Umwandeln von Penn in WN -Tags:
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
Hoffe das hilft.
Als Erweiterung zu der akzeptierten Antwort von @Fred Foo
über;
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))
Ähnliches mit Motiven
Ich benutze ein Diktat:
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,
}
es ist klarer und effektiver als die Aufzählung:
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)