貝葉斯統計都是以條件概率,聯合概率為基礎的,所以我們從概率,條件概率,聯合概率開始,然后到貝葉斯定理,最后講一個貝葉斯的應用--垃圾郵件的過濾
概率:事件發生的可能性,比如拋一枚硬幣,正面向上的可能性有50%,擲色子點數為6的可能性為1/6。我們用符號表示為P(A)
條件概率:滿足某些條件下事件發生的可能性,比如求一個人在買了褲子的前提下再買衣服的概率,我們用符號表示為P(B|A),即事件A發生下B發生的概率
聯合概率:多個事件同時發生的可能性,比如拋硬幣兩次都朝上的概率P(AB) = P(A)P(B),前提是事件是相互獨立的互不影響,如果不獨立則聯合概率為P(AB) = P(A)P(B|A)
當P(B) = P(B|A)時表示事件是相互獨立的。
貝葉斯定理
利用聯合概率我們可以計算出條件概率,比如知道了P(AB)和P(A)我們想知道事件A發生的前提下B發生的概率則P(B|A) = P(AB) / P(A),可如果我們想計算P(A|B)的概率呢?
不巧的是P(A|B)並不等於P(B|A)。
我們從聯合概率知道概率乘積的順序可以交換即P(AB) = P(BA),然后將兩個概率展開P(A)P(B|A) = P(B)P(A|B),我們可以清楚的看到我們想要的P(A|B)就在其中
P(A|B) = P(B|A)P(A) / P(B),這就是貝葉斯定理。
P(A)就是先驗概率,我們在計算前假設的某個概率,比如拋硬幣正面向上的概率為50%
P(B|A)就是后驗概率,這是我們看到數據的后計算得到的
P(A|B)就是先驗概率和后驗概率計算得到的,稱似然度
P(B) 在任何情況下該事件發生的概率,稱標准化常量 P(B) = P(B1)P(B1|A1) + P(B2)P(B2|A2).....
貝葉斯估計
用極大似然估計可能會出現所要估計的概率值為0的情況,這會影響到后驗概率的計算結果,使得分類有偏差。我們使用貝葉斯估計,即添加一個λ修正參數
貝葉斯公式 P(B|A) = (P(AB) + λ) / (P(A) + Sλ) λ >= 0 S表示隨機變量各個取值的頻數
垃圾郵件的過濾
垃圾郵件就是包含了某些詞語,我們只有找到這些詞,並計算出在這些詞語出現的前提下是垃圾郵件的概率和不是垃圾郵件的概率,比較概率大小即
p(垃圾郵件 | w1,w2,w3,w4,w5...) 和 p(非垃圾郵件 | w1,w2,w3,w4,w5...)的大小。無法直接知道這個條件概率,所以貝葉斯又上場了,先寫出聯合概率,然后展開得
p(垃圾郵件 | w1,w2,w3,w4,w5...)p(w1,w2,w3,w4,w5...) = p(w1,w2,w3,w4,w5...| 垃圾郵件) p(垃圾郵件),再化簡得
p(垃圾郵件 | w1,w2,w3,w4,w5...) = p(w1,w2,w3,w4,w5...| 垃圾郵件) p(垃圾郵件) / p(w1,w2,w3,w4,w5...)
p(非垃圾郵件 | w1,w2,w3,w4,w5...) = p(w1,w2,w3,w4,w5...| 非垃圾郵件) p(非垃圾郵件) / p(w1,w2,w3,w4,w5...)
p(垃圾郵件) 就是先驗概率0.5, p(w1,w2,w3,w4,w5...| 垃圾郵件) 就是后驗概率,是根據所給數據計算的,因為兩個概率都除以了p(w1,w2,w3,w4,w5...),所以消去最終得到以下式子:
p(垃圾郵件 | w1,w2,w3,w4,w5...) = p(w1,w2,w3,w4,w5...| 垃圾郵件) p(垃圾郵件)
p(非垃圾郵件 | w1,w2,w3,w4,w5...) = p(w1,w2,w3,w4,w5...| 非垃圾郵件) p(非垃圾郵件)
import numpy as np import re pattern = re.compile(r'\w+') class bayes(object): def __init__(self,wordList): self.wordsList = wordList self.hamCnt = 0 self.spamCnt = 0 self.pham = np.ones(len(self.wordsList)) self.pspan = np.ones(len(self.wordsList)) self.phamWordCnt = 2 self.pspanWordCnt = 2 def word_to_vector(self, word): tempVector = np.zeros(len(self.wordsList)) for line in pattern.findall(word): if line in self.wordsList: tempVector[self.wordsList.index(line)] += 1.0 return tempVector def Set_tran_data(self, word, Flag): Vector = self.word_to_vector(word.strip()) if Flag: self.pham += Vector self.phamWordCnt += sum(Vector) self.hamCnt += 1.0 else: self.pspan += Vector self.pspanWordCnt += sum(Vector) self.spamCnt += 1.0 def classifiy(self, word): Vector = self.word_to_vector(word) pA = self.hamCnt / (self.hamCnt + self.spamCnt) pB = self.spamCnt / (self.hamCnt + self.spamCnt) pAnum = sum(np.log(self.pham / self.phamWordCnt)*Vector) pBnum = sum(np.log(self.pspan / self.pspanWordCnt)*Vector) if np.log(pA) + pAnum > np.log(pB) + pBnum: return 1 else: return -1 if __name__ == "__main__": hamlist = [item for i in range(1, 20) for item in open(r'C:\Users\Administrator\Desktop\machinelearninginaction\Ch04\email\ham\%s.txt'% i, 'r').readlines() ] spamlist = [item for i in range(1, 20) for item in open(r'C:\Users\Administrator\Desktop\machinelearninginaction\Ch04\email\spam\%s.txt'% i, 'r').readlines()] wordList1 = [word for line in hamlist for word in pattern.findall(line) if len(word) > 2] wordList2 = [word for line in spamlist for word in pattern.findall(line) if len(word) > 2] wordList1.extend(wordList2) temp = bayes(list(set(wordList1))) tranhamlist = [open(r'C:\Users\Administrator\Desktop\machinelearninginaction\Ch04\email\ham\%s.txt'% i, 'r').read() for i in range(1, 20)] transpamlist = [open(r'C:\Users\Administrator\Desktop\machinelearninginaction\Ch04\email\spam\%s.txt'% i, 'r').read() for i in range(1, 20)] for line in tranhamlist: temp.Set_tran_data(line, True) for line in transpamlist: temp.Set_tran_data(line, False) testlist = [open(r'C:\Users\Administrator\Desktop\machinelearninginaction\Ch04\email\ham\%s.txt'% i, 'r').read() for i in range(21, 26)] for line in testlist: print temp.classifiy(line)
數據是機器學習實戰第4章