基于概率论的分类方法:朴素贝叶斯
来源:互联网 发布:亿乐社区系统 v2.0源码 编辑:程序博客网 时间:2024/05/22 06:57
一 、什么是贝叶斯公式?
贝叶斯公式用来描述两个条件概率之间的关系:P(Y|X)=P(X|Y)P(Y)P(X)
以上公式也可变形为:P(Y,X)=P(Y|X)P(X)=P(X|Y)P(Y)
举例说明:
现分别有 A、B 两个容器,在容器 A 里分别有 7 个红球和 3 个白球,在容器 B 里有 1 个红球和 9 个白球,现已知从这两个容器里任意抽出了一个球,问这个球是红球且来自容器 A 的概率是多少?
假设已经抽出红球为事件 B,选中容器 A 为事件 A,则有:P(B) = 8/20,P(A) = 1/2,P(B|A) = 7/10,按照公式,则有:P(A|B) = (7/10)*(1/2) / (8/20) = 0.875
叶贝斯公司常用来计算已知先验概率求后验概率的情景。
二、什么是朴素叶贝斯公式?
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。即:加上条件独立假设的贝叶斯方法就是朴素贝叶斯方法(Naive Bayes)。
贝叶斯公式 + 条件独立假设 = 朴素贝叶斯方法
所谓的独立是统计意义上的独立,即每个条件发生的概率不受其它条件的影响。显然这是一种假设,但朴素贝叶斯的实际效果却很好。
三、使用朴素贝叶斯进行文档分类
(1)准备数据:从文本中构建词向量
def loadDataSet():# 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 createVocabList(dataSet): vocabSet = set([]) #创建set空集合,用来存放无重复的样本数据 for document in dataSet: vocabSet = vocabSet | set(document) #将每篇文章的新词汇添加到集合中 return list(vocabSet)def setOfWords2Vec(vocabList, inputSet):#判断词汇列表中的词汇是否在每组中,存在返回1,否则返回默认值0 returnVec = [0]*len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] = 1 else: print "the word: %s is not in my Vocabulary!" % word return returnVec
三个函数的作用分别是:创建样本数据以及人工标注分类标签,1代表有侮辱词汇,0没有;创建无重复单词的词汇列表;把单词转换成向量。
(2)训练算法:从词向量计算概率
def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[0]) pAbusive = sum(trainCategory)/float(numTrainDocs)#求有侮辱性的分类占总分类的比例 p0Num = zeros(numWords); p1Num = zeros(numWords) #change to ones() p0Denom = 0.0; p1Denom = 0.0 #change to 2.0 for i in range(numTrainDocs): if trainCategory[i] == 1:#计算侮辱词汇的数目,trainMatrix为0-1值形成的向量 p1Num += trainMatrix[i] # p1Num存储的是每个词在侮辱分类下出现的次数 p1Denom += sum(trainMatrix[i])# p1Denom存储的是侮辱分类下词的总数目 else: p0Num += trainMatrix[i] p0Denom += sum(trainMatrix[i]) p1Vect = p1Num/p1Denom #计算侮辱词汇分类下每个词出现的概率 p0Vect = p0Num/p0Denom #计算非侮辱词汇分类下每个词出现的概率 return p0Vect,p1Vect,pAbusive该函数是用来计算每个词汇在1和0两大分类情况下的概率,返回的p0Vect,p1Vect结果如图所示:
但因为在计算多个概率的乘积时,其中有一个概率为0,那么最后的概率也为0,所以我们可以把所有词初始化为1,分母初始化为2.
p0Num = ones(numWords); p1Num = ones(numWords) p0Denom = 2.0; p1Denom = 2.0此外,如果很多小概率数字相乘会出现下溢问题,所以我们对乘积取自然对数,
p1Vect = log(p1Num/p1Denom) p0Vect = log(p0Num/p0Denom)进行如上操作后会得到与原始数据同等增加或减少的图像
(3)构造朴素贝叶斯分类函数:
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1): #计算属于侮辱分类的概率 p1 = sum(vec2Classify * p1Vec) + log(pClass1) # 计算不属于侮辱分类的概率 p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1) # 根据概率大小判断属于哪个类 if p1 > p0: return 1 else: return 0 def testingNB(): #挑选一些词汇,计算他属于两种分类的概率,并判断属于哪个分类 # 加载数据集 listOPosts,listClass = loadDataSet() # 创建词汇列表 myVocabList = createVocabList(listOPosts) trainMat = [] for postinDoc in listOPosts: trainMat.append(setOfWords2Vec(myVocabList,postinDoc)) p0V,p1V,pAb = trainNB0(array(trainMat),array(listClass)) # print p0V,p1V,pAb # print trainMat 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)
两个函数分别构建了分类函数和测试函数,最后选择一些数据集进行测试,并返回概率大的标签。
四、应用:用朴素贝叶斯过滤垃圾邮件
朴素贝叶斯最大的应用便是用来过滤垃圾邮件,我们选择25封垃圾邮件和25份非垃圾邮件使用算法根据以下步骤过滤垃圾邮件:
(1)收集数据:提供文本文件,下载地址:http://download.csdn.net/detail/liyuefeilong/9106481
(2)准备数据:将文本文件解析成词条向量;
(3)分析数据:检查词条确保解析的正确性;
(4)训练算法:使用我们之前建立的trainNB0()函数;
(5)测试算法:使用函数classifyNB(),并且构建一个新的测试函数来计算文档集的错误率;
使用算法:构建一个完整的程序对一组文档进行分类,将错分的文档输出到屏幕上。
代码的Python语言实现如下:注意我们随机选择10个邮件作为测试集,用算法得到的分类标签与已知的分类标签比较,不相同则错误率加一。因为随机选择,所以每次运行的结果的不同,我们取十次的运行结果取平均值,得到错误率约为0.6.
def textParse(bigString): #input is big string, #output is word list import re listOfTokens = re.split(r'\W*', bigString) return [tok.lower() for tok in listOfTokens if len(tok) > 2] def spamTest(): # 定义docList文档列表,classList类别列表,fullText所有文档词汇 docList=[]; classList = []; fullText =[] for i in range(1,26):#导入并解析文件,spam为1,ham为0 wordList = textParse(open('email/spam/%d.txt' % i).read()) docList.append(wordList) fullText.extend(wordList) classList.append(1)#根据文件名,判断文件分类 wordList = textParse(open('email/ham/%d.txt' % i).read()) docList.append(wordList) fullText.extend(wordList) classList.append(0) vocabList = createVocabList(docList)#去除所以重复单词,创建词汇列表 trainingSet = range(50); testSet=[]#创建训练集,测试集 for i in range(10):#随机选取10份邮件为测试集, randIndex = int(random.uniform(0,len(trainingSet))) testSet.append(trainingSet[randIndex])# 将随机选择的文档加入到测试集中 del(trainingSet[randIndex]) # 从训练集中删除随机选择的文档 trainMat=[]; trainClasses = [] for docIndex in trainingSet:#train the classifier (get probs) trainNB0 trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex])) trainClasses.append(classList[docIndex]) p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses)) #print trainClasses 训练集邮件(40份)的分类结果,也就是正确的分类,classList根据文件名判断 errorCount = 0 for docIndex in testSet: #从测试集中遍历邮件 wordVector = bagOfWords2VecMN(vocabList, docList[docIndex]) print classifyNB(array(wordVector),p0V,p1V,pSpam)#调用classifyNB()分类函数,输出测试模型的分类结果 if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:#注意docIndex是取自测试集 errorCount += 1 print "classification error",docList[docIndex] print 'the error rate is: ',float(errorCount)/len(testSet)
此外,要注意textParse()函数是对文本文件进行分词,单词长度小于2自动舍弃,最后的运行结果如图所示:
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯
- 基于概率论的分类方法--朴素贝叶斯
- C++实现基于概率论的分类方法--朴素贝叶斯分类
- 机器学习实战--基于概率论的分类方法:朴素贝叶斯
- 机器学习之基于概率论的分类方法 : 朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯算法实践学习
- 《机器学习实战》笔记之四——基于概率论的分类方法:朴素贝叶斯
- 机器学习实战python版第四章基于概率论的分类方法 朴素贝叶斯
- 机器学习实战(3)--(基于概率论的分类方法)朴素贝叶斯
- 基于概率论的分类方法:朴素贝叶斯---过滤网站恶意留言
- 判断多选框是否被选中
- 强制文件下载header设置
- linux OSI七层模型、TCP-IP协议栈及每层结构大揭秘
- POJ 3281 Dining(网络流建模)
- PAT (Basic Level) Practise (中文) 1026. 程序运行时间(15)
- 基于概率论的分类方法:朴素贝叶斯
- linux下查看CPU、内存、磁盘信息
- dblink链接数据库简介(oracle)
- 学习链接
- 程序员被提bug之后的反应
- 深度学习入门系列问题(一)
- JAVA DES加密(DES/ECB/PKCS5Padding)和C#加密对应设置
- 接口 和 抽象类 区别
- centos git 折腾