機器學習實戰三(Naive Bayes)
機器學習實戰三(Naive Bayes)
前兩章的兩種分類算法,是確定的分類器,但是有時會產生一些錯誤的分類結果,這時可以要求分類器給出一個最優的猜測結果,估計概率。樸素貝葉斯就是其中一種。
學過概率論的人對於貝葉斯這個名字應該是相當的熟悉,在學條件概率的時候,貝葉斯公式可謂是一針見血。這裏的“樸素貝葉斯”,是因為在計算貝葉斯概率的時候只考慮最原始、最簡單的假設。
Naive Bayes(樸素貝葉斯)
優點:在數據較少的情況下依然有效,可處理多類別問題。
缺點:對於輸入數據的格式要求嚴格。
原理:樸素貝葉斯的原理十分簡單,如果假定數據有兩類,分別計算待分類數據屬於這兩類的概率,p1和p2,如果
- p1 > p2, 則屬於類別1
- p1 < p2, 則屬於類別2
略微提及一下貝葉斯公式:
\(p\left( c|x\right) =\dfrac {p\left( x|c\right) p\left( c\right) }{p\left( x\right) }\)。
這個公式的強大之處在於,可以將先驗概率和後驗概率進行轉換,看起來簡單,但是使用的時候的確很強大,而且計算很便捷。
先來看樸素貝葉斯的兩個基本假設:
- 文本之間相互獨立
- 每個特征同等重要
根據這兩個基本假設,就可以著手構造分類器了。
首先要將文本轉換到向量空間,思路比較清晰。
import feedparser import numpy as np import operator import random import re # 加載測試數據 def loadDataSet(): postingList = [[‘my‘, ‘dog‘, ‘has‘, ‘flea‘, ‘problems‘, ‘help‘, ‘please‘], [‘maybe‘, ‘not‘, ‘take‘, ‘him‘, ‘to‘, ‘dog‘, ‘park‘, ‘stupid‘], [‘my‘, ‘dalmation‘, ‘is‘, ‘so‘, ‘cute‘, ‘I‘, ‘love‘, ‘him‘], [‘stop‘, ‘posting‘, ‘stupid‘, ‘worthless‘, ‘garbage‘], [‘mr‘, ‘licks‘, ‘ate‘, ‘my‘, ‘steak‘, ‘how‘, ‘to‘, ‘stop‘, ‘him‘], [‘quit‘, ‘buying‘, ‘worthless‘, ‘dog‘, ‘food‘, ‘stupid‘]] classVec = [0, 1, 0, 1, 0, 1] return postingList, classVec # 創建詞匯表 def createVocabList(dataSet): vocabSet = set() for document in dataSet: vocabSet = vocabSet | set(document) return list(vocabSet) # 構造文檔向量 def setOfWord2Vec(vocabList, inputSet): returnVec = [0] * len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] = 1 else: print(‘the word: {} is not in my Vocabulary!‘.format(word)) return returnVec
下一步是訓練算法,從詞向量計算概率,但是這裏有幾個小技巧:
- 分母的初始值設置為2,避免分母為0的情況出現
- 由於特征之間獨立,在做乘法的時候有時會面臨小數位數過多的下溢出,這時可以將其轉化為對數形式,這是一種比較通常的解決思路
# 訓練函數 def trainNB0(trainMatrix, trainCategory): numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[0]) pAbusive = np.sum(trainCategory) / numTrainDocs p0Num = np.ones(numWords) p1Num = np.ones(numWords) p0Denom = 2.0 p1Denom = 2.0 for i in range(numTrainDocs): if trainCategory[i] == 1: p1Num += trainMatrix[i] p1Denom += np.sum(trainMatrix[i]) else: p0Num += trainMatrix[i] p0Denom += np.sum(trainMatrix[i]) p1Vect = np.log(p1Num / p1Denom) p0Vect = np.log(p0Num / p0Denom) return p0Vect, p1Vect, pAbusive
這種分類方式稱為詞集模型
,只考慮某個詞出不出現,如果一種詞出現不止一次,那麽統計出現的次數無疑會包含更多信息,這種方法稱為詞袋模型
。
# 詞袋模型
def bagofWords2VecMN(vocabList, inputSet):
returnVec = [0] * len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
return returnVec
變化其實並不大。
現在就可以執行分類了,這一步完全就是條件概率公式的應用,註意對數可以將相乘轉換為相加。
# 執行分類
def classifyNB(vect2Classify, p0Vec, p1Vec, pClass1):
# 對數相乘轉換為相加
p1 = np.sum(vect2Classify * p1Vec) + np.log(pClass1)
p0 = np.sum(vect2Classify * p0Vec) + np.log(1.0 - pClass1)
if p1 > p0:
return 1
else:
return 0
原書中提供的兩個關於樸素貝葉斯應用的例子,一個是過濾垃圾郵件,另一個是從個人廣告中獲取區域傾向,都是很有趣的例子,代碼可以在我的Github中找到。
例子中有幾點需要註意:
1.留存交叉驗證,其實就是從樣本集中隨機選取一部分作為訓練集,剩下的作為預測集來檢驗精度。
2.高頻詞通常移除會帶來更好的分類效果。
3.停用詞也可以選擇剔除。
Naive Bayes存在的問題:
通過降級特征之間的條件獨立性假設降低對數據量的需求,有時這個假設會顯得過於簡單,但是樸素貝葉斯仍是一種有效的分類器,而且使用概率要比使用硬規則更為有效。
Next: 初次接觸優化算法和Logistic回歸
總結:概率在機器學習中的應用是廣泛的,這是因為很多時候我們對於事物的具體發生機理並不了解,這個時候就需要借助概率論和統計的力量。
References:https://github.com/plantree/Machine-Learing-In-Action/tree/master/chapter4
機器學習實戰三(Naive Bayes)