机器学习系列之手把手教你实现一个 naiveBayes
https://www.ibm.com/developerworks/cn/analytics/library/machine-learning-hands-on3-naivebayes/index.html?ca=drs-
樸素貝葉斯簡(jiǎn)介
在本系列的前面兩篇文章中,分別介紹了 SVM 模型和 FP-growth 模型。其中 SVM 模型主要用于分類,FP-growth 模型用于挖掘頻繁項(xiàng)集和關(guān)聯(lián)規(guī)則。本文將介紹 naiveBayes 模型,即樸素貝葉斯模型。樸素貝葉斯模型主要用來分類,但是與 SVM 模型不同的的是,樸素貝葉斯模型不需要針對(duì)目標(biāo)變量建立模型,而是借助貝葉斯公式計(jì)算樣本屬于各個(gè)類別的概率,然后取概率值大的類別作為分類類別。之所以稱之為樸素,是因?yàn)闃闼刎惾~斯模型假設(shè)各屬性之間是條件獨(dú)立的,該假設(shè)極大得簡(jiǎn)化了運(yùn)算,使得樸素貝葉斯模型變得非常簡(jiǎn)單。
樸素貝葉斯模型主要應(yīng)用在文本分類方面。這里需要用到向量空間模型,即將文本轉(zhuǎn)換成詞向量。詞向量的每一項(xiàng)是該詞出現(xiàn)的頻數(shù)。在樸素貝葉斯中會(huì)將頻數(shù)進(jìn)一步轉(zhuǎn)換成頻率。這樣就完成了文本到數(shù)值上的轉(zhuǎn)化,方便后期計(jì)算條件概率和先驗(yàn)概率。
樸素貝葉斯模型也有它的優(yōu)缺點(diǎn),優(yōu)點(diǎn)是模型簡(jiǎn)單,計(jì)算快;缺點(diǎn)是依賴于屬性之間條件獨(dú)立這一假設(shè),但是現(xiàn)實(shí)場(chǎng)景下很多情況并不滿足這一假設(shè),使得樸素貝葉斯的準(zhǔn)確率受到影響。這種情況需要考慮半樸素貝葉斯,即放松屬性之間條件獨(dú)立這一假設(shè),一定程度上考慮屬性之間的依賴關(guān)系。由于篇幅有限,對(duì)半樸素貝葉斯感興趣的話可自行參照文末參考資源學(xué)習(xí),本文重點(diǎn)介紹樸素貝葉斯的原理和實(shí)現(xiàn)。
樸素貝葉斯原理
樸素貝葉斯模型主要利用貝葉斯公式進(jìn)行展開。貝葉斯公式如下:
圖 1. 貝葉斯公式
公式中 P(C|X)表示 X 屬于類別 C 的概率,P(X|C)表示類別 C 中 X 出現(xiàn)的概率,P(C)表示類別 C 出現(xiàn)的概率。其中 P(C)稱為先驗(yàn)概率,P(X|C)是條件概率,P(C|X)稱為后驗(yàn)概率,將后驗(yàn)概率最大的類作為 X 的類別輸出。假設(shè)有 C0 和 C1 兩個(gè)類,由于 P(X)都是一樣的,所以不需要考慮 P(X),只需考慮如下:
由上述可知,需要計(jì)算 P(X|C)和 P(C)。樸素貝葉斯假設(shè)屬性之間條件獨(dú)立,可得:
P(X|C) =?P(X0|C) *?P(X1|C) *?P(X2|C) *?P(X3|C) *… *?P(Xn|C)
令 Dc 表示訓(xùn)練集 D 中第 C 類樣本組成的集合,可得:
P(Xi|C) = |Dc,xi| / |Dc,x|,表示類別為 C 的樣本在第 i 個(gè)屬性上頻數(shù)總和除以類別為 C 的樣本集合中所有屬性頻數(shù)總和。為了避免 P(Xi|C)為 0 造成 P(X|C)為 0 而影響分類結(jié)果,在此引入拉普拉斯平滑,本文分別給分子和分母加上 1 和 2,即 P(Xi|C) = (|Dc,xi| + 1) / (|Dc,x| + 2)。
又有 P(C) = |Dc| / |D|, 表示類別為 C 的樣本集合大小除以數(shù)據(jù)集 D 的樣本集合大小。
至此,通過 P(X|C0) *?P(C0) 和?P(X|C1) *?P(C1)的大小比較,可得 X 所屬類別。但是小數(shù)連乘會(huì)造成所得值幾乎等于 0 的結(jié)果,從而無法比較大小。鑒于此,往往在實(shí)際運(yùn)算中,會(huì)借助 log 函數(shù),比較 log(P(X|C0) *?P(C0)) 和 log(P(X|C1) *?P(C1))的大小來判斷 X 所屬類別。從而得:
log(?P(X|C0) *?P(C0) ) = log(P(X|C0)) + log(P(C0)) = log(P(X0|C0)) + log(P(X1|C0)) + log(P(X2|C0)) + …+ log(P(Xn|C0)) + log(P(C0)),
同理可得 log(?P(X|C1) *?P(C1) ) = log(P(X|C1)) + log(P(C1)) = log(P(X0|C1)) + log(P(X1|C1)) + log(P(X2|C1)) + …+ log(P(Xn|C1)) + log(P(C1))。
用樸素貝葉斯進(jìn)行文本分類
利用樸素貝葉斯模型進(jìn)行文本分類,首先需要將文本表示成詞向量,再從詞向量中計(jì)算得到條件概率 P(X|C)和先驗(yàn)概率 P(C),然后利用條件概率 P(X|C)與先驗(yàn)概率 P(C)計(jì)算后驗(yàn)概率 P(C0|X)、P(C1|X)。最終比較 P(C0|X)、P(C1|X)大小得到 X 屬于 C0 類還是 C1 類。下面用表 1 所示訓(xùn)練數(shù)據(jù)和表 2 所示測(cè)試數(shù)據(jù)展開介紹。
表 1. 示例訓(xùn)練數(shù)據(jù)集
| 1 | 'book', 'student', 'campus', 'study' |
| 0 | 'others', 'game', 'sky' |
| 1 | 'campus', ' book ' |
| 0 | 'others', 'yes' |
表 2. 示例測(cè)試數(shù)據(jù)集
| ? | 'book', 'campus', 'study' |
從文本到詞向量
首先需要將文本表示成詞向量,去掉重復(fù)的詞。將表 1 中示例數(shù)據(jù)集表示成詞向量如下:
[ 'book', 'student', 'campus', 'study', 'others', 'game', 'sky', 'yes' ]
可以看出,重復(fù)的'campus', 'book', 'others'都只出現(xiàn)了一次。
然后,需要將文本列表轉(zhuǎn)換成詞向量列表,文本中的詞在詞向量中出現(xiàn)為 1,未出現(xiàn)為 0, 如表 3,4 所示:
表 3. 訓(xùn)練文本詞向量列表
| 1 | [1, 1, 1, 1, 0, 0, 0, 0] |
| 0 | [0, 0, 0, 0, 1, 1, 1, 0] |
| 1 | [1, 0, 1, 0, 0, 0, 0, 0] |
| 0 | [0, 0, 0, 0, 1, 0, 0, 1] |
表 4. 測(cè)試文本詞向量列表
| ? | [1, 0, 1, 1, 0, 0, 0, 0] |
從詞向量到條件概率和先驗(yàn)概率
由上一章知,
條件概率 P(X|C) =?P(X0|C) *?P(X1|C) *?P(X2|C) *?P(X3|C) *… *?P(Xn|C),
為防止概率為 0 影響結(jié)果,加入拉普拉斯平滑后 P(Xi|C) = (|Dc,xi| + 1) / (|Dc,x| + 2),
先驗(yàn)概率 P(C) = |Dc| / |D|。
為防止小數(shù)連乘造成結(jié)果幾乎為 0,引入 log 函數(shù),由于測(cè)試文本只包含 X0, X2, X3, 得:
log(?P(X|C0) *?P(C0) ) = log(P(X0|C0)) + log(P(X2|C0)) + log(P(X3|C0)) + log(P(C0))
log(?P(X|C1) *?P(C1) ) = log(P(X0|C1)) + log(P(X2|C1)) + log(P(X3|C1)) + log(P(C1))
代入數(shù)據(jù),得
P(X0|C0) =?P(X2|C0) =?P(X3|C0) = (0 + 1) / (5 + 2) = 1/7,
P(C0) =?P(C1) = 2 / 4,
P(X0|C1) =?P(X2|C1) = (2 + 1) / (6 + 2) = 3/8,
P(X3|C1) = (1 + 1) / (6 + 2) = 2/8,
故可得:
log(?P(X|C0) *?P(C0) ) = log(1/7) + log(1/7) + log(1/7) + log(2/4) = -2.84
log(?P(X|C1) *?P(C1) ) = log(3/8) + log(3/8) + log(2/8) + log(2/4) = -1.76
根據(jù)后驗(yàn)概率分類
由上一章知,
因此后驗(yàn)概率 P(C0|X)只需考慮 P(X|C0) *?P(C0) ,同理后驗(yàn)概率 P(C1|X)只需考慮 P(X|C1) *?P(C1)。
已知:
如果 log(?P(X|C0) *?P(C0) ) > log(?P(X|C1) *?P(C1) ),則 P(C0|X) >?P(C1|X),可得 X 屬于 C0 類;
如果 log(?P(X|C0) *?P(C0) ) < log(?P(X|C1) *?P(C1) ),則 P(C0|X) <?P(C1|X),可得 X 屬于 C1 類。
又由于-1.76 > -2.84, 所以 log(?P(X|C1) *?P(C1) ) > log(?P(X|C0) *?P(C0) ), 即 P(C1|X) >?P(C0|X),可得測(cè)試文本{'book', 'campus', 'study'}屬于類別 1。
實(shí)現(xiàn)步驟:自己動(dòng)手實(shí)現(xiàn)樸素貝葉斯
本節(jié)將介紹使用樸素貝葉斯進(jìn)行文本分類的實(shí)現(xiàn)過程。自己動(dòng)手實(shí)現(xiàn)樸素貝葉斯主要從三個(gè)方面展開,分別是從文本到詞向量,從詞向量到先驗(yàn)概率和條件概率,以及推斷測(cè)試文本的類別。
清單 1. 從文本到詞向量
| 1 2 3 4 5 6 | def word2vector(words, article): ????article2Vector = zeros(len(words)) ????for word in article: ????????if word in words: ????????????article2Vector[words.index(word)] += 1 ????return article2Vector |
清單 1 完成了將文本表示成詞向量的過程。words 是統(tǒng)計(jì)出的所有文本中的詞列表,即所有文本中不重復(fù)的詞列表,如清單 2 所示,計(jì)算 words 的過程用到了集合的并操作。對(duì)于文本 article 中的每個(gè)詞,如果詞在 words 列表中,就將詞向量中對(duì)應(yīng)下標(biāo)的元素加一。
清單 2. 從詞向量到先驗(yàn)概率
| 1 2 3 4 5 6 7 8 9 10 11 | def calcProb(articles, categories): ????p1 = sum(array(categories)) / len(categories) ????p0 = 1 - p1 ????words = set([]) ????for i in range(len(articles)): ????????words = words | set(articles[i]) ????words = list(words) ????p0words, p1words = calcWordsProbInCateg(words, articles, categories) ????return p0,p1,p0words,p1words,words |
清單 2 完成了從詞向量中計(jì)算先驗(yàn)概率 p0 和 p1 的過程。p1 的計(jì)算過程為首先統(tǒng)計(jì)類別列表 categories 中所有類別為 1 的向量集合大小,然后對(duì)其除以所有文本總數(shù)。P0 由 1 減去 p1 即可得到, 這是因?yàn)?P0 + P1 = 1。
清單 3. 從詞向量到條件概率
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | def calcWordsProbInCateg(words, articles, categories): ????articlesMatrix = [] ????for article in articles: ????????article2Vector = word2vector(words, article) ????????articlesMatrix.append(article2Vector) ????sumWords0 = 2 ????sumWords1 = 2 ????p0words = ones(len(words)) ????p1words = ones(len(words)) ????for i in range(len(articles)): ????????if categories[i] == 0: ????????????p0words += articlesMatrix[i] ????????????sumWords0 += sum(articlesMatrix[i]) ????????else: ????????????p1words += articlesMatrix[i] ????????????sumWords1 += sum(articlesMatrix[i]) ????p0words = p0words / sumWords0 ????p1words = p1words / sumWords1 ????return p0words, p1words |
清單 3 完成了從詞向量中計(jì)算條件概率 p0words 和 p1words 的過程。p0words 表示類別 0 中所有詞出現(xiàn)的概率向量,p1words 表示類別 1 中所有詞出現(xiàn)的概率向量。代碼一開始先將文本列表 articles 轉(zhuǎn)換成文本詞概率矩陣 articelsMatrix, 然后對(duì)每篇文本,對(duì)該文本所屬的類別,統(tǒng)計(jì)每個(gè)詞的出現(xiàn)總次數(shù)和所有詞的出現(xiàn)總次數(shù)。最后對(duì)每個(gè)類別,用每個(gè)詞在該類別中的出現(xiàn)總次數(shù)除以所有詞的出現(xiàn)總次數(shù),得到類別 0 中所有詞出現(xiàn)的概率向量和類別 1 中所有詞出現(xiàn)的概率向量。注意此處利用拉普拉斯平滑避免了概率為 0 的出現(xiàn),方便后續(xù)概率計(jì)算。
清單 4. 推斷測(cè)試文本的類別
| 1 2 3 4 5 6 7 8 9 10 11 12 | def inferCategory(words, testArticle, p0, p1, p0words, p1words): ????category = 0 ????testArticle2Vector = word2vector(words, testArticle) ????p0temp = sum(log(p0words) * testArticle2Vector) ????p1temp = sum(log(p1words) * testArticle2Vector) ????pwords0 = p0temp + log(p0) ????pwords1 = p1temp + log(p1) ????if pwords0 < pwords1: ????????category = 1 ????return category |
清單 4 用 inferCategory 函數(shù)推斷測(cè)試文本 testArticle 所屬的類別。首先,將 testArticle 轉(zhuǎn)化成詞向量 testArticle2Vector,然后利用貝葉斯公式分別計(jì)算 testArticle 屬于類別 0 的概率和 testArticle 屬于類別 1 的概率,取概率值大的類別作為 testArticle 所屬的類別。注意此處利用了 log 函數(shù)避免了連乘造成的結(jié)果幾乎等于 0 的后果。
代碼下載 (code downloads)
本文所有樸素貝葉斯實(shí)現(xiàn)代碼可在文末下載。
本文數(shù)據(jù)集簡(jiǎn)介
圖 2. 數(shù)據(jù)集樣例
訓(xùn)練數(shù)據(jù)集有 6 條文本數(shù)據(jù),分為教育類和非教育類,第 1,3,5 條文本數(shù)據(jù)['book', 'student', 'is', 'campus', 'classes', 'study']、['children', 'library', 'are', 'homework', 'we', 'learn', 'cafeteria']、['student', 'library', 'teach', 'lecture', 'time', 'math','art', 'biology', 'geography'],代表教育類的文本;第 2,4,6 條文本數(shù)據(jù)['others', 'game', 'sky', 'cat', 'park', 'dog']、['nothing', 'gone', 'from', 'good', 'cookie']、['bread', 'milk', 'water', 'you', 'we', 'yes'],代表非教育類的文本。教育類用類別 1 表示,非教育類用類別 0 表示。
應(yīng)用示例: 應(yīng)用實(shí)現(xiàn)的樸素貝葉斯解決實(shí)際問題
清單 5. 用樸素貝葉斯解決實(shí)際問題
| 1 2 3 4 5 6 7 8 9 | if __name__ == '__main__': ?articles, categories = loadDataSet() ?p0, p1, p0words, p1words, words = calcProb(articles, categories) ?testArticle1 = ['student', 'study', 'campus'] ?category1 = inferCategory(words, testArticle1, p0, p1, p0words, p1words) ?print("test article:", testArticle1, ",category is: ", category1) ?testArticle2 = ['other', 'no'] ?category2 = inferCategory(words, testArticle2, p0, p1, p0words, p1words) ????print("test article:", testArticle2, ",category is: ", category2) |
測(cè)試數(shù)據(jù)集有 2 條文本數(shù)據(jù),分別為['student', 'study', 'campus']和['other', 'no']。清單 5 首先調(diào)用 loadDataSet 函數(shù)加載文本列表和類別列表,接著調(diào)用 calcProb 函數(shù)計(jì)算類別 0 概率、類別 1 概率、類別 0 中所有詞的概率向量、類別 1 中所有詞的概率向量,然后調(diào)用 inferCategory 函數(shù)計(jì)算測(cè)試文本 testArticle 所屬的類別。
運(yùn)行結(jié)果如下:
test article: ['student', 'study', 'campus'] ,category is: 1
test article: ['other', 'no'] ,category is: 0
可以看出測(cè)試文本['student', 'study', 'campus']屬于類別 1,即教育類;測(cè)試文本['other', 'no']屬于類別 0,即非教育類。
總結(jié)
本文首先介紹了樸素貝葉斯的應(yīng)用場(chǎng)景和優(yōu)缺點(diǎn),接著詳細(xì)介紹了樸素貝葉斯的原理,然后介紹了如何用樸素貝葉斯進(jìn)行文本分類,并通過代碼樣例詳細(xì)介紹如何自己動(dòng)手實(shí)現(xiàn)樸素貝葉斯。最后,用教育類數(shù)據(jù)展示了如何應(yīng)用樸素貝葉斯模型解決實(shí)際問題。需要注意的是樸素貝葉斯模型認(rèn)為屬性之間是條件獨(dú)立的,這也就是樸素這個(gè)詞的來源,表達(dá)了簡(jiǎn)化的含義。但是實(shí)際場(chǎng)景中,屬性之間是條件獨(dú)立的這個(gè)假設(shè)不一定總是成立的。這就引申出了半樸素貝葉斯,即放松了屬性之間條件獨(dú)立這一假設(shè)。半樸素貝葉斯考慮了一部分屬性之間的相互依賴關(guān)系。由于篇幅有限,對(duì)于半樸素貝葉斯感興趣的話可以參考文末列出的第三個(gè)參考資源(周志華著《機(jī)器學(xué)習(xí)》)了解詳細(xì)原理。
參考資源
本文用到的參考文獻(xiàn)如下:
- 參考 Peter Harrington 著《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》,了解樸素貝葉斯模型基本原理。
- 參考李航著《統(tǒng)計(jì)學(xué)習(xí)方法》,了解拉普拉斯平滑原理。
- 參考周志華著《機(jī)器學(xué)習(xí)》,了解半樸素貝葉斯原理。
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/8926997.html
總結(jié)
以上是生活随笔為你收集整理的机器学习系列之手把手教你实现一个 naiveBayes的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习之手把手实现,第 2 部分 频
- 下一篇: 机器学习系列之手把手教你实现一个决策树