我眼中的樸素貝葉斯
既然要用到貝葉斯公式,首先給出貝葉斯公式
P(A|B)=P(B|A)P(A)/P(B)
數學含義:
P(A)是先驗概率,可以通過計算獲得
P(B|A)是條件概率,意識是在A發生的條件下B發生的概率
P(B)是用於歸一化的“證據”因子,對於給定的樣本B,P(B)與類標記無關
P(A|B)就是後驗概率,也是需要我們根據P(B|A),P(A)求的
這個準則有什麽用呢?接下來給一個例子
使用樸素貝葉斯進行文檔分類
目標是實現自動檢測輸入的文檔是侮辱性詞還是非侮辱性詞
首先用圖來描繪整個過程,和對貝葉斯公式的簡單運用
創建訓練集:
假如你有6個文檔,並且知道他們個屬於什麽類型(侮辱/一般)詞
0表示一般詞,1表示侮辱詞,首先把這些詞匯總在一起構建一個無重復的詞庫
有了詞庫以後我們要制作訓練集,就要把6六個文檔用詞向量的形式比表示,怎麽做呢?,就用到了無重復的詞庫,把6個文檔分別與詞庫比較,有就標記為1,無則為0,就得到只有01的矩陣,它的列長與詞庫的長度相同
這就是訓練集,接下來訓練
訓練過程:
詞矩陣:[Wi]
c1表示辱罵型詞,c0表示一般詞
訓練的過程是要求出每一詞的條件分布P([wi]|c1),P([wi]|c0)
P([wi]|c1):已知詞wi是辱罵性詞的條件下,它的概率是多少,概率越高表示它出現的次數越多,表示它越可能是辱罵性詞
P([wi]|c0):相同可知
要求這兩個條件概率,首先要把訓練樣本根據已知標簽分成兩類c1,c0,然後再求每一詞出現的概率,所以最後得到兩個條件概率矩陣。
得到兩個矩陣後,相當於訓練好的模型,但怎麽實現分類呢?在回顧一下貝葉斯準則
P(cj|[wi])=p([Wi]|c1)*P(c1)/P([wi])
P(cj|[wi]):含義是已知詞wi,則它是(侮辱性詞/非侮辱性)的概率是多少,這就是我們要求的,求得這個概率就能確定它的分類
[Wi]是詞矩陣,且假設每一個詞都是相互獨立,這樣就簡化了問題,這也是為什麽叫樸素貝葉斯。
p([Wi]|c1) = p(W1|c1)*p(W2|c1)*....p(Wn|c1)
p([Wi]|c0) = p(W1|c0)*p(W2|c0)*....p(Wn|c0)
所以
P(c1|[wi]) = p(W1|c1)*p(W2|c1)*....p(Wn|c1)P(c1)
P(c0|[wi]) = p(W1|c0)*p(W2|c0)*....p(Wn|c0)P(c0)
比較P(c1|[wi]),P(c0|[wi])大小
if P(c1|[wi])>P(c0|[wi])
說明是侮辱性詞的概率大
else
是一般性詞
測試:
假如輸入一個不知道類型的文檔,根據上面的詞庫建立它是詞向量,分別與上面的兩個條件概率向量相乘,計算條件貝葉斯概率即可
代碼:
#coding=utf-8 from numpy import * 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‘]] #1代表侮辱性文字,0代表正常言論 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 setOfWords2Vec(vocabList,inputSet): #構建一個長度和vocabList一樣的零向量 returnVec =[0]*len(vocabList) for word in inputSet: if word in vocabList: #如果這個詞在詞表中有,則詞向量中相應位置值設為1 #vocabList.index(word) 返回的是詞word在vocabList中的位置下標 returnVec[vocabList.index(word)] = 1 else: print ("the word :%s is not in my Vocabulary" %word) return returnVec #樸素貝葉斯分類器訓練trainMaxtrix訓練矩陣,trainCategory標簽 def trainNB0(trainMaxtrix,trainCategory): #行數 numTrainDocs = len(trainMaxtrix) #列數 numWords = len(trainMaxtrix[0]) #侮辱性文檔所占概率P(c1) pAbusive = sum(trainCategory)/float(numTrainDocs) #為了防止其中一個概率為零,導致乘積為零,初始化分子為1,分母為2 p0Num = ones(numWords) p1Num = ones(numWords) p0Denom = 2.0 p1Denom = 2.0 #遍歷文檔,每一行表示一個文檔 for i in range(numTrainDocs): #1表示正常言論文檔,否則辱罵言論文檔 if trainCategory[i] == 1: #統計每個詞出現的次數 p1Num += trainMaxtrix[i] #辱罵詞的總個數 p1Denom +=sum(trainMaxtrix[i]) else: p0Num += trainMaxtrix[i] p0Denom +=sum(trainMaxtrix[i]) #p([Wi]|c1) = p(W1|c1)*p(W2|c1)*....p(Wn|c1) 因為相互獨立 #p1Vect = p1Num/p1Denom,為了防止許多小數相乘下溢,於是log一下 p1Vect = log(p1Num/p1Denom) #p([Wi]|c0) = p(W1|c0)*p(W2|c0)*....p(Wn|c0) #p0Vect = p0Num/p0Denom p0Vect = log(p0Num/p0Denom) return p0Vect,p1Vect,pAbusive #樸素貝葉斯分類器函數 def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1): #p([Wi]|c1)*P(c1) = P(c1|[wi])*P(w) 根據貝葉斯公式 #P(c1|[wi])意思是已知詞wi,則它是(侮辱性詞/非侮辱性)的概率是多少 p1 = sum(vec2Classify * p1Vec) + log(pClass1) #p([Wi]|c0)*P(c0) = P(c0|[wi])*P(w) p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1) if p1 > p0: return 1; else: return 0; def testingNB(): listOPosts,listClasses = loadDataSet() myVocabList = createVocabList(listOPosts) print("myVocabList",myVocabList) trainMat = [] #把文檔轉換成詞向量,生成一個二維向量矩陣trainMat for postinDoc in listOPosts: trainMat.append(setOfWords2Vec(myVocabList,postinDoc)) print("trainMat",trainMat) p0V,p1V,pAb = trainNB0(trainMat,listClasses) testEntry = [‘love‘,‘my‘,‘dalmation‘] thisDoc = array(setOfWords2Vec(myVocabList,testEntry)) print(testEntry,‘classified as‘,classifyNB(thisDoc,p0V,p1V,pAb)) testEntry = [‘stupid‘,‘garbage‘] thisDoc = array(setOfWords2Vec(myVocabList,testEntry)) print(testEntry,‘classified as‘,classifyNB(thisDoc,p0V,p1V,pAb))
代碼來至機器學習實戰,我做了詳細的註釋,結合上面的圖過程可以理解
主要還幫助理解的貝葉斯公式到底是怎麽實現分類的。
我眼中的樸素貝葉斯