分類算法是機器學習算法中的一種,用來判斷給定數據項所屬的類別,即種類或類型。比如,可以根據某些特征來分辨一部電影屬于哪個流派,等等。這樣,流派就是我們要預測的類別。第10章“預測性分析與機器學習”還會對機器學習做進一步介紹。此刻,我們要討論的是一個名為樸素貝葉斯分類的流行算法,它常常用于進行文本文檔的研究。
樸素貝葉斯分類是一個概率算法,它基于概率與數理統計中的貝葉斯定理。貝葉斯定理給出了如何利用新證據修正某事件發生的概率的方法。例如,假設一個袋子里裝有一些巧克力和其他物品,但是這些我們沒法看到。這時,我們可以用P(D)表示從袋子中掏出一塊深色巧克力的概率。同時,我們用P(C)代表掏出一塊巧克力的概率。當然,因為全概率是1,所以P(D)和P(C)的最大取值也只能是1。貝葉斯定理指出,后驗概率與先驗概率和相似度的乘積成正比,具體公式如下所示:
上面公式中,P(C|D)是在事件C發生的情況下事件D發生的可能性。在我們還沒有掏出任何物品之前,P(D)= 0.5,因為我們尚未獲得任何信息。實際應用這個公式時,必須知道P(C|D)和P(C),或者能夠間接求出這兩個概率。
樸素貝葉斯分類之所以稱為樸素,是因為它簡單假設特征之間是相互獨立的。實踐中,樸素貝葉斯分類的效果通常都會很好,說明這個假設得到了一定程度的保證。近來,人們發現這個假設之所以有意義,理論上是有依據的。不過,由于機器學習領域發展迅猛,現在已經發明了多種效果更佳的算法。
下面,我們將利用停用詞或標點符號對單詞進行分類。這里,將字長作為一個特征,因為停用詞和標點符號往往都比較短。
為此,需要定義如下所示的函數:
def word_features(word):
return {'len': len(word)}
def isStopword(word):
return word in sw or word in punctuation
下面,對取自古登堡項目的shakespeare-caesar.txt中的單詞進行標注,以區分是否為停用詞,具體代碼如下所示:
labeled_words = ([(word.lower(), isStopword(word.lower())) for
word in words])
random.seed(42)
random.shuffle(labeled_words)
print labeled_words[:5]
下面顯示了5個標注后的單詞:
[('was', True), ('greeke', False), ('cause', False), ('but', True), ('house', False)]
對于每個單詞,我們可以求出其長度:
featuresets = [(word_features(n), word) for (n, word) in
labeled_words]
前幾章介紹過擬合,以及通過訓練數據集和測試數據集的交叉驗證來避免這種情況的方法。下面將要訓練一個樸素貝葉斯分類器,其中90%的單詞用于訓練,剩下的10%用于測試。首先,創建訓練數據集和測試數據集,并針對數據展開訓練,具體代碼如下所示:
cutoff = int(.9 * len(featuresets))
train_set, test_set = featuresets[:cutoff], featuresets[cutoff:]
classifier = nltk.NaiveBayesClassifier.train(train_set)
如今,拿出一些單詞,檢查該分類器的效果。
classifier = nltk.NaiveBayesClassifier.train(train_set)
print "'behold' class",
classifier.classify(word_features('behold'))
print "'the' class", classifier.classify(word_features('the'))
幸運的是,這些單詞的分類完全正確:
'behold' class False 'the' class True
然后,根據測試數據集來計算分類器的準確性,具體代碼如下所示:
print "Accuracy", nltk.classify.accuracy(classifier, test_set)
這個分類器的準確度非常高,幾乎達到85%。下面來看哪些特征的貢獻最大:
print classifier.show_most_informative_features(5)
結果顯示,在分類過程中字長的作用最大:
下列代碼取自本書代碼包中的naive_classification.py文件:
import nltk
import string
import random
sw = set(nltk.corpus.stopwords.words('english'))
punctuation = set(string.punctuation)
def word_features(word):
return {'len': len(word)}
def isStopword(word):
return word in sw or word in punctuation
gb = nltk.corpus.gutenberg
words = gb.words("shakespeare-caesar.txt")
labeled_words = ([(word.lower(), isStopword(word.lower())) for
word in words])
random.seed(42)
random.shuffle(labeled_words)
print labeled_words[:5]
featuresets = [(word_features(n), word) for (n, word) in
labeled_words]
cutoff = int(.9 * len(featuresets))
train_set, test_set = featuresets[:cutoff], featuresets[cutoff:]
classifier = nltk.NaiveBayesClassifier.train(train_set)
print "'behold' class",
classifier.classify(word_features('behold'))
print "'the' class", classifier.classify(word_features('the'))
print "Accuracy", nltk.classify.accuracy(classifier, test_set)
print classifier.show_most_informative_features(5)
以上內容選自《Python數據分析》