朴素贝叶斯(naive bayes)
樸素貝葉斯(naive bayes)
標簽: Python 機器學習
主要參考資料:《機器學習實戰》《統計學習方法》
1.樸素貝葉斯分類原理
樸素貝葉斯法是基于貝葉斯定理和特征條件獨立假設(稱為樸素的原因)的分類方法。先看看維基百科中貝葉斯定理的描寫敘述:
貝葉斯定理(維基百科)
通常,事件A在事件B(發生)的條件下的概率。與事件B在事件A的條件下的概率是不一樣的。然而,這兩者是有確定的關系,貝葉斯定理就是這樣的關系的陳述。
公式描寫敘述例如以下:
當中P(A|B)是在B發生的情況下A發生的可能性。
在機器學習中,經常常使用事件A表示屬于某個類別,事件B表示特征條件的集合。下面圖作為樣例解說:
圖中共同擁有兩類點。記為c1和c2。p(ci|x,y)表示點(x,y)為類ci的概率。那么依據貝葉斯公式,能夠進行例如以下分類:
- 假設P(c1|x,y)>P(c2|x,y)。則斷定該點屬于c1
- 假設P(c1|x,y)<P(c2|x,y)。則斷定該點屬于c2
假設用P(x,y|ci)表示類ci中點(x,y)的概率(分布)。則:
又由于假設了特征條件獨立。即x和y之間沒有不論什么的關系。則:
P(ci|x,y)=P(x|ci)P(y|ci)P(ci)P(x,y)
分母同樣,僅僅須要比較分子就可以。樸素貝葉斯算法訓練的目的就是得到訓練集中P(x|ci)P(y|ci)P(ci),即不同獨立特征的條件概率。
2.樸素貝葉斯實現
2.1準備數據
由于是簡單的演示樣例,直接創建訓練集和類標簽向量:
# 訓練集:留言板的中的留言 def create_data_set(): 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] #1表示侮辱性語句, 0表示文明用語return postingList,classVec當前數據集中的數據是單詞,我們要依據單詞出現的頻率預計出條件概率。就必須知道每一個單詞出現的頻數。而統計單詞頻數,首先得創建單詞表,即全部單詞僅僅出現一次的列表(集合):
#創建單詞表 def create_vocablist(dataSet): vocabSet = set([]) #create empty setfor document in dataSet:vocabSet = vocabSet | set(document) #取并集return list(vocabSet)有了單詞表就能夠將語句轉化為頻率矢量,首先將單詞表全部單詞的頻率初始化為0。然后遍歷每一條語句。將出現的單詞頻率置為1(0表示未出現該單詞,1表示出現該單詞):
#將輸入語句轉化為單詞頻率向量,表示單詞表中的哪些單詞出現過 def setOfWords2Vec(vocabList, inputSet):returnVec = [0]*len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] = 1else: print "the word: %s is not in my Vocabulary!" % wordreturn returnVec利用上面生成的數據集生成一個單詞表,結果例如以下:
將語句”I buying cute dog”轉化為向量例如以下:
2.2訓練算法
先看看訓練的目標參數:P(w1|ci),P(w2|ci),...,P(wm|ci)P(ci),當中wi表示某一個單詞,由于一條語句是由若干單詞組成。且我們假設每一個單詞出現的事件是獨立的。故類ci有語句w的概率P(w??|ci)=P(w1|ci),P(w2|ci),...,P(wm|ci)。
訓練函數傳入的參數有兩個。各自是語句集合轉化的單詞表向量集合和類標簽向量。首先依據類標簽列表能夠計算出侮辱性語句和非侮辱性語句的頻率。然后再計算各個特征的條件概率。
計算特征的條件概率時使用了numpy中的矢量運算。極大的簡化了程序的編寫。先定義2個空的單詞表矢量,用來統計侮辱性單詞和非侮辱性單詞的頻數,再定義2個浮點型變量。用來統計侮辱性單詞和非侮辱性單詞的總數。遍歷單詞表向量集合。依據每一個向量的類別,統計侮辱性和非侮辱性單詞的頻數與總數。最后,將頻數除以總數,就能夠得到侮辱性或非侮辱性條件下某單詞的出現的概率。
#樸素貝葉斯訓練函數,輸入為全部文檔的單詞頻率向量集合。類標簽向量 def trainNB(trainMatrix,trainCategory):numTrainDocs = len(trainMatrix) #文檔數量numWords = len(trainMatrix[0]) #單詞表長度pAbusive = sum(trainCategory)/float(numTrainDocs) #侮辱性詞語的頻率p0Num = zeros(numWords); p1Num = zeros(numWords) #分子初始化為0p0Denom = 0.0; p1Denom = 0.0 #分母初始化為0for i in range(numTrainDocs):if trainCategory[i] == 1: #假設是侮辱性語句p1Num += trainMatrix[i] #矢量相加,將侮辱性語句中出現的詞語頻率全部加1p1Denom += sum(trainMatrix[i]) #屈辱性詞語的總量也添加else:p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = p1Num/p1Denom #對每一個元素做除法p0Vect = p0Num/p0Denomreturn p0Vect,p1Vect,pAbusive #返回全部詞語非侮辱性詞語中的頻率。全部詞語在侮辱性詞語中的頻率。侮辱性語句的頻率可是這段程序有兩個問題,問題一為可能發生下溢出,問題二為某語句的某個單詞在侮辱性或非侮辱性集合中的頻率為0,這會導致連乘的積為0.
首先解決這個問題一:
頻率都是非常小的小數,這些小數連乘的結果終于也是非常小非常小的小數,在計算機中會發生下溢出或者為0,總之都不是正確的結果。
較為常見的解決方法是使用對數。將連乘變為連加。對應的程序改動例如以下:
p1Vect = log(p1Num/p1Denom) #變為對數,防止下溢出;對每一個元素做除法 p0Vect = log(p0Num/p0Denom)然后解決這個問題二:
能夠通過分子全部初始化為1,分母初始化為2解決該問題,這樣的方法在統計學中叫做貝葉斯預計。
條件概率P(wj|ci)的極大似然預計為:
我們原先就是依照上面的公式計算P(wj|ci),可是該公式可能出現所要預計的概率值為0的情況,所以給分子分母添加一項,稱為條件概率的貝葉斯預計,詳細例如以下:
P(wj|ci)=∑I(wj,ci)+λI(ci)+Sjλ
當中λ>0,Sj表示wj能夠取得不同值的個數。當λ=1時,稱為拉普拉斯平滑。
在我們所討論的問題中。wj表示某個單詞是否出現,僅僅有0和1兩個值。故Sj=2。所以初始化時分子為1。分母為2,再依據遍歷結果添加分子和分母的值。對應的程序改動例如以下:
p0Num = ones(numWords); p1Num = ones(numWords) #分子初始化為1 p0Denom = 2.0; p1Denom = 2.0 #分母初始化為22.3測試算法
依據下面準則編寫分類函數:
- 假設P(c0|x,y)>P(c1|x,y),則斷定為非侮辱性語句
- 假設P(c0|x,y)<P(c1|x,y),則斷定為侮辱性語句
然后編寫測試函數,進行測試,須要注意的是python中的列表不提供矢量運算,要想進行矢量運算,就要將列表轉化為numpy中的array或者mat。
def testingNB():listOPosts,listClasses = create_data_set()myVocabList = create_vocablist(listOPosts)trainMat=[]for postinDoc in listOPosts:trainMat.append(setOfWords2Vec(myVocabList, postinDoc))p0V,p1V,pAb = trainNB(array(trainMat),array(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)執行結果例如以下:
3.總結
- 源代碼在我的GitHub中,MachineLearningAction倉庫里面有常見的機器學習算法處理常見數據集的各種實例,歡迎訪問
- 樸素貝葉斯算法核心就兩個:
- 貝葉斯定理
- 樸素:假設各個特征之間是獨立的
- 僅僅要牢記樸素貝葉斯的核心以及公式,那么編敲代碼就比較easy
- 樸素貝葉斯經常常使用于文本分類。然而該方法對于英文等語言非常好用。對中文就不是非常好,由于中文是字組成詞。對于長句子要進行“分詞”操作,比方“黃金”和“金黃”的字全然一樣,可是意思截然不同
- 樸素貝葉斯有非常多的改進方法,比方說用詞袋模型取代詞集模型,移除停用詞
總結
以上是生活随笔為你收集整理的朴素贝叶斯(naive bayes)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 期初付年金(annuity-due)
- 下一篇: Python大数据:jieba分词,词频