2015-10-15 60 views
2

我正在使用Python3.5的nltk pos_tag函數和WordNetLemmatizer。我的目標是在我們的數據庫中拼合單詞以分類文本。我正在嘗試使用lemmatizer進行測試,並且在相同的記號上使用POS標記時遇到了奇怪的行爲。在下面的例子中,我有一個三個字符串的列表,當它們在POS標記器中運行時,其他每個元素都作爲名詞(NN)返回,其餘的作爲動詞(VBG)返回。詞性標註後的單詞產生意想不到的結果

這會影響詞形。輸出看起來是這樣的:

pos Of token: v 
lemmatized token: skydive 
pos Of token: n 
lemmatized token: skydiving 
pos Of token: v 
lemmatized token: skydive 

如果我添加更多的元素到相同的字符串列表,這種模式仍然繼續。在全我使用的代碼是這樣的:

tokens = ['skydiving', 'skydiving', 'skydiving'] 
lmtzr=WordNetLemmatizer() 

def get_wordnet_pos(treebank_tag): 
    if treebank_tag.startswith('J'): 
     return 'a' 
    elif treebank_tag.startswith('V'): 
     return 'v' 
    elif treebank_tag.startswith('N'): 
     return 'n' 
    elif treebank_tag.startswith('R'): 
     return 'r' 
    elif treebank_tag.startswith('S'): 
     return '' 
    else: 
     return '' 

numTokens = (len(tokens)) 
for i in range(0,numTokens): 
    tokens[i]=tokens[i].replace(" ","") 

noSpaceTokens = pos_tag(tokens) 

for token in noSpaceTokens: 
    tokenStr = str(token[1]) 
    noWhiteSpace = token[0].replace(" ", "") 
    preLemmed = get_wordnet_pos(tokenStr) 
    print("pos Of token: " + preLemmed) 
    lemmed = lmtzr.lemmatize(noWhiteSpace,preLemmed) 
    print("lemmatized token: " + lemmed) 

回答

2

簡而言之:

當POS標籤你需要上下文的句子不是一個不合語法標記列表。

當lemmatizing斷章取義句話,以獲得正確的引理的唯一方法是手動指定POS標籤。


在長:

POS惡搞通常工作在完整的句子,而不是單個的單詞。當您嘗試在上下文之外標記一個單詞時,您得到的是最常見的標籤。

要驗證標籤一個字(即只用1個字的句子)時,它總是給相同的標籤:

>>> from nltk.stem import WordNetLemmatizer 
>>> from nltk import pos_tag 
>>> ptb2wn_pos = {'J':'a', 'V':'v', 'N':'n', 'R':'r'} 
>>> sent = ['skydive'] 
>>> most_frequent_tag = pos_tag(sent)[0][1] 
>>> most_frequent_tag 
'JJ' 
>>> most_frequent_tag = ptb2wn_pos[most_frequent_tag[0]] 
>>> most_frequent_tag 
'a' 
>>> for _ in range(1000): assert ptb2wn_pos[pos_tag(sent)[0][1][0]] == most_frequent_tag; 
... 
>>> 

現在,由於標籤始終是「A」默認情況下,如果句子只能有1個字,那麼WordNetLemmatizer總會返回skydive

>>> wnl = WordNetLemmatizer() 
>>> wnl.lemmatize(sent[0], pos=most_frequent_tag) 
'skydive' 

讓我們來看看引理一個詞在句子的語境:

>>> sent2 = 'They skydrive from the tower yesterday' 
>>> pos_tag(sent2.split()) 
[('They', 'PRP'), ('skydrive', 'VBP'), ('from', 'IN'), ('the', 'DT'), ('tower', 'NN'), ('yesterday', 'NN')] 
>>> pos_tag(sent2.split())[1] 
('skydrive', 'VBP') 
>>> pos_tag(sent2.split())[1][1] 
'VBP' 
>>> ptb2wn_pos[pos_tag(sent2.split())[1][1][0]] 
'v' 

因此,當您執行pos_tag時,輸入令牌列表的上下文很重要。

在你的榜樣,你有一個清單['skydiving', 'skydiving', 'skydiving']這意味着你有POS標記的句子的不合語法的句子:

跳傘跳傘跳傘

而且pos_tag函數認爲是正常的句子因而令標籤:

>>> sent3 = 'skydiving skydiving skydiving'.split() 
>>> pos_tag(sent3) 
[('skydiving', 'VBG'), ('skydiving', 'NN'), ('skydiving', 'VBG')] 

在這種情況下,第一個是動詞,第二WOR DA名詞和第三字是動詞,這將返回下面的引理(你不希望):

>>> wnl.lemmatize('skydiving', 'v') 
'skydive' 
>>> wnl.lemmatize('skydiving', 'n') 
'skydiving' 
>>> wnl.lemmatize('skydiving', 'v') 
'skydive' 

因此,如果我們在您的令牌列表的有效語法的句子,輸出可能看起來非常不同

>>> sent3 = 'The skydiving sport is an exercise that promotes diving from the sky , ergo when you are skydiving , you feel like you are descending to earth .' 
>>> pos_tag(sent3.split()) 
[('The', 'DT'), ('skydiving', 'NN'), ('sport', 'NN'), ('is', 'VBZ'), ('an', 'DT'), ('exercise', 'NN'), ('that', 'IN'), ('promotes', 'NNS'), ('diving', 'VBG'), ('from', 'IN'), ('the', 'DT'), ('sky', 'NN'), (',', ','), ('ergo', 'RB'), ('when', 'WRB'), ('you', 'PRP'), ('are', 'VBP'), ('skydiving', 'VBG'), (',', ','), ('you', 'PRP'), ('feel', 'VBP'), ('like', 'IN'), ('you', 'PRP'), ('are', 'VBP'), ('descending', 'VBG'), ('to', 'TO'), ('earth', 'JJ'), ('.', '.')] 
+0

是的,我擔心缺乏背景是問題所在。我想我試圖潛入nltk沒有適當的背景。現在從第一章開始寫這本書。必須找到另一種方法來嘗試解決這個問題。 – kinghenry14

相關問題