2013-03-23 11 views
39

Ich wollte wordnet lemmatizer in python verwenden und ich habe gelernt, dass die Standard-POS-Tag ist NOUN und dass es nicht das richtige Lemma für ein Verb ausgeben, es sei denn, die POS-Tag explizit angegeben ist VERB.wordnet lemmatization und pos tagging in python

Meine Frage ist, was ist der beste Schuss, um die obige Lemmatisierung genau durchzuführen?

Ich habe die Pos-Tagging mit nltk.pos_tag und ich bin verloren bei der Integration der Baum Bank POS-Tags zu Wordnet-kompatiblen POS-Tags. Bitte helfen

from nltk.stem.wordnet import WordNetLemmatizer 
lmtzr = WordNetLemmatizer() 
tagged = nltk.pos_tag(tokens) 

Ich bekomme die Ausgabe Tags in NN, JJ, VB, RB. Wie ändere ich diese in Wordnet-kompatible Tags?

Muss ich auch nltk.pos_tag() mit einem getaggten Korpus trainieren oder kann ich es direkt auf meine Daten auswerten?

Antwort

56

Zunächst können Sie nltk.pos_tag() direkt verwenden, ohne es zu trainieren. Die Funktion lädt einen vortrainierten Tagger aus einer Datei. Sie können die Dateinamen mit nltk.tag._POS_TAGGER sehen:

nltk.tag._POS_TAGGER 
>>> 'taggers/maxent_treebank_pos_tagger/english.pickle' 

Wie es mit dem Treebank Korpus ausgebildet wurde, ist es auch die Treebank tag set verwendet.

Die folgende Funktion würde die Baumbank-Tags WordNet Wortart Namen zuordnen:

from nltk.corpus import wordnet 

def get_wordnet_pos(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 '' 

können Sie dann den Rückgabewert mit dem Lemmatizer verwenden:

from nltk.stem.wordnet import WordNetLemmatizer 
lemmatizer = WordNetLemmatizer() 
lemmatizer.lemmatize('going', wordnet.VERB) 
>>> 'go' 
+9

erinnern Sie sich auch Satellitenadjektive =) 'ADJ_SAT = 's'' http://wordnet.princeton.edu/wordnet/man/wngloss.7WN.html – alvas

+1

das Pos-Tag für'' es''in '' I liebe es. "' string ist ''PRP''.Die Funktion gibt eine leere Zeichenfolge zurück, die der Lemmatizer nicht akzeptiert, und löst einen 'KeyError' aus. Was kann in diesem Fall getan werden? –

+0

Weiß jemand, wie effizient das bei der Verarbeitung ganzer Dokumente ist? – Ksofiac

2

@Suzana_K war w orking. Aber ich kann KeyError als @ Clock Slave erwähnen.

Convert Baumbank-Tags Wordnet Tag

from nltk.corpus import wordnet 

def get_wordnet_pos(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 None # for easy if-statement 

Jetzt haben wir nur Eingang pos in lemmatize Funktion nur, wenn wir Tag haben wordnet

from nltk.stem.wordnet import WordNetLemmatizer 
lemmatizer = WordNetLemmatizer() 
tagged = nltk.pos_tag(tokens) 
for word, tag in tagged: 
    wntag = get_wordnet_pos(tag) 
    if wntag is None:# not supply tag in case of None 
     lemma = lemmatizer.lemmatize(word) 
    else: 
     lemma = lemmatizer.lemmatize(word, pos=wntag) 
3

Schritt zu konvertieren: Dokument-> Sätze -> Token-> POS-> Lemmas

import nltk 
from nltk.stem import WordNetLemmatizer 
from nltk.corpus import wordnet 

#example text text = 'What can I say about this place. The staff of these restaurants is nice and the eggplant is not bad' 

class Splitter(object): 
    """ 
    split the document into sentences and tokenize each sentence 
    """ 
    def __init__(self): 
     self.splitter = nltk.data.load('tokenizers/punkt/english.pickle') 
     self.tokenizer = nltk.tokenize.TreebankWordTokenizer() 

    def split(self,text): 
     """ 
     out : ['What', 'can', 'I', 'say', 'about', 'this', 'place', '.'] 
     """ 
     # split into single sentence 
     sentences = self.splitter.tokenize(text) 
     # tokenization in each sentences 
     tokens = [self.tokenizer.tokenize(sent) for sent in sentences] 
     return tokens 


class LemmatizationWithPOSTagger(object): 
    def __init__(self): 
     pass 
    def get_wordnet_pos(self,treebank_tag): 
     """ 
     return WORDNET POS compliance to WORDENT lemmatization (a,n,r,v) 
     """ 
     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: 
      # As default pos in lemmatization is Noun 
      return wordnet.NOUN 

    def pos_tag(self,tokens): 
     # find the pos tagginf for each tokens [('What', 'WP'), ('can', 'MD'), ('I', 'PRP') .... 
     pos_tokens = [nltk.pos_tag(token) for token in tokens] 

     # lemmatization using pos tagg 
     # convert into feature set of [('What', 'What', ['WP']), ('can', 'can', ['MD']), ... ie [original WORD, Lemmatized word, POS tag] 
     pos_tokens = [ [(word, lemmatizer.lemmatize(word,self.get_wordnet_pos(pos_tag)), [pos_tag]) for (word,pos_tag) in pos] for pos in pos_tokens] 
     return pos_tokens 

lemmatizer = WordNetLemmatizer() 
splitter = Splitter() 
lemmatization_using_pos_tagger = LemmatizationWithPOSTagger() 

#step 1 split document into sentence followed by tokenization 
tokens = splitter.split(text) 

#step 2 lemmatization using pos tagger 
lemma_pos_token = lemmatization_using_pos_tagger.pos_tag(tokens) 
print(lemma_pos_token) 
0

Sie können dies in einer Zeile:

wnpos = lambda e: ('a' if e[0].lower() == 'j' else e[0].lower()) if e[0].lower() in ['n', 'r', 'v'] else 'n' 

Dann wnpos(nltk_pos) verwenden, um die POS zu erhalten, um() zu .lemmatize. In Ihrem Fall, lmtzr.lemmatize(word=tagged[0][0], pos=wnpos(tagged[0][1])).