基于概率的分類方法:樸素貝葉斯
樸素貝葉斯是貝葉斯決策理論的一部分,所以在講解樸素貝葉斯之前我們先快速簡單了解一下貝葉斯決策理論知識。
貝葉斯決策理論的核心思想:選擇具有最高概率的決策。比如我們畢業選擇就業方向,選擇C++方向的概率為0.3,選擇java的概率為0.2,選擇機器學習的概率為0.5。那么我們就把這樣的一位畢業生就業方向歸類為機器學習方向。
條件概率
什么是條件概率?事件A在另一個事件B已知發生條件下的發生概率,記為P(A|B),讀作“在B條件下A的概率”。
例子1:有兩個骰子,一個骰子扔出點數是6,那么扔另一個骰子時,求出兩個骰子點數之和大于等于10的概率。
例子2:有三個箱子編號為1,2,3。1號箱子有1個紅球4個白球,2號箱子有2個紅球3個白球,3號箱子有3個紅球。從三個箱子中任取一箱,從中任意摸出一個球,求取得紅球的概率。
另一種有效計算條件概率的方法就是貝葉斯準則。貝葉斯準則告訴我們如何交換條件概率中的條件和結果,即如果已知P(x|c),要求P(c|x) , 此時我們可以使用這樣的計算方法:P(c|x)*P(x)=P(x|c)*P(c)。
到目前為止,我們基本了解了貝葉斯決策理論和條件概率,我們就開始學習編寫代碼,用Python語言來試著實現樸素貝葉斯分類器吧。
以留言板為例,為了不影響社區的發展,我們要屏蔽侮辱性的言論,所以要構建一個快速過濾器,如果某條留言使用了負面或者侮辱性的詞語,就將這條留言標識為內容不當。過濾這類內容是很多網站的基本需求。這里,我們就將言論歸為侮辱類和非侮辱類,分別用1和0來表示。
1 # coding : utf-8 2 from numpy import * 3 4 def loadDataSet(): 5 postingList = [['my', 'dog', 'has', 'flea', / 6 'PRoblems', 'help', 'please'], 7 ['maybe', 'not', 'take', 'him', / 8 'to', 'dog', 'park', 'stupid'], 9 ['my' ,'dalmation', 'is', 'so', 'cute', /10 'I', 'love', 'him'],11 ['stop', 'posting', 'stupid', 'worthless', 'garbage'],12 ['mr', 'licks', 'ate', 'my', 'steak', 'how' /13 'to', 'stop', 'him'],14 ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']15 ]16 classVec = [0,1,0,1,0,1]17 return postingList, classVec18 19 def createVocabList(dataSet):20 vocabSet = set([])21 for doc in dataSet:22 vocabSet = vocabSet | set(doc)23 return list(vocabSet)24 25 def setOfWord2Vec(vocabList, inputSet):26 returnVec = [0]*len(vocabList)27 for word in inputSet:28 if word in vocabList:29 returnVec[vocabList.index(word)] = 130 else:31 print "the word: %s is not in my Vocabulary!" % word32 return returnVec 33
第一個函數loadDataSet()創建了一些實驗樣本。該函數返回的第一個變量是進行詞條切分后的文檔集合,這些文檔來自對狗狗的留言板。第二個變量是一個類別標簽的集合。這里有兩類,分別是侮辱性和非侮辱性。
下一個函數createVocabList()會創建一個包含在所有文檔中出現的不重復詞的列表,使用了set數據類型。操作符“|”用于求兩個集合的并集。
第三個函數的輸入參數為詞匯列表和某個文檔,輸出的是文檔向量,向量的每一個元素為1或者0,分別表示詞匯表中的單詞在輸入文檔中是否出現過。
接下來我們看看執行這個函數塊的效果是怎么樣的。
1 # coding : utf-82 import bayes3 from numpy import *4 5 list2Posts, listClasses = bayes.loadDataSet()6 myVocabList = bayes.createVocabList(list2Posts)7 print myVocabList, len(myVocabList)8 print bayes.setOfWord2Vec(myVocabList, list2Posts[0])9 print bayes.setOfWord2Vec(myVocabList, list2Posts[3])

計算概率
1 def trainNBO(trainMatrix, trainCategory): 2 numTrainDocs = len(trainMatrix) 3 numWords = len(trainMatrix[0]) 4 pAbusive = sum(trainCategory)/float(numTrainDocs) 5 p0Num = zeros(numWords); p1Num = zeros(numWords) 6 p0Denom = p1Denom = 0.0 7 for i in range(numTrainDocs): 8 if trainCategory[i] == 1: 9 p1Num += trainMatrix[i]10 p1Denom += sum(trainMatrix[i])11 else :12 p0Num += trainMatrix[i]13 p0Denom += sum(trainMatrix[i])14 p1Vect = p1Num/p1Denom15 p0Vect = p0Num/p0Denom16 return p0Vect,p1Vect,pAbusive
萬事俱備,只欠東風。接下來,就是重要的樸素貝葉斯分類函數了。
1 def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1): 2 p1 = sum(vec2Classify * p1Vec) + log(pClass1) 3 p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1) 4 if p1 > p0: 5 return 1 6 else : 7 return 0 8 9 def testingNB():10 listOPosts,listClasses = loadDataSet()11 myVocabList = createVocabList(listOPosts)12 trainMat = []13 for postinDoc in listOPosts:14 trainMat.append(setOfWord2Vec(myVocabList,postinDoc))15 p0V,p1V,pAb = trainNBO(array(trainMat),array(listClasses))16 testEntry = ['love', 'my', 'dalmation']17 thisDoc = array(setOfWord2Vec(myVocabList, testEntry))18 print testEntry, 'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)19 testEntry = ['stupid', 'garbage']20 thisDoc = array(setOfWord2Vec(myVocabList, testEntry))21 print testEntry, 'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)
試試看我們的運算結果:

和我們期望的結果一樣,文檔單詞正確的進行了分類。
樸素貝葉斯算法總體來說,是比決策樹和KNN算法較復雜一些,代碼量也相對而言多一些。回想起大一時期青澀的我,沒有好好學習概率論,當時沒有對其引起重視,導致如今這個鳥樣。哎,只怪當時還年輕啊!條件概率部分有很多較復雜的概率公式還是很模糊,接下來會花一點時間在概率這方面。只要概率方面沒問題的話,相信讀懂以上這幾份代碼應該不成問題,classifyNB函數里就是在計算最終的概率。
加油吧,BaiYiShaoNian!
新聞熱點
疑難解答