《Natural Language Processing with Python》6.2節的一些錯誤

來源:互聯網
上載者:User

最近一直在閱讀《Natural Language Processing with Python》,在閱讀該書的6.2節的Sentence Segmentation時,發現錯誤比較多。現在記錄下來,也許可以幫到其他人,也許以後可以整理一下給該書作者發個郵件。

在說明問題之前,在這裡先列出我的軟體版本:

Python:2.5

Nltk:2.0b2

本節內容簡介

Sentence Segmentation(我不知道如何翻譯,下文中稱作“句子劃分”)把一段文字分成一組句子,由於句子的結尾一般有比較特殊的標點,所以句子劃分可以被看做一個針對標點符號的分類問題,即當我們遇到一個標點符號時,判斷它是不是一個句子的結束。

本節中對於句子劃分任務用的方法是:利用監督學習之樸素Bayes方法,和一般監督學習演算法一樣,其基本步驟為:

1,資料預先處理:把資料整理成一種合適的格式,這樣就便於下一步的特徵提取。

>>> sents = nltk.corpus.treebank_raw.sents()<br />>>> tokens = []<br />>>> boundaries = set()<br />>>> offset = 0<br />>>> for sent in nltk.corpus.treebank_raw.sents():<br />... tokens.extend(sent)<br />... offset += len(sent)<br />... boundaries.add(offset-1) 

2,特徵提取:提取一些比較有分辨能力的特徵。

>>> def punct_features(tokens, i):<br />... return {'next-word-capitalized': tokens[i+1][0].isupper(),<br />... 'prevword': tokens[i-1].lower(),<br />... 'punct': tokens[i],<br />... 'prev-word-is-one-char': len(tokens[i-1]) == 1} 

3,準備訓練資料和測試資料

>>> featuresets = [(punct_features(tokens, i), (i in boundaries))<br />... for i in range(1, len(tokens)-1)<br />... if tokens[i] in '.?!']<br />>>> size = int(len(featuresets) * 0.1)<br />>>> train_set, test_set = featuresets[size:], featuresets[:size] 

4,訓練:利用樸素貝葉斯演算法訓練。

classifier = nltk.NaiveBayesClassifier.train(train_set) 

5,測試:測試訓練出來的分類器效果如何。

>>> nltk.classify.accuracy(classifier, test_set)<br />0.97419354838709682 

那麼如何用該分類器來對一段文字進行句子劃分呢?本節用的方法就是檢查每個標點,判斷它是不是句子的邊界,如果是就把文字從該標點出分開。

def segment_sentences(words):<br /> start = 0<br /> sents = []<br /> for i, word in words:<br /> if word in '.?!' and classifier.classify(words, i) == True:<br /> sents.append(words[start:i+1])<br /> start = i+1<br /> if start < len(words):<br /> sents.append(words[start:]) 

錯誤之處及改正方法

下面我將指出該節代碼中的錯誤之處,並給出相應的解決方案。

問題1:特徵提取函數可能產生越界。

特徵提取函數中的代碼:

'next-word-capitalized': tokens[i+1][0].isupper()

有可能越界,即如果i是這tokens序列的最後一個字元的索引值,那麼上面的代碼就會越界。而且這種情況會經常發生,因為段文字的最後一個字元通常是“.?!”(對英文而言)中的一個,所以一定會執行改行代碼。

解決辦法:因為一般在句尾遇到“.?!”標點之一時,標誌的一句話的結束,那我們就捕獲該異常並把“next-word-capitalized”的值設定為True。

問題2及解決方案:一個小的列印錯誤,書中忘了把對要分類的資料進行特徵提取。

“segment_sentence”函數中第4行的“classifier.classify(words, i) == True”應該改為“classifier.classify(punct_features(words, i))”

問題3:segment_sentence函數才執行完後,我如何才能獲得句子劃分的結果?由於儲存劃分結果的sents變數是一個局部變數,在執行完後,我們在函數外邊是得不到結果的,而且其內部也沒有列印該結果。

解決辦法:在函數結尾加上一句“return sents”,讓其把劃分結果返回。

問題4:當我調用“classifier.show_most_informative_features()”時,提示如下錯誤:

“File "E:/編程工具/py2.5/lib/site-packages/nltk/classify/naivebayes.py", line 144, in show_most_informative_features“

“TypeError: 'bool' object is unsubscriptable”

我針對該錯誤,找到檔案“naivebayes.py”,其144行語句是:

 print ('%24s = %-14r %6s : %-6s = %s : 1.0' %

                   (fname, fval, l1[:6], l0[:6], ratio))

解決辦法:由於,我們的分類任務的類別只有兩個,即True和False,在代碼中即用l1和l0來表示,由於在144行對其執行了下標操作,從而導致了前面的錯誤。我猜想nltk作者可能假設所有類別都是字串,他們為了在輸出的時候保持格式較短,才在這裡做了下標操作。所以,我的解決辦法是在對l1和l0進行下標操作之前把其轉化為字串,即把上面的代碼改為:

 print ('%24s = %-14r %6s : %-6s = %s : 1.0' %

                   (fname, fval, str(l1)[:6], str(l0)[:6], ratio))

至此,我解決了我遇到的問題,我才可以放心的進行下面章節的學習。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.