贝叶斯统计都是以条件概率,联合概率为基础的,所以我们从概率,条件概率,联合概率开始,然后到贝叶斯定理,最后讲一个贝叶斯的应用--垃圾邮件的过滤
概率:事件发生的可能性,比如抛一枚硬币,正面向上的可能性有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章