机器学习-朴素贝叶斯分类器
来源:互联网 发布:怎么执行mysql数据库 编辑:程序博客网 时间:2024/05/01 02:54
自学中,如有不足,请指出,谢谢~
朴素贝叶斯分类是一种十分简单的分类算法,朴素贝叶斯的思想基础是这样的:对于给出的待分类项,
求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。比如说现在有橘子,苹果,香蕉三类,
给出的特征有{形状,颜色},如果给出{圆形,红色}这个样本,那么它是P(苹果)的概率就是最大的,因此猜测它是苹果。
贝叶斯定理:
朴素贝叶斯有两个假设:
1、特征直接相互独立;
2、每个特征同等重要;
虽然朴素贝叶的假设不符合实际情况,但朴素贝叶斯分类器在很多复杂的现实情形中仍能够取得相当好的效果。
朴素贝叶斯的应用——文本分类:
用朴素贝叶斯进行文本分类,首先要准备数据
#创建实验样本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#创建包含所有不重复的词的list(用set)def createVocabList(dataSet): vocabSet = set([]) #创建空集合 for document in dataSet: vocabSet = vocabSet | set(document) #集合∪ return list(vocabSet)#输入词汇表和某个文档,输出文档向量#作用:将某个文档转换成和词汇表等长的0,1向量,文档中的词出现在词汇表中,对应的位置为1def setOfWords2Vec(vocabList, inputSet): returnVec = [0]*len(vocabList)#创建与词汇表等长的向量 for word in inputSet: if word in vocabList: #Word在inputSet中,对应的元素置1 returnVec[vocabList.index(word)] = 1 else: print "the word: %s is not in my Vocabulary!" % word return returnVec经过上述代码处理,输入的文档就会转换成0、1向量;
下面要计算这些数字的概率,通过贝叶斯概率知识,可以得到:
w是一个向量,即setOfWords2Vec函数产生的returnVec向量;Ci表示的就是类别,此例中为侮辱性留言和正常留言。
在朴素贝叶斯条件下,w向量的每个元素独立,则
因为分母P(w)是个常值,所以,需要最大化分子,即
实现代码如下:
#trainMatrix:postingList[i]中词汇在词汇表中是否出现的0,1向量所构成的矩阵def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) #postingList[i]中i的值(样本个数) numWords = len(trainMatrix[0]) #词汇表的长度 pAbusive = sum(trainCategory)/float(numTrainDocs) #是侮辱类的概率P(1) #计算p(w0|1)p(w1|1)p(w2|1)多个概率乘积,因为太多太小的数相乘可能会下溢, #所以取自然对数,转化成加法,避免错误 p0Num = ones(numWords); p1Num = ones(numWords) p0Denom = 2.0; p1Denom = 2.0 for i in range(numTrainDocs): if trainCategory[i] == 1: #如果第i个样本是侮辱性的 p1Num += trainMatrix[i] # p1Denom += sum(trainMatrix[i]) else: #如果第i个样本是正常的 p0Num += trainMatrix[i] p0Denom += sum(trainMatrix[i]) p1Vect = log(p1Num/p1Denom) #change to log() p0Vect = log(p0Num/p0Denom) #change to log() return p0Vect,p1Vect,pAbusive#判断分类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,listClasses = loadDataSet() #加载训练样本 myVocabList = createVocabList(listOPosts) trainMat=[] for postinDoc in listOPosts: trainMat.append(setOfWords2Vec(myVocabList, postinDoc)) p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses)) testEntry = ['love', 'my', 'dalmation'] thisDoc = array(setOfWords2Vec(myVocabList, testEntry)) #classifyNB进行分类 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)运行实际效果如下:
>>> import bayes>>> bayes.testingNB()['love', 'my', 'dalmation'] classified as: 0['stupid', 'garbage'] classified as: 1
以上的处理,是将每个词出现与否作为一个特征,setOfWords2Vec()这个函数实现了这个功能,这被称为是词集模式;
它不能统计每个词出现的次数,因此可能会损失一定的准确率,因此使用词袋模型来构建垃圾邮件分类器,bagOfWords2VecMN()实现该功能
#文档词袋模型,每个单词可以出现多次def bagOfWords2VecMN(vocabList, inputSet): returnVec = [0]*len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] += 1 return returnVec要过滤垃圾邮件,首先要获取邮件文本,将文本转成词汇,这要用到split()方法,有的单词会出现大写字母,这会造成匹配的困难,因此需要统一成小写或者大写形式,
需要使用lower()或者upper()方法
def textParse(bigString): import re listOfTokens = re.split(r'\W*', bigString) #用正则表达式切分(具体用法见另一博文) return [tok.lower() for tok in listOfTokens if len(tok) > 2] # 返回单词长度大于2的小写形式然后用spamTest()函数对贝叶斯垃圾分类器自动化处理。产生一个测试集和一个训练集,一共有50封邮件,随机选择10封邮件作为测试集,另外的40封邮件作为训练集,这个就是留存交叉验证,为了得到更高的准确率,可以进行多次迭代,然后求平均值;
#垃圾自动分类器 def spamTest(): docList=[]; classList = []; fullText =[] for i in range(1,26): wordList = textParse(open('email/spam/%d.txt' % i).read()) docList.append(wordList) #每个spam中的单词作为一个子列表添加到docList fullText.extend(wordList)#每个spam中的单词添加到docList classList.append(1) #classList里面加个1(类标签) wordList = textParse(open('email/ham/%d.txt' % i).read()) docList.append(wordList) fullText.extend(wordList) classList.append(0) vocabList = createVocabList(docList)#创建包含所有不重复的词的vocabList 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:#训练分类器 trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex])) trainClasses.append(classList[docIndex]) p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses)) errorCount = 0 for docIndex in testSet: #测试错误率 wordVector = bagOfWords2VecMN(vocabList, docList[docIndex]) if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:#classifyNB产生的类标签和真实的类标签不同 errorCount += 1 print "classification error",docList[docIndex] print 'the error rate is: ',float(errorCount)/len(testSet) #错误率以上的代码只是进行一次迭代,为了更加准确的分类,我将上述程序迭代了10次,然后求得平均错误率,代码基本是一样的,只是加入了几条语句,
我测试了3次,三次的结果如下:
>>> import bayes>>> bayes.spamTest()the error rate is: 0.04>>> ================================ RESTART ================================>>> >>> import bayes>>> bayes.spamTest()the error rate is: 0.08>>> ================================ RESTART ================================>>> >>> import bayes>>> bayes.spamTest()the error rate is: 0.03>>>
0 0
- 【机器学习】贝叶斯分类器:朴素贝叶斯
- 机器学习-朴素贝叶斯分类器
- 机器学习系列----朴素贝叶斯分类器
- 【机器学习】朴素贝叶斯分类器
- 机器学习系列-朴素贝叶斯分类器
- 机器学习之朴素贝叶斯分类器
- 机器学习:半朴素贝叶斯分类器
- 机器学习--朴素贝叶斯分类
- 【机器学习】朴素贝叶斯分类
- 机器学习--朴素贝叶斯分类
- 机器学习-朴素贝叶斯分类
- 机器学习-朴素贝叶斯分类
- 机器学习----贝叶斯分类器(朴素贝叶斯)
- 机器学习之旅---朴素贝叶斯分类器
- 朴素贝叶斯分类器——机器学习
- 机器学习——朴素贝叶斯分类器
- 半朴素贝叶斯分类器(周志华《机器学习》)
- 机器学习之朴素贝叶斯分类器附C++代码
- 把Gps坐标转成百度坐标的java方法
- 程序员可以在周末做的8件事
- Hbase在数据统计中的应用心得
- Tomcat错误-Port already in use
- 在一个activity中添加多个listview
- 机器学习-朴素贝叶斯分类器
- 昔我往矣,杨柳依依
- 读取excel大于Z列的数据
- 夏
- Vim 复制粘帖格
- char、varchar、nchar、nvarchar的区别(MSSQL)
- iOS中判定delegate是否已经被释放掉
- iOS集成支付宝SDK支付功能
- 九月的天气是忧郁的,是伤感的,是充满离别的