目录
一、定义
贝叶斯方法
贝叶斯方法是以贝叶斯原理为基础,使用概率统计的知识对样本数据集进行分类。由于其有着坚实的数学基础,贝叶斯分类算法的误判率是很低的。贝叶斯方法的特点是结合先验概率和后验概率,即避免了只使用先验概率的主观偏见,也避免了单独使用样本信息的过拟合现象。贝叶斯分类算法在数据集较大的情况下表现出较高的准确率,同时算法本身也比较简单。
朴素贝叶斯算法
朴素贝叶斯算法(Naive Bayesian algorithm) 是应用最为广泛的分类算法之一。
朴素贝叶斯方法是在贝叶斯算法的基础上进行了相应的简化,即假定给定目标值时属性之间相互条件独立。也就是说没有哪个属性变量对于决策结果来说占有着较大的比重,也没有哪个属性变量对于决策结果占有着较小的比重。虽然这个简化方式在一定程度上降低了贝叶斯分类算法的分类效果,但是在实际的应用场景中,极大地简化了贝叶斯方法的复杂性。
二、贝叶斯公式
先验概率
代表还没有训练模型之前,根据历史数据/经验估算
拥有的初始概率。
常被称为
的先验概率(prior probability) ,它反映了
的概率分布,该分布独立于样本。
后验概率
给定数据样本
时
成立的概率
被称为后验概率(posterior probability),因为它反映了在看到数据样本
后
成立的置信度。
贝叶斯定理
已知两个独立事件A和B,事件B发生的前提下,事件A发生的概率可以表示为P(A|B),即上图中橙色部分占红色部分的比例,即:
三、朴素贝叶斯分类器
朴素贝叶斯分类器(Naïve Bayes Classifier)采用了“属性条件独立性假设”,即每个属性独立地对分类结果发生影响。
为方便公式标记,不妨记P(C=c|X=x)为P(c|x),基于属性条件独立性假设,贝叶斯公式可重写为
- 其中d为属性数目,x_i 为 x 在第i个属性上的取值。
由于对所有类别来说 P(x)相同,因此MAP判定准则可改为:
四、拉普拉斯修正
为了避免其他属性携带的信息,被训练集中未出现的属性值“抹去”,在估计概率值时通常要进行“拉普拉斯修正”:
令 N 表示训练集 D 中可能的类别数,
表示第i个属性可能的取值数,则贝叶斯公式可修正为:
五、垃圾邮件分类
数据集
将邮件分为三部分:normal(正常邮件)、spam(垃圾邮件)、test(测试邮件)
朴素贝叶斯算法
spamEmail.py
#encoding=utf-8 import jieba; import os; class spamEmailBayes: #获得停用词表 def getStopWords(self): stopList=[] for line in open("../data/stop.txt"): stopList.append(line[:len(line)-1]) return stopList; #获得词典 def get_word_list(self,content,wordsList,stopList): #分词结果放入res_list res_list = list(jieba.cut(content)) for i in res_list: if i not in stopList and i.strip()!='' and i!=None: if i not in wordsList: wordsList.append(i) #若列表中的词已在词典中,则加1,否则添加进去 def addToDict(self,wordsList,wordsDict): for item in wordsList: if item in wordsDict.keys(): wordsDict[item]+=1 else: wordsDict.setdefault(item,1) def get_File_List(self,filePath): filenames=os.listdir(filePath) return filenames #通过计算每个文件中p(s|w)来得到对分类影响最大的15个词 def getTestWords(self,testDict,spamDict,normDict,normFilelen,spamFilelen): wordProbList={} for word,num in testDict.items(): if word in spamDict.keys() and word in normDict.keys(): #该文件中包含词个数 pw_s=spamDict[word]/spamFilelen pw_n=normDict[word]/normFilelen ps_w=pw_s/(pw_s+pw_n) wordProbList.setdefault(word,ps_w) if word in spamDict.keys() and word not in normDict.keys(): pw_s=spamDict[word]/spamFilelen pw_n=0.01 ps_w=pw_s/(pw_s+pw_n) wordProbList.setdefault(word,ps_w) if word not in spamDict.keys() and word in normDict.keys(): pw_s=0.01 pw_n=normDict[word]/normFilelen ps_w=pw_s/(pw_s+pw_n) wordProbList.setdefault(word,ps_w) if word not in spamDict.keys() and word not in normDict.keys(): #若该词不在脏词词典中,概率设为0.4 wordProbList.setdefault(word,0.4) sorted(wordProbList.items(),key=lambda d:d[1],reverse=True)[0:15] return (wordProbList) #计算贝叶斯概率 def calBayes(self,wordList,spamdict,normdict): ps_w=1 ps_n=1 for word,prob in wordList.items() : print(word+"/"+str(prob)) ps_w*=(prob) ps_n*=(1-prob) p=ps_w/(ps_w+ps_n) # print(str(ps_w)+""+str(ps_n)) return p #计算预测结果正确率 def calAccuracy(self,testResult): rightCount=0 errorCount=0 for name ,catagory in testResult.items(): if (int(name)<1000 and catagory==0) or(int(name)>1000 and catagory==1): rightCount+=1 else: errorCount+=1 return rightCount/(rightCount+errorCount)ttss.py
#encoding=utf-8 from spam.spamEmail import spamEmailBayes import re #spam类对象 spam=spamEmailBayes() #保存词频的词典 spamDict={} normDict={} testDict={} #保存每封邮件中出现的词 wordsList=[] wordsDict={} #保存预测结果,key为文件名,值为预测类别 testResult={} #分别获得正常邮件、垃圾邮件及测试文件名称列表 normFileList=spam.get_File_List(r"c:/Users/18111/Desktop/BayesSpam-master/data/normal") spamFileList=spam.get_File_List(r"c:/Users/18111/Desktop/BayesSpam-master/data/spam") testFileList=spam.get_File_List(r"c:/Users/18111/Desktop/BayesSpam-master/data/test") #获取训练集中正常邮件与垃圾邮件的数量 normFilelen=len(normFileList) spamFilelen=len(spamFileList) #获得停用词表,用于对停用词过滤 stopList=spam.getStopWords() #获得正常邮件中的词频 for fileName in normFileList: wordsList.clear() for line in open("../data/normal/"+fileName): #过滤掉非中文字符 rule=re.compile(r"[^\u4e00-\u9fa5]") line=rule.sub("",line) #将每封邮件出现的词保存在wordsList中 spam.get_word_list(line,wordsList,stopList) #统计每个词在所有邮件中出现的次数 spam.addToDict(wordsList, wordsDict) normDict=wordsDict.copy() #获得垃圾邮件中的词频 wordsDict.clear() for fileName in spamFileList: wordsList.clear() for line in open("../data/spam/"+fileName): rule=re.compile(r"[^\u4e00-\u9fa5]") line=rule.sub("",line) spam.get_word_list(line,wordsList,stopList) spam.addToDict(wordsList, wordsDict) spamDict=wordsDict.copy() # 测试邮件 for fileName in testFileList: testDict.clear( ) wordsDict.clear() wordsList.clear() for line in open("../data/test/"+fileName): rule=re.compile(r"[^\u4e00-\u9fa5]") line=rule.sub("",line) spam.get_word_list(line,wordsList,stopList) spam.addToDict(wordsList, wordsDict) testDict=wordsDict.copy() #通过计算每个文件中p(s|w)来得到对分类影响最大的15个词 wordProbList=spam.getTestWords(testDict, spamDict,normDict,normFilelen,spamFilelen) #对每封邮件得到的15个词计算贝叶斯概率 p=spam.calBayes(wordProbList, spamDict, normDict) if(p>0.9): testResult.setdefault(fileName,1) else: testResult.setdefault(fileName,0) #计算分类准确率(测试集中文件名低于1000的为正常邮件) testAccuracy=spam.calAccuracy(testResult) for i,ic in testResult.items(): print(i+"/"+str(ic)) print(testAccuracy)
运行结果
获取邮件中的词频(部分截图):
测试邮件分类(0为垃圾邮件,1为正常邮件):
分类准确率:
小结
在400封邮件(正常邮件与垃圾邮件各一半)的测试集中测试结果为分类准确率95.15%,在仅仅统计词频计算概率的情况下,分类结果还是相当不错的。












754

被折叠的 条评论
为什么被折叠?



