Estoy usando el lematizador NLTK WordNet para un proyecto de etiquetado de parte del discurso modificando primero cada palabra en el corpus de entrenamiento a su raíz (modificación en el lugar), y luego entrenando solo en el nuevo corpus. Sin embargo, descubrí que el lemmatizer no funciona como esperaba.

Por ejemplo, la palabra loves está lematizada a love, lo cual es correcto, pero la palabra loving permanece loving incluso después de la lematización. Aquí loving es como en la oración "Me encanta".

¿No es love la raíz de la palabra flexionada loving? Del mismo modo, muchas otras formas 'ing' permanecen como están después de la lematización. ¿Es este el comportamiento correcto?

¿Cuáles son algunos otros lematizadores que son precisos? (no es necesario que esté en NLTK) ¿Existen analizadores de morfología o lematizadores que también tengan en cuenta la etiqueta Parte del habla de una palabra al decidir la raíz de la palabra? Por ejemplo, la palabra killing debe tener kill como raíz si killing se usa como verbo, pero debe tener killing como raíz si se usa como sustantivo (como en the killing was done by xyz).

37
sanjeev mk 27 ago. 2014 a las 22:10

3 respuestas

La mejor respuesta

El lematizador de WordNet tiene en cuenta la etiqueta POS, pero no la determina mágicamente:

>>> nltk.stem.WordNetLemmatizer().lemmatize('loving')
'loving'
>>> nltk.stem.WordNetLemmatizer().lemmatize('loving', 'v')
u'love'

Sin una etiqueta de POS, se supone que todo lo que alimentas es un sustantivo. Así que aquí cree que le estás pasando el sustantivo "amoroso" (como en "dulce amoroso").

69
Fred Foo 27 ago. 2014 a las 19:34

Como una extensión a la respuesta aceptada de @Fred Foo arriba;

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))
0
Kiran Racherla 28 ago. 2019 a las 09:56

Es más clara y más efectiva que la enumeración :

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
Joe Zhow 20 ene. 2018 a las 10:31