机器学习实战 朴素贝叶斯原理及代码
2018-01-13 16:31
537 查看
朴素贝叶斯(naive Bayes)法是是基于贝叶斯定理 和特征条件独立假设的分类方法,对于给定的训练数据集,首先基于特征条件独立假设学习输入/输出的联合分布概率;然后基于此模型,对给定的输入x,再利用贝叶斯定理求出其后验概率最大的输出y。
1,它是一种典型的生成学习方法,其生成方法是由训练数据学习联合概率分布P(X,Y),具体来说就是利用训练数据学习P(Y)和P(X|Y)的估计:P(X,Y) = P(Y)P(X|Y),其概率估计方法是极大似然估计,其实很好理解,就是从数据分布估计参数的分布,比如,你现在知道了全班一共50个人,30个男的,20个女的,那你就可以用数据估计出男生大致分布为五分之三,女生为五分之二,数据分布估计参数分布。。。。
2,另一个要注意的点是朴素贝叶斯的基本假设是条件独立性。就是每个参数变量的概率分布不互相影响,相互独立。
举个知乎上的例子!
朴素贝叶斯数学表达是下面这个贝叶斯公式,这个公式应该很好理解把。。学过概率统计都知道,条件概率的求法:
![](https://img-blog.csdn.net/20180117114116418?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmd6aGVueGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
如果还不懂。。。换个表达形式就会明朗很多,如下:
![](https://img-blog.csdn.net/20180117114140074?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmd6aGVueGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
我们最终求的p(类别|特征)即可!就相当于完成了我们的任务。
![](https://img-blog.csdn.net/20180117114101396?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmd6aGVueGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
现在给我们的问题是,如果一对男女朋友,男生想女生求婚,男生的四个特点分别是不帅,性格不好,身高矮,不上进,请你判断一下女生是嫁还是不嫁?
这是一个典型的分类问题,转为数学问题就是比较p(嫁|(不帅、性格不好、身高矮、不上进))与p(不嫁|(不帅、性格不好、身高矮、不上进))的概率,谁的概率大,我就能给出嫁或者不嫁的答案,哪个大选哪个。。。
这里我们联系到朴素贝叶斯公式:
![](https://img-blog.csdn.net/20180117114228276?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmd6aGVueGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
我们需要求p(嫁|(不帅、性格不好、身高矮、不上进),这是我们不知道的,但是通过朴素贝叶斯公式可以转化为好求的三个量,p(不帅、性格不好、身高矮、不上进|嫁)、p(不帅、性格不好、身高矮、不上进)、p(嫁)(至于为什么能求,后面会讲,那么就太好了,将待求的量转化为其它可求的值,这就相当于解决了我们的问题!)
是根据已知训练数据统计得来,下面详细给出该例子的求解过程。
回忆一下我们要求的公式如下:
![](https://img-blog.csdn.net/20180117114303508?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmd6aGVueGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
那么我只要求得p(不帅、性格不好、身高矮、不上进|嫁)、p(不帅、性格不好、身高矮、不上进)、p(嫁)即可,好的,下面我分别求出这几个概率,最后一比,就得到最终结果。
p(不帅、性格不好、身高矮、不上进|嫁) = p(不帅|嫁)*p(性格不好|嫁)*p(身高矮|嫁)*p(不上进|嫁),那么我就要分别统计后面几个概率,也就得到了左边的概率!
等等,为什么这个成立呢?学过概率论的同学可能有感觉了,这个等式成立的条件需要特征之间相互独立吧!
对的!这也就是为什么朴素贝叶斯分类有朴素一词的来源,朴素贝叶斯算法是假设各个特征之间相互独立,那么这个等式就成立了!
但是为什么需要假设特征之间相互独立呢?
1、我们这么想,假如没有这个假设,那么我们对右边这些概率的估计其实是不可做的,这么说,我们这个例子有4个特征,其中帅包括{帅,不帅},性格包括{不好,好,爆好},身高包括{高,矮,中},上进包括{不上进,上进},那么四个特征的联合概率分布总共是4维空间,总个数为2*3*3*2=36个。
24个,计算机扫描统计还可以,但是现实生活中,往往有非常多的特征,每一个特征的取值也是非常之多,那么通过统计来估计后面概率的值,变得几乎不可做,这也是为什么需要假设特征之间独立的原因。
2、假如我们没有假设特征之间相互独立,那么我们统计的时候,就需要在整个特征空间中去找,比如统计p(不帅、性格不好、身高矮、不上进|嫁),
我们就需要在嫁的条件下,去找四种特征全满足分别是不帅,性格不好,身高矮,不上进的人的个数,这样的话,由于数据的稀疏性,很容易统计到0的情况。 这样是不合适的。
根据上面俩个原因,朴素贝叶斯法对条件概率分布做了条件独立性的假设,由于这是一个较强的假设,朴素贝叶斯也由此得名!这一假设使得朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率。
好的,上面我解释了为什么可以拆成分开连乘形式。那么下面我们就开始求解!
求解过程就是用=贝叶斯定理与学到的联合概率模型进行分类预测,
![](https://img-blog.csdn.net/20180117114347778?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmd6aGVueGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
将输入x分到后验概率最大的类y.
![](https://img-blog.csdn.net/20180117114406782?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmd6aGVueGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这个在统计学习方法中有推导,意思就是对每个参数都求最小,得到的就是最优结果
接下来贴上机器学习实战朴素贝叶斯的代码:
书上利用朴素贝叶斯进行文档分类 :首先收集数据,把数据做成数值型或者布尔型数据,分析数据时因为有大量的特征,绘制特征不好使,使用直方图比较好。计算不同的独立特征的条件概率,对测试数据计算错误率,得到文档分类。
1:要想从文本中获取特征,就要先拆分文本。这里首先给出将文本转换为数字向量的过程,将每一个文本片段表示为一个词条向量,值为1表示词条出现在文档中,0表示词条未出现。在此对类别标签设置为侮辱类和非侮辱类,使用0和1表示。
创建一些实验文本,返回的第一个变量是进行词条切分后的文档集合,文本被切分成一系列的词条集合,标点符号从文本中去掉,第二个是类别标签的集合。
2:创建一个包含在所有文档中出现的不重复词的列表,使用set数据类型,set将返回一个不重复词表。
3:使用词汇表或者想要检查的所有单词作为输入,然后为其中每个单词构建一个特征,一旦给定一篇文档,该文档将自动转化为词向量。
4:上面将一组单词转化为一组数字,接下来就是如何使用这些数字计算概率。由以上的程序可知,一个词是否出现在一篇文档中,也知道该文档所属的类别。
首先通过类别i(侮辱或非侮辱)中文档数除以总的文档数来计算概率p(ci),然后计算p(x|ci),这里用到朴素贝叶斯假设。如果将x展开为一个个独立的特征,那么就可以将上述概率写成p(x0,x1,x2…..xn|ci),所有词都互相独立,则称作条件独立性假设,意味着可以使用p(x0|ci)p(x1|ci)p(x2|ci)…..p(xn|ci)来计算上述概率。
p0Vect是一个向量,元素是每个词在该类别中出现的概率。p1Vect同上。
pAbusive是文档属于1的概率。
5:构建完整的分类器,就是编写分类函数。
6:现在将每个词的出现与否作为一个特征,这被描述为词集模型,但一个词在文档中出现不止一次,就要使用词袋模型,在词袋中,每个单词可以出现多次
结果如下:
![](https://img-blog.csdn.net/20180113171043081?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmd6aGVueGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
说明对于简单的样本,还是能正确分类的!
本期到此结束!
1,它是一种典型的生成学习方法,其生成方法是由训练数据学习联合概率分布P(X,Y),具体来说就是利用训练数据学习P(Y)和P(X|Y)的估计:P(X,Y) = P(Y)P(X|Y),其概率估计方法是极大似然估计,其实很好理解,就是从数据分布估计参数的分布,比如,你现在知道了全班一共50个人,30个男的,20个女的,那你就可以用数据估计出男生大致分布为五分之三,女生为五分之二,数据分布估计参数分布。。。。
2,另一个要注意的点是朴素贝叶斯的基本假设是条件独立性。就是每个参数变量的概率分布不互相影响,相互独立。
举个知乎上的例子!
朴素贝叶斯数学表达是下面这个贝叶斯公式,这个公式应该很好理解把。。学过概率统计都知道,条件概率的求法:
如果还不懂。。。换个表达形式就会明朗很多,如下:
我们最终求的p(类别|特征)即可!就相当于完成了我们的任务。
例题分析
下面我先给出例子问题。给定数据如下:
现在给我们的问题是,如果一对男女朋友,男生想女生求婚,男生的四个特点分别是不帅,性格不好,身高矮,不上进,请你判断一下女生是嫁还是不嫁?
这是一个典型的分类问题,转为数学问题就是比较p(嫁|(不帅、性格不好、身高矮、不上进))与p(不嫁|(不帅、性格不好、身高矮、不上进))的概率,谁的概率大,我就能给出嫁或者不嫁的答案,哪个大选哪个。。。
这里我们联系到朴素贝叶斯公式:
我们需要求p(嫁|(不帅、性格不好、身高矮、不上进),这是我们不知道的,但是通过朴素贝叶斯公式可以转化为好求的三个量,p(不帅、性格不好、身高矮、不上进|嫁)、p(不帅、性格不好、身高矮、不上进)、p(嫁)(至于为什么能求,后面会讲,那么就太好了,将待求的量转化为其它可求的值,这就相当于解决了我们的问题!)
朴素贝叶斯算法的朴素一词解释
那么这三个量是如何求得?是根据已知训练数据统计得来,下面详细给出该例子的求解过程。
回忆一下我们要求的公式如下:
那么我只要求得p(不帅、性格不好、身高矮、不上进|嫁)、p(不帅、性格不好、身高矮、不上进)、p(嫁)即可,好的,下面我分别求出这几个概率,最后一比,就得到最终结果。
p(不帅、性格不好、身高矮、不上进|嫁) = p(不帅|嫁)*p(性格不好|嫁)*p(身高矮|嫁)*p(不上进|嫁),那么我就要分别统计后面几个概率,也就得到了左边的概率!
等等,为什么这个成立呢?学过概率论的同学可能有感觉了,这个等式成立的条件需要特征之间相互独立吧!
对的!这也就是为什么朴素贝叶斯分类有朴素一词的来源,朴素贝叶斯算法是假设各个特征之间相互独立,那么这个等式就成立了!
但是为什么需要假设特征之间相互独立呢?
1、我们这么想,假如没有这个假设,那么我们对右边这些概率的估计其实是不可做的,这么说,我们这个例子有4个特征,其中帅包括{帅,不帅},性格包括{不好,好,爆好},身高包括{高,矮,中},上进包括{不上进,上进},那么四个特征的联合概率分布总共是4维空间,总个数为2*3*3*2=36个。
24个,计算机扫描统计还可以,但是现实生活中,往往有非常多的特征,每一个特征的取值也是非常之多,那么通过统计来估计后面概率的值,变得几乎不可做,这也是为什么需要假设特征之间独立的原因。
2、假如我们没有假设特征之间相互独立,那么我们统计的时候,就需要在整个特征空间中去找,比如统计p(不帅、性格不好、身高矮、不上进|嫁),
我们就需要在嫁的条件下,去找四种特征全满足分别是不帅,性格不好,身高矮,不上进的人的个数,这样的话,由于数据的稀疏性,很容易统计到0的情况。 这样是不合适的。
根据上面俩个原因,朴素贝叶斯法对条件概率分布做了条件独立性的假设,由于这是一个较强的假设,朴素贝叶斯也由此得名!这一假设使得朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率。
好的,上面我解释了为什么可以拆成分开连乘形式。那么下面我们就开始求解!
求解过程就是用=贝叶斯定理与学到的联合概率模型进行分类预测,
将输入x分到后验概率最大的类y.
这个在统计学习方法中有推导,意思就是对每个参数都求最小,得到的就是最优结果
接下来贴上机器学习实战朴素贝叶斯的代码:
书上利用朴素贝叶斯进行文档分类 :首先收集数据,把数据做成数值型或者布尔型数据,分析数据时因为有大量的特征,绘制特征不好使,使用直方图比较好。计算不同的独立特征的条件概率,对测试数据计算错误率,得到文档分类。
1:要想从文本中获取特征,就要先拆分文本。这里首先给出将文本转换为数字向量的过程,将每一个文本片段表示为一个词条向量,值为1表示词条出现在文档中,0表示词条未出现。在此对类别标签设置为侮辱类和非侮辱类,使用0和1表示。
创建一些实验文本,返回的第一个变量是进行词条切分后的文档集合,文本被切分成一系列的词条集合,标点符号从文本中去掉,第二个是类别标签的集合。
2:创建一个包含在所有文档中出现的不重复词的列表,使用set数据类型,set将返回一个不重复词表。
3:使用词汇表或者想要检查的所有单词作为输入,然后为其中每个单词构建一个特征,一旦给定一篇文档,该文档将自动转化为词向量。
4:上面将一组单词转化为一组数字,接下来就是如何使用这些数字计算概率。由以上的程序可知,一个词是否出现在一篇文档中,也知道该文档所属的类别。
首先通过类别i(侮辱或非侮辱)中文档数除以总的文档数来计算概率p(ci),然后计算p(x|ci),这里用到朴素贝叶斯假设。如果将x展开为一个个独立的特征,那么就可以将上述概率写成p(x0,x1,x2…..xn|ci),所有词都互相独立,则称作条件独立性假设,意味着可以使用p(x0|ci)p(x1|ci)p(x2|ci)…..p(xn|ci)来计算上述概率。
p0Vect是一个向量,元素是每个词在该类别中出现的概率。p1Vect同上。
pAbusive是文档属于1的概率。
5:构建完整的分类器,就是编写分类函数。
6:现在将每个词的出现与否作为一个特征,这被描述为词集模型,但一个词在文档中出现不止一次,就要使用词袋模型,在词袋中,每个单词可以出现多次
#---------------------------从文本中构建词条向量------------------------- #1 要从文本中获取特征,需要先拆分文本,这里特征是指来自文本的词条,每个词 #条是字符的任意组合。词条可以理解为单词,当然也可以是非单词词条,比如URL #IP地址或者其他任意字符串 # 将文本拆分成词条向量后,将每一个文本片段表示为一个词条向量,值为1表示出现 #在文档中,值为0表示词条未出现 #导入numpy from numpy import * 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'], ['my','licks','ate','my','steak','how',\ 'to','stop','him'], ['quit','buying','worthless','dog','food','stupid']] #由人工标注的每篇文档的类标签 classVec=[0,1,0,1,0,1] return postingList,classVec #统计所有文档中出现的词条列表 def createVocabList(dataSet): #新建一个存放词条的集合 vocabSet=set([]) #遍历文档集合中的每一篇文档 for document in dataSet: #将文档列表转为集合的形式,保证每个词条的唯一性 #然后与vocabSet取并集,向vocabSet中添加没有出现 #的新的词条 vocabSet=vocabSet|set(document) #再将集合转化为列表,便于接下来的处理 return list(vocabSet) #根据词条列表中的词条是否在文档中出现(出现1,未出现0),将文档转化为词条向量 def setOfWords2Vec(vocabSet,inputSet): #新建一个长度为vocabSet的列表,并且各维度元素初始化为0 returnVec=[0]*len(vocabSet) #遍历文档中的每一个词条 for word in inputSet: #如果词条在词条列表中出现 if word in vocabSet: #通过列表获取当前word的索引(下标) #将词条向量中的对应下标的项由0改为1 returnVec[vocabSet.index(word)]=1 else: print('the word: %s is not in my vocabulary! '%'word') #返回inputet转化后的词条向量 return returnVec #训练算法,从词向量计算概率p(w0|ci)...及p(ci) #@trainMatrix:由每篇文档的词条向量组成的文档矩阵 #@trainCategory:每篇文档的类标签组成的向量 def trainNB0(trainMatrix,trainCategory): #获取文档矩阵中文档的数目 numTrainDocs=len(trainMatrix) #获取词条向量的长度 numWords=len(trainMatrix[0]) #所有文档中属于类1所占的比例p(c=1) pAbusive=sum(trainCategory)/float(numTrainDocs) #创建一个长度为词条向量等长的列表 p0Num=zeros(numWords);p1Num=zeros(numWords) p0Denom=0.0;p1Denom=0.0 #遍历每一篇文档的词条向量 for i in range(numTrainDocs): #如果该词条向量对应的标签为1 if trainCategory[i]==1: #统计所有类别为1的词条向量中各个词条出现的次数 p1Num+=trainMatrix[i] #统计类别为1的词条向量中出现的所有词条的总数 #即统计类1所有文档中出现单词的数目 p1Denom+=sum(trainMatrix[i]) else: #统计所有类别为0的词条向量中各个词条出现的次数 p0Num+=trainMatrix[i] #统计类别为0的词条向量中出现的所有词条的总数 #即统计类0所有文档中出现单词的数目 p0Denom+=sum(trainMatrix[i]) #利用NumPy数组计算p(wi|c1) p1Vect=p1Num/p1Denom #为避免下溢出问题,后面会改为log() #利用NumPy数组计算p(wi|c0) p0Vect=p0Num/p0Denom #为避免下溢出问题,后面会改为log() return p0Vect,p1Vect,pAbusive #朴素贝叶斯分类函数 #@vec2Classify:待测试分类的词条向量 #@p0Vec:类别0所有文档中各个词条出现的频数p(wi|c0) #@p0Vec:类别1所有文档中各个词条出现的频数p(wi|c1) #@pClass1:类别为1的文档占文档总数比例 def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1): #根据朴素贝叶斯分类函数分别计算待分类文档属于类1和类0的概率 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: #将每篇文档利用words2Vec函数转为词条向量,存入文档矩阵中 trainMat.append(setOfWords2Vec(myVocabList,postinDoc))\ #将文档矩阵和类标签向量转为NumPy的数组形式,方便接下来的概率计算 #调用训练函数,得到相应概率值 p0V,p1V,pAb=trainNB0(array(trainMat),array(listClasses)) #测试文档 testEntry=['love','my','dalmation'] #将测试文档转为词条向量,并转为NumPy数组的形式 thisDoc=array(setOfWords2Vec(myVocabList,testEntry)) #利用贝叶斯分类函数对测试文档进行分类并打印 print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAb)) #第二个测试文档 testEntry1=['stupid','garbage'] #同样转为词条向量,并转为NumPy数组的形式 thisDoc1=array(setOfWords2Vec(myVocabList,testEntry1)) print(testEntry1,'classified as:',classifyNB(thisDoc1,p0V,p1V,pAb)) def bagOfWords2VecMN(vocabList,inputSet): #词袋向量 returnVec=[0]*len(vocabList) for word in inputSet: if word in vocabList: #某词每出现一次,次数加1 returnVec[vocabList.index(word)]+=1 return returnVec
结果如下:
说明对于简单的样本,还是能正确分类的!
本期到此结束!
相关文章推荐
- 读书笔记:机器学习实战(3)——章4的朴素贝叶斯分类代码和个人理解与注释
- 机器学习实战_初识朴素贝叶斯算法_理解其python代码(二)
- 机器学习实战_初识朴素贝叶斯算法_理解其python代码(一)
- 机器学习实战笔记(3.1)-朴素贝叶斯算法(原理分析)
- 读书笔记:机器学习实战(1)——章2的knn代码和个人改进与注释
- 机器学习实战--基于概率论的分类方法:朴素贝叶斯
- 机器学习实战代码详解(12)使用FP-growth算法来高效发现频繁集
- 机器学习实战python版第三章决策树代码理解
- 机器学习之朴素贝叶斯模型及代码示例
- 机器学习实战 - 第九章树回归 代码运行报错原因
- 机器学习实战学习笔记8——朴素贝叶斯
- 机器学习实战-边学边读python代码(5)
- 代码注释:机器学习实战第6章 支持向量机
- 机器学习实战代码 第三章3-1注释
- 机器学习笔记:朴素贝叶斯方法(Naive Bayes)原理和实现
- 机器学习实战——朴素贝叶斯
- 机器学习实战:KNN 代码注释(python)
- 机器学习实战代码3-5
- 机器学习实战_初识kNN算法_理解其python代码
- 机器学习实战,第三章,临时代码