web-dev-qa-db-ja.com

pythonでのワードネットの見出し語化とposタグ付け

pythonでwordnet lemmatizerを使用したかったのですが、posタグがVERBとして明示的に指定されていない限り、デフォルトのposタグはNOUNであり、動詞の正しい見出し語を出力しないことがわかりました。

私の質問は、上記の補題を正確に実行するための最良のショットは何ですか?

_nltk.pos_tag_を使用してposのタグ付けを行いましたが、ツリーバンクのposタグをwordnet互換のposタグに統合することに失敗しました。助けてください

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

NN、JJ、VB、RBで出力タグを取得します。これらをワードネット互換のタグに変更するにはどうすればよいですか?

また、タグ付きコーパスでnltk.pos_tag()をトレーニングする必要がありますか、それをデータに直接使用して評価できますか?

50
user1946217

まず、トレーニングせずにnltk.pos_tag()を直接使用できます。この関数は、事前に訓練されたタガーをファイルからロードします。 nltk.tag._POS_TAGGERでファイル名を見ることができます:

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

Treebankコーパスでトレーニングされたため、 Treebankタグセット も使用します。

次の関数は、treebankタグを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 ''

次に、lemmatizerで戻り値を使用できます。

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

空の文字列ではKeyErrorが返されるため、戻り値をLemmatizerに渡す前に確認してください。

69
Suzana

Nltk.corpus.reader.wordnetのソースコードのように( http://www.nltk.org/_modules/nltk/corpus/reader/wordnet.html

#{ Part-of-speech constants
 ADJ, ADJ_SAT, ADV, NOUN, VERB = 'a', 's', 'r', 'n', 'v'
#}
POS_LIST = [NOUN, VERB, ADJ, ADV]
10
pg2455

変換手順:ドキュメント->センテンス->トークン-> 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)
8
Deepak

python default dictを使用してマップを作成し、lemmatizerのデフォルトタグが名詞であるという事実を利用できます。

from nltk.corpus import wordnet as wn
from nltk.stem.wordnet import WordNetLemmatizer
from nltk import Word_tokenize, pos_tag
from collections import defaultdict

tag_map = defaultdict(lambda : wn.NOUN)
tag_map['J'] = wn.ADJ
tag_map['V'] = wn.VERB
tag_map['R'] = wn.ADV

text = "Another way of achieving this task"
tokens = Word_tokenize(text)
lmtzr = WordNetLemmatizer()

for token, tag in pos_tag(tokens):
    lemma = lmtzr.lemmatize(token, tag_map[tag[0]])
    print(token, "=>", lemma)
7

@Suzana_Kは機能していました。しかし、@ Clock Slaveが言及しているように、KeyErrorにはいくつかのケースの結果があります。

ツリーバンクタグを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 

ここで、wordnetタグがある場合にのみ、posをlemmatize関数に入力します

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) 
2
Haha TTpro

これは1行で行えます。

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

次に、wnpos(nltk_pos)を使用して、POSを取得して.lemmatize()に渡します。あなたの場合、lmtzr.lemmatize(Word=tagged[0][0], pos=wnpos(tagged[0][1]))

0
wordsforthewise