0

The following code prints out leaf:

from nltk.stem.wordnet import WordNetLemmatizer

lem = WordNetLemmatizer()
print(lem.lemmatize('leaves'))

This may or may not be accurate depending on the surrounding context, e.g. Mary leaves the room vs. Dew drops fall from the leaves. How can I tell NLTK to lemmatize words taking surrounding context into account?

James Ko
  • 32,215
  • 30
  • 128
  • 239
  • Take a look at https://www.kaggle.com/alvations/basic-nlp-with-nltk ("Stemming and Lemmatization" section). – alvas Mar 19 '18 at 05:28

1 Answers1

8

TL;DR

First tag the sentence, then use the POS tag as the additional parameter input for the lemmatization.

from nltk import pos_tag
from nltk.stem import WordNetLemmatizer

wnl = WordNetLemmatizer()

def penn2morphy(penntag):
    """ Converts Penn Treebank tags to WordNet. """
    morphy_tag = {'NN':'n', 'JJ':'a',
                  'VB':'v', 'RB':'r'}
    try:
        return morphy_tag[penntag[:2]]
    except:
        return 'n' 

def lemmatize_sent(text): 
    # Text input is string, returns lowercased strings.
    return [wnl.lemmatize(word.lower(), pos=penn2morphy(tag)) 
            for word, tag in pos_tag(word_tokenize(text))]

lemmatize_sent('He is walking to school')

For a detailed walkthrough of how and why the POS tag is necessary see https://www.kaggle.com/alvations/basic-nlp-with-nltk


Alternatively, you can use pywsd tokenizer + lemmatizer, a wrapper of NLTK's WordNetLemmatizer:

Install:

pip install -U nltk
python -m nltk.downloader popular
pip install -U pywsd

Code:

>>> from pywsd.utils import lemmatize_sentence
Warming up PyWSD (takes ~10 secs)... took 9.307677984237671 secs.

>>> text = "Mary leaves the room"
>>> lemmatize_sentence(text)
['mary', 'leave', 'the', 'room']

>>> text = 'Dew drops fall from the leaves'
>>> lemmatize_sentence(text)
['dew', 'drop', 'fall', 'from', 'the', 'leaf']
alvas
  • 115,346
  • 109
  • 446
  • 738
  • I quite new in python. Can you explain how this part work. return [wnl.lemmatize(word.lower(), pos=penn2morphy(tag)) for word, tag in pos_tag(word_tokenize(text))] or maybe divide it – snailp4el Aug 07 '20 at 09:01
  • 1
    Take a look at https://github.com/usaarhat/pywarmups, esp. session 2 =) – alvas Aug 07 '20 at 13:44