目录

1、朴素贝叶斯

2、朴素贝叶斯算法实例1--文档分类

3、朴素贝叶斯算法实例2--过滤垃圾邮件


1、朴素贝叶斯

朴素贝叶斯算法是有监督的学习算法,解决的是分类问题,如客户是否流失、是否值得投资、信用等级评定等多分类问题。该算法的优点在于简单易懂、学习效率高、在某些领域的分类问题中能够与决策树、神经网络相媲美。但由于该算法以自变量之间的独立(条件特征独立)性和连续变量的正态性假设为前提,就会导致算法精度在某种程度上受影响。

朴素贝叶斯是贝叶斯决策理论的一部分,所以讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论。

假设现在我们有一个数据集,它由两类数据组成,数据分布如图4-1所示。

假设有位读者找到了描述图中两类数据的统计参数。我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中用圆点表示的类别)的概率,用p2(x, y)表示数据点(x,y)属于类别2(图中用三角形表示的类别)的概率,那么对于一个新数据点(x,y),可以用下面的规则来判断它的类别:

①如果p1 (x,y) > p2(x,y),那么类别为1。

②如果p2(x,y) > p1(x,y),那么类别为2。

也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。回到图4-1,如果该图中的整个数据使用6个浮点数"来表示,并且计算类别概率的Python代码只有两行,那么你会更倾向于使用下面哪种方法来对该数据点进行分类?

①使用第1章的kNN,进行1000次距离计算;

②使用第2章的决策树,分别沿x轴、y轴划分数据;

③计算数据点属于每个类别的概率,并进行比较。

使用决策树不会非常成功,而和简单的概率计算相比,kNN的计算量太大。因此,对于上述问题,最佳选择是使用刚才提到的概率比较方法。

提到贝叶斯决策理论要求计算两个概率p1(x, y)和p2(x,y)。如果p1(x,y) > p2(x, y),那么属于类别1;如果p2(x,y) > p1(x,y),那么属于类别2。

但这两个准则并不是贝叶斯决策理论的所有内容。使用p1( )和p2( )只是为了尽可能简化描述,而真正需要计算和比较的是。这些符号所代表的具体意义是:给定某个由x、y表示的数据点,那么该数据点来自类别的概率是多少?数据点来自类别的概率又是多少?注意这些概率与刚才给出的概率p(x,y|c)并不一样,不过可以使用贝叶斯准则来交换概率中条件与结果。具体地,应用贝叶斯准则得到:

使用这些定义,可以定义贝叶斯分类准则为:

①如果,那么属于类别

②如果,那么属于类别

使用贝叶斯准则,可以通过已知的三个概率值来计算未知的概率值。后面就会给出利用贝叶斯准则来计算概率并对数据进行分类的代码。现在介绍了一些概率理论,你也了解了基于这些理论构建分类器的方法,接下来就要将它们付诸实践。

2、朴素贝叶斯算法实例1--文档分类

机器学习的一个重要应用就是文档的自动分类。在文档分类中,整个文档(如一封电子邮件)是实例,而电子邮件中的某些元素则构成特征。虽然电子邮件是一种会不断增加的文本,但我们同样也可以对新闻报道、用户留言、政府公文等其他任意类型的文本进行分类。我们可以观察文档中出现的词,并把每个词的出现或者不出现作为一个特征,这样得到的特征数目就会跟词汇表中的词目一样多。朴素贝叶斯是上节介绍的贝叶斯分类器的一个扩展,是用于文档分类的常用算法。

便用每个词作为特征并观察它们是否出现,这样得到的特征数目会有多少呢?针对的是哪一种人类语言呢?当然不止一种语言。据估计,仅在英语中,单词的总数就有500 000之多。为了能进行英文阅读,估计需要掌握数千单词。

假设词汇表中有1000个单词。要得到好的概率分布,就需要足够的数据样本,假定样本数为N。前面讲到的约会网站示例中有1000个实例,手写识别示例中每个数字有200个样本,而决策树示例中有24个样本。其中,24个样本有点少,200个样本好一些,而1000个样本就非常好了。约会网站例子中有三个特征。由统计学知,如果每个特征需要N个样本,那么对于10个特征将需要个样本,对于包含1000个特征的词汇表将需要个样本。可以看到,所需要的样本数会随着特征数目增大而迅速增长。

