2013-03-23 13 views
39

Volevo utilizzare wordnet lemmatizer in python e ho appreso che il tag pos predefinito è NOUN e che non emette il lemma corretto per un verbo, a meno che il tag pos sia esplicitamente specificato come VERBO.wordnet lemmatization e pos tagging in python

La mia domanda è che cosa è il miglior colpo inorder per eseguire la lemmatizzazione sopra con precisione?

Ho eseguito il tagging pos utilizzando nltk.pos_tag e mi sono perso nell'integrare i tag pos del tree bank sui tag pos compatibili con wordnet. Please help

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

Ottengo i tag di uscita in NN, JJ, VB, RB. Come posso cambiarle in tag compatibili con wordnet?

fare Inoltre devo allenare nltk.pos_tag() con un corpus etichettato o posso utilizzarlo direttamente sui miei dati per la valutazione?

risposta

56

Prima di tutto, è possibile utilizzare nltk.pos_tag() direttamente senza la formazione di esso. La funzione caricherà un tagger preliminare da un file. È possibile visualizzare il nome del file con nltk.tag._POS_TAGGER:

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

Come è stato addestrato con il corpus Treebank, utilizza anche il Treebank tag set.

La seguente funzione sarebbe mappare i tag Treebank a WordNet parte di nomi di discorso:

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 '' 

È quindi possibile utilizzare il valore di ritorno con l'lemmatizer:

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

aggettivi satellite =) 'ADJ_SAT = 's'' http://wordnet.princeton.edu/wordnet/man/wngloss.7WN.html – alvas

+1

il tag pos per'' it'' in '" I "Mi piace". 'stringa è' 'PRP''.La funzione restituisce una stringa vuota che il lemmatizer non accetta e lancia un 'KeyError'. Cosa si può fare in quel caso? –

+0

Qualcuno sa quanto sia efficiente quando si elaborano interi documenti? – Ksofiac

2

@Suzana_K era w orking. Ma io ci sono alcuni casi risultato in KeyError come menzione @ Clock Slave.

Converti Treebank tag a tag Wordnet

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 

Ora, abbiamo solo pos input in funzione lemmatize solo se abbiamo Wordnet tag

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

passo per la conversione: documento-> Frasi -> Tokens-> 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

È possibile farlo in una sola riga:

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

Quindi utilizzare wnpos(nltk_pos) per ottenere il POS per dare a .lemmatize(). Nel tuo caso, lmtzr.lemmatize(word=tagged[0][0], pos=wnpos(tagged[0][1])).