2011-05-07 160 views
21

我想創建一個小的類似英語的語言來指定任務。基本的想法是將一個陳述分解成這些動詞應該適用的動詞和名詞短語。我與NLTK工作,但沒有得到我所希望的,如結果:自定義標記與nltk

>>> nltk.pos_tag(nltk.word_tokenize("select the files and copy to harddrive'")) 
[('select', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('and', 'CC'), ('copy', 'VB'), ('to', 'TO'), ("harddrive'", 'NNP')] 
>>> nltk.pos_tag(nltk.word_tokenize("move the files to harddrive'")) 
[('move', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('to', 'TO'), ("harddrive'", 'NNP')] 
>>> nltk.pos_tag(nltk.word_tokenize("copy the files to harddrive'")) 
[('copy', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('to', 'TO'), ("harddrive'", 'NNP')] 

在每種情況下,未能實現的第一個字(選擇,移動和複製),旨在爲動詞。我知道我可以創建自定義標記符和語法來解決這個問題,但同時我很猶豫是否會在很多這些東西超出我的聯盟時重新發明輪子。我特別希望能夠處理非英語語言的解決方案。

因此,無論如何,我的問題是: 有沒有更好的標記這種類型的語法? 有沒有一種方法可以使現有標註器比名詞形式更頻繁地使用動詞形式? 有沒有辦法培訓一個標籤? 完全有更好的方法嗎?

回答

22

一個解決方案是創建一個手動UnigramTagger,後者返回到NLTK標記器。事情是這樣的:

>>> import nltk.tag, nltk.data 
>>> default_tagger = nltk.data.load(nltk.tag._POS_TAGGER) 
>>> model = {'select': 'VB'} 
>>> tagger = nltk.tag.UnigramTagger(model=model, backoff=default_tagger) 

然後你得到

>>> tagger.tag(['select', 'the', 'files']) 
[('select', 'VB'), ('the', 'DT'), ('files', 'NNS')] 

同樣的方法可以用於非英語語言的工作,只要你有一個適當的默認惡搞。您可以使用train_tagger.pynltk-trainer和適當的語料庫訓練您自己的標籤符號。

19

雅各布的答案是現貨。但是,要擴展它,你可能會發現你不僅需要unigrams。

例如,考慮了三個句子:

select the files 
use the select function on the sockets 
the select was good 

在此,詞語「選擇」被分別用作動詞,形容詞和名詞。一個unigram tagger將無法對此進行建模。甚至一個bigram tagger也無法處理它,因爲兩個案例共享相同的前面的單詞(即「the」)。你需要一個trigram tagger來正確處理這種情況。

import nltk.tag, nltk.data 
from nltk import word_tokenize 
default_tagger = nltk.data.load(nltk.tag._POS_TAGGER) 

def evaluate(tagger, sentences): 
    good,total = 0,0. 
    for sentence,func in sentences: 
     tags = tagger.tag(nltk.word_tokenize(sentence)) 
     print tags 
     good += func(tags) 
     total += 1 
    print 'Accuracy:',good/total 

sentences = [ 
    ('select the files', lambda tags: ('select', 'VB') in tags), 
    ('use the select function on the sockets', lambda tags: ('select', 'JJ') in tags and ('use', 'VB') in tags), 
    ('the select was good', lambda tags: ('select', 'NN') in tags), 
] 

train_sents = [ 
    [('select', 'VB'), ('the', 'DT'), ('files', 'NNS')], 
    [('use', 'VB'), ('the', 'DT'), ('select', 'JJ'), ('function', 'NN'), ('on', 'IN'), ('the', 'DT'), ('sockets', 'NNS')], 
    [('the', 'DT'), ('select', 'NN'), ('files', 'NNS')], 
] 

tagger = nltk.TrigramTagger(train_sents, backoff=default_tagger) 
evaluate(tagger, sentences) 
#model = tagger._context_to_tag 

注意,您可以使用NLTK的NgramTagger訓練使用任意大量的正克惡搞,但通常你沒有得到卦以後多的性能提升。

+0

是否有可能使用(在雅各布答案等)的模型和培訓句子(如在此答案)? – Sadik 2015-10-17 13:11:02

3

查看Jacob的回答。

在後來的版本(至少nltk 3.2)nltk.tag._POS_TAGGER不存在。默認標註器通常被下載到nltk_data /標記者/目錄,例如:

>>> import nltk 
>>> nltk.download('maxent_treebank_pos_tagger') 

用法如下。

>>> import nltk.tag, nltk.data 
>>> tagger_path = '/path/to/nltk_data/taggers/maxent_treebank_pos_tagger/english.pickle' 
>>> default_tagger = nltk.data.load(tagger_path) 
>>> model = {'select': 'VB'} 
>>> tagger = nltk.tag.UnigramTagger(model=model, backoff=default_tagger) 

另請參閱:How to do POS tagging using the NLTK POS tagger in Python

0

巴德的回答是正確的。另外,根據this link

如果正確安裝了您的nltk_data包,然後NLTK知道他們是在系統上的,而你並不需要傳遞一個絕對路徑。

含義,你就可以說

tagger_path = '/path/to/nltk_data/taggers/maxent_treebank_pos_tagger/english.pickle' 
default_tagger = nltk.data.load(tagger_path)