如果特征之间相互独立,那么样本数就可以从减少到1000×N。所谓独立指的是统计意义上的独立,即一个特征或者单词出现的可能性与它和其他单词相邻没有关系。举个例子讲,假设单词bacon出现在unhealthy后面与出现在delicious后面的概率相同。当然,我们知道这种假设并不正确,bacon常常出现在delicious附近,而很少出现在unhealthy附近,这个假设正是朴素贝叶斯分类器中朴素( naive)一词的含义。朴素贝叶斯分类器中的另一个假设是,每个特征相同重要。

以在线社区的留言板为例。为了不影响社区的发展,我们要屏蔽侮辱性的言论,所以要构建一个快速过滤器,如果某条留言使用了负面或者侮辱性的语言,那么就将该留言标识为内容不当。过滤这类内容是一个很常见的需求。对此问题建立两个类别:侮辱类和非侮辱类,使用1和0分别表示。

1、准备数据

我们将把文本看成单词向量或者词条向量,也就是说将句子转换为向量。考虑出现在所有文档中的所有单词,再决定将哪些词纳入词汇表或者说所要的词汇集合,然后必须要将每一篇文档转换为词汇表上的向量。接下来我们正式开始。打开文本编辑器,创建一个叫bayes.py的新文件,然后将下面的程序清单添加到文件中。

#数据集
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([])for document in dataSet:vocabSet = vocabSet | set(document)return list(vocabSet)
#根据vocabList词汇表,将inputSet向量化,向量的每个元素为1或0
def setOfWordVex(vocabList,inputSet):returnVec = [0]*len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] = 1else:print("%s  is not in vocalList",word)return returnVec

我们来测试一下代码:

DataSet,classVec = loadDataSet()
vocabSet = createVocabList(DataSet)
ans = setOfWordVex(vocabSet,DataSet[0])

得到的输出为:

2、朴素贝叶斯分类训练函数

前面介绍了如何将一组单词转换为一组数字,接下来看看如何使用这些数字计算概率。

#朴素贝叶斯分类器训练函数
def trainNBO(trainMatrix,trainCategroy):numTrainDocs = len(trainMatrix)     #计算训练的文档数目numWords = len(trainMatrix[0])     #计算每篇文档的词条数pAbusive = sum(trainCategroy)/float(numTrainDocs)      #文档属于侮辱类的概率#初始化概率p0num = np.ones(numWords)   #拉普拉斯平滑p1num = np.ones(numWords)p0Denom = 2.0p1Denom = 2.0for i in range(numTrainDocs):if trainCategroy[i] == 1:   #统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···p1num += trainMatrix[i]p1Denom += sum(trainMatrix[i])else:   #统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···p0num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = log(p1num/p1Denom) #取对数,取值不同,但是不影响最终结果。p0Vect = log(p0num/p0Denom) #可以防止下溢出,这是由于太多太小的数相乘造成的。return p0Vect,p1Vect,pAbusive #返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率

利用贝叶斯分类器对文档进行分类时,要计算多个概率的乘积以获得文档属于某个类别的概率,即计算。如果其中一个概率值为0,那么最后的乘积也为0。为降低这种影响,可以将所有词的出现数初始化为1,并将分母初始化为2。

另一个遇到的问题是下溢出,这是由于太多很小的数相乘造成的。当计算乘积时,由于大部分因子都非常小,所以程序会下溢出或者得到不正确的答案。(读者可以用Python尝试相乘许多很小的数,最后四舍五入后会得到0。)一种解决办法是对乘积取自然对数。在代数中有1n(a*b) = ln (a)+1n(b),于是通过求对数可以避免下溢出或者浮点数舍入导致的错误。同时,采用自然对数进行处理不会有任何损失。

3、朴素贝叶斯分类函数

使用NumPy的数组来计算两个向量相乘的结果。这里的相乘是指对应元素相乘,即先将两个向量中的第1个元素相乘,然后将第2个元素相乘,以此类推。接下来将词汇表中所有词的对应值相加,然后将该值加到类别的对数概率上。最后,比较类别的概率返回大概率对应的类别标签。这一切不是很难,对吧?

def classifyNB(vecClassify,p0Vec,p1Vec,pClass1):p1 = sum(vecClassify*p1Vec)+log(pClass1)p0 = sum(vecClassify*p0Vec)+log(1-pClass1)if p1>p0:return 1else :return 0
def testingNB():DataSet,classVec = loadDataSet()vocabSet = createVocabList(DataSet)trainMat = []for postinDoc in DataSet:trainMat.append(setOfWordVex(vocabSet,postinDoc))p0V,p1V,pAb = trainNBO(trainMat,classVec)testEntry = ['love','my','dalmation']thisDoc = array(setOfWordVex(vocabSet,testEntry))print(classifyNB(thisDoc,p0V,p1V,pAb))

我们测试一下代码,得到:

4、词袋模型

目前为止,我们将每个词的出现与否作为一个特征,这可以被描述为词集模型。如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,这种方法被称为词袋模型。在词袋中,每个单词可以出现多次,而在词集中,每个词只能出现一次。为适应词袋模型,需要对函数setofWordsvec()稍加修改,修改后的函数称为bagofwordsvec ()。

下面的函数给出了基于词袋模型的朴素贝叶斯代码。它与函数setofwordsvec()几乎完全相同,唯一不同的是每当遇到一个单词时,它会增加词向量中的对应值,而不只是将对应的数值设为1。

#词带模型
def bagOfWordVecMN(vocabList,inputSet):returnVec = [0]*len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] += 1   #与词集模型不同之处return returnVec

现在分类器已经构建好了,下面我们将利用该分类器来过滤垃圾邮件。

5、完整代码

见下个实例吧。哈。

3、朴素贝叶斯算法实例2--过滤垃圾邮件

在前面那个简单的例子中,我们引人了字符串列表。使用朴素贝叶斯解决一些现实生活中的问题时,需要先从文本内容得到字符串列表,然后生成词向量。下面这个例子中,.我们将了解朴素贝叶斯的一个最著名的应用:电子邮件垃圾过滤。首先看一下如何使用通用框架来解决该问题。

1、准备数据,切分文本

前一节介绍了如何创建词向量,并基于这些词向量进行朴素贝叶斯分类的过程。前一节中的词向量是预先给定的,下面介绍如何从文本文档中构建自己的词列表。

数据:数据在这!         提取码:kfpg

#切分文本
def textParse(bigString):listOfTokens = re.split(r'\W+', bigString)return [tok.lower() for tok in listOfTokens if len(tok)>2]
def spamTest():docList = []classList = []fullText = []for i in range(1,26):#遍历25个txt文件wordList = textParse(open('email/spam/%d.txt' % i, 'r').read()) #读取每个垃圾邮件,并字符串转换成字符串列表docList.append(wordList)fullText.extend(wordList)classList.append(1) #标记垃圾邮件,1表示垃圾文件wordList = textParse(open('email/ham/%d.txt' % i).read())docList.append(wordList)fullText.extend(wordList)classList.append(0)#标记非垃圾邮件# print(docList)vocabList = createVocabList(docList) #创建词汇表,不重复trainingSet = list(range(50))   #训练集print(trainingSet)testSet = []    # 测试集for i in range (10):    #随机构建训练集、测试集randIndex  = int(random.uniform(0,len(trainingSet)))testSet.append(trainingSet[randIndex])del(trainingSet[randIndex])trainMat = []trainClasses = []for docIndex in trainingSet:trainMat.append(setOfWordVex(vocabList,docList[docIndex]))trainClasses.append(classList[docIndex])p0V,p1V,pSpam = trainNBO(array(trainMat),array(trainClasses))errorCount = 0for docIndex in testSet:wordVector = setOfWordVex(vocabList,docList[docIndex])if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:errorCount += 1print('the error is %f',errorCount/float(len(testSet)))

测试一下得到:

函数spamTest ()会输出在10封随机选择的电子邮件上的分类错误率。既然这些电子邮件是随机选择的,所以每次的输出结果可能有些差别。如果发现错误的话,函数会输出错分文档的词表,这样就可以了解到底是哪篇文档发生了错误。如果想要更好地估计错误率,那么就应该将上述过程重复多次,比如说10次,然后求平均值。我这么做了一下,获得的平均错误率为6%。

这里一直出现的错误是将垃圾邮件误判为正常邮件。相比之下,将垃圾邮件误判为正常邮件要比将正常邮件归到垃圾邮件好。为避免错误,有多种方式可以用来修正分类器,这些将在第7章中进行讨论。

2、完整代码

from numpy import  *
import numpy as np
import random
import re#数据集
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([])for document in dataSet:vocabSet = vocabSet | set(document)return list(vocabSet)#根据vocabList词汇表,将inputSet向量化,向量的每个元素为1或0
def setOfWordVex(vocabList,inputSet):returnVec = [0]*len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] = 1else:print("%s  is not in vocalList",word)return returnVec#词带模型
def bagOfWordVecMN(vocabList,inputSet):returnVec = [0]*len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] += 1   #与词集模型不同之处return returnVec#朴素贝叶斯分类器训练函数
def trainNBO(trainMatrix,trainCategroy):numTrainDocs = len(trainMatrix)     #计算训练的文档数目numWords = len(trainMatrix[0])     #计算每篇文档的词条数pAbusive = sum(trainCategroy)/float(numTrainDocs)      #文档属于侮辱类的概率#初始化概率p0num = np.ones(numWords)   #拉普拉斯平滑p1num = np.ones(numWords)p0Denom = 2.0p1Denom = 2.0for i in range(numTrainDocs):if trainCategroy[i] == 1:   #统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···p1num += trainMatrix[i]p1Denom += sum(trainMatrix[i])else:   #统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···p0num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = log(p1num/p1Denom) #取对数,取值不同,但是不影响最终结果。p0Vect = log(p0num/p0Denom) #可以防止下溢出,这是由于太多太小的数相乘造成的。return p0Vect,p1Vect,pAbusive #返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率def classifyNB(vecClassify,p0Vec,p1Vec,pClass1):p1 = sum(vecClassify*p1Vec)+log(pClass1)p0 = sum(vecClassify*p0Vec)+log(1-pClass1)if p1>p0:return 1else :return 0def testingNB():DataSet,classVec = loadDataSet()vocabSet = createVocabList(DataSet)trainMat = []for postinDoc in DataSet:trainMat.append(setOfWordVex(vocabSet,postinDoc))p0V,p1V,pAb = trainNBO(trainMat,classVec)testEntry = ['love','my','dalmation']thisDoc = array(setOfWordVex(vocabSet,testEntry))print(classifyNB(thisDoc,p0V,p1V,pAb))#切分文本
def textParse(bigString):listOfTokens = re.split(r'\W+', bigString)return [tok.lower() for tok in listOfTokens if len(tok)>2]#
def spamTest():docList = []classList = []fullText = []for i in range(1,26):#遍历25个txt文件wordList = textParse(open('email/spam/%d.txt' % i, 'r').read()) #读取每个垃圾邮件,并字符串转换成字符串列表docList.append(wordList)fullText.extend(wordList)classList.append(1) #标记垃圾邮件,1表示垃圾文件wordList = textParse(open('email/ham/%d.txt' % i).read())docList.append(wordList)fullText.extend(wordList)classList.append(0)#标记非垃圾邮件# print(docList)vocabList = createVocabList(docList) #创建词汇表,不重复trainingSet = list(range(50))   #训练集print(trainingSet)testSet = []    # 测试集for i in range (10):    #随机构建训练集、测试集randIndex  = int(random.uniform(0,len(trainingSet)))testSet.append(trainingSet[randIndex])del(trainingSet[randIndex])trainMat = []trainClasses = []for docIndex in trainingSet:trainMat.append(setOfWordVex(vocabList,docList[docIndex]))trainClasses.append(classList[docIndex])p0V,p1V,pSpam = trainNBO(array(trainMat),array(trainClasses))errorCount = 0for docIndex in testSet:wordVector = setOfWordVex(vocabList,docList[docIndex])if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:errorCount += 1print('the error is %f',errorCount/float(len(testSet)))# DataSet,classVec = loadDataSet()
# vocabSet = createVocabList(DataSet)
# ans = setOfWordVex(vocabSet,DataSet[0])
# print(ans)
# trainMat = []
# for postinDoc in DataSet:
#     trainMat.append(setOfWordVex(vocabSet,postinDoc))
#
# p0V,p1V,pAb = trainNBO(trainMat,classVec)# testingNB()spamTest()

机器学习实战3(朴素贝叶斯篇)相关推荐

  1. 《机器学习实战》朴素贝叶斯

    机器学习实战的朴素贝叶斯一章中的源文件老是提示 IndexError: range object index out of range 看源码里怎么都不会溢出啊,除非minLen为0:所以看了下测试集 ...

  2. 机器学习实战之朴素贝叶斯

    机器学习实战之朴素贝叶斯 一.朴素贝叶斯算法概述 1.贝叶斯决策理论 2.条件概率 3.全概率公式 4.贝叶斯推断 5.朴素贝叶斯推断 二.实战 三.总结 1.朴素贝叶斯推断的一些优点: 2.朴素贝叶 ...

  3. 机器学习实战:朴素贝叶斯算法在新闻文本数据上的分类表现

    https://www.toutiao.com/a6647102437532369421/ 2019-01-17 08:01:00 大家好,今天跟大家学习一下通过sklearn的朴素贝叶斯模型实战.前 ...

  4. 实现贝叶斯分类器_机器学习实战项目-朴素贝叶斯

    朴素贝叶斯 概述 贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类.本章首先介绍贝叶斯分类算法的基础--贝叶斯定理.最后,我们通过实例来讨论贝叶斯分类的中最简单的一种: ...

  5. 《机器学习实战》——朴素贝叶斯

    一 前言 朴素贝叶斯算法是有监督的学习算法,解决的是分类问题,如客户是否流失.是否值得投资.信用等级评定等多分类问题.该算法的优点在于简单易懂.学习效率高.在某些领域的分类问题中能够与决策树.神经网络 ...

  6. 04机器学习实战之朴素贝叶斯

    朴素贝叶斯 概述 贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类.本章首先介绍贝叶斯分类算法的基础--贝叶斯定理.最后,我们通过实例来讨论贝叶斯分类的中最简单的一种: ...

  7. 【机器学习实战】朴素贝叶斯应用之垃圾邮件过滤

    1.什么是朴素贝叶斯 2.贝叶斯公式 3.朴素贝叶斯常用的三个模型 4.朴素贝叶斯实现垃圾邮件过滤的步骤 5.垃圾邮件过滤实验: (一).准备收集好的数据集,并下载到本地文件夹 (二).朴素贝叶斯分类 ...

  8. 机器学习实战之朴素贝叶斯与垃圾邮件分类

    文章目录 一.实现原理 1.1 贝叶斯理论与公式 1.2 朴素贝叶斯分类器 1.3 拉普拉斯修正 1.4 分类小案例 二.代码实现 2.1 数据准备与处理 2.2 创建词汇表 2.3 构建词袋/词集模 ...

  9. 【机器学习实战】朴素贝叶斯(连续型/离散型)

    朴素贝叶斯 一.连续型 1.计算高斯概率密度CalcuGaussProb(x,mean,stdev) 2.获取各类别中各特征的均值.方差和标签集getMeanStdLabel(self,train_d ...

  10. 《机器学习实战》—— 朴素贝叶斯

    文章目录 一.朴素贝叶斯 二.基于贝叶斯决策理论的分类方法 三.数学知识准备 3.1 条件概率 3.2 全概率公式 3.3 贝叶斯推断 四.使用条件概率来分类 五.文本分类 5.1 从文本中构建词向量 ...

最新文章

  1. arcgisengine计算线要素总长度_弱电监控工程报价清单中,线材及辅材该如何计算?...
  2. php中$_REQUEST、$_POST、$_GET的区别
  3. Django实战教程 分页列表
  4. BZOJ3336: Uva10572 Black and White(插头Dp)
  5. Git常用命令速查表
  6. 关于SAP S/4HANA里ABAP源代码管理功能的增强
  7. 【知识图谱】一、知识表示与知识建模
  8. C++学习系列笔记(三)
  9. 外媒吐槽:iPhone 13系列为史上力度最小的升级
  10. 探求Floyd算法的动态规划本质
  11. Python抽象及异常处理
  12. MS Sql Server 数据库或表修复(DBCC CHECKDB)
  13. 2017-2018-2 1723《程序设计与数据结构》第八周作业 实验二 第一周结对编程 总结...
  14. Java开发框架——Struts框架
  15. 安装CentOS时提示an error has occurred - no valid devices were fo
  16. 语法分析器-LL(1)语法分析
  17. 国际学术期刊排名按照姓氏字母排吗?
  18. pdf 转换为图片格式(可提高兼容性)
  19. 腾讯云轻量服务器和虚拟主机VPS有什么区别?
  20. 实习期间的一些思考整理(2)2018.4.10~4.11

热门文章

  1. Ubuntu 调用查看USB摄像头命令行介绍
  2. 43 《激活个体:互联时代的组织管理新范式》 -豆瓣评分6.9
  3. 饥荒steam服务器文档,Steam饥荒专用服务器搭建
  4. 用手机测试你的肺活量!?
  5. Adr翻译助手 1.0.1.5 版发布
  6. 你的博客为什么不更新了?
  7. storm 入门教程——storm基础知识(W3Cschool)
  8. 云计算的未来是XMPP
  9. google中国的高层大离职
  10. ZZULIOJ1152: 二分搜索