主要内容:

一.贝叶斯公式与朴素贝叶斯法

二.先验概率与后验概率

三.极大似然估计与贝叶斯估计

四.利用朴素贝叶斯进行文档分类

五.利用朴素贝叶斯进行垃圾邮件过滤

六.补充

 

 

一.贝叶斯公式与朴素贝叶斯法

1.贝叶斯公式

《机器学习实战》学习笔记第四章 —— 朴素贝叶斯法

2.朴素贝叶斯:假定所有变量X都相互独立(条件独立性),那么上式中的P(X|Y)可以变为:

《机器学习实战》学习笔记第四章 —— 朴素贝叶斯法

这是一个较强的假设,即假设比较简单直接、没有考虑太多因素。但正因如此,模型包含的条件概率的数量大为减少,朴素贝叶斯法的学习与预测大为简化。

因而朴素贝叶斯法高效,且易于实现;缺点是分类的性能不一定很高。

3.在使用朴素贝叶斯法时,我们要做的就是计算[P(Y0|X)、P(Y1|X)、……P(Yn|X)],然后选取概率最大的那一个分类,作为输入值的分类。

在计算P(Yi|X)时,根据贝叶斯公式,都需要除以相同的值P(X),但由于我们只需要比较大小,而不需要求出具体的值,所以可以免去这一步,所以总体而言,朴素贝叶斯法就是:

《机器学习实战》学习笔记第四章 —— 朴素贝叶斯法

可以看出,在朴素贝叶斯法中,我们需要计算两类值:P(Y)和P(X|Y)。

 

 

二.先验概率与后验概率

1.先验概率:根据以往经验和分析得到的概率。

2.后验概率:事情已经发生,要求这件事情发生的原因是由某个因素引起的可能性的大小。

如贝叶斯公式中:P(Y|X) = P(X|Y)*P(Y)/P(X)

P(X)、P(Y)是根据以往大量的经验而获得的概率,因此他们是先验概率(P(X|Y)这一个条件概率应该也是先验概率?)

而P(Y|X)则是:在X已经发生的情况下,问其是由Y引起的概率。即由果溯因,为后验概率。

 

 

三.极大似然估计与贝叶斯估计

1.极大似然估计(也是最普通的做法):

《机器学习实战》学习笔记第四章 —— 朴素贝叶斯法

其算法流程如下:

《机器学习实战》学习笔记第四章 —— 朴素贝叶斯法

 

2.贝叶斯估计(对极大似然估计的优化):

《机器学习实战》学习笔记第四章 —— 朴素贝叶斯法

 

 

四.利用朴素贝叶斯进行文档分类

  1 # coding:utf-8
  2 '''
  3 Created on Oct 19, 2010
  4 @author: Peter
  5 '''
  6 from numpy import *
  7 
  8 '''创造一些数据'''
  9 def loadDataSet():
 10     postingList = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
 11                    ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
 12                    ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
 13                    ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
 14                    ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
 15                    ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
 16     classVec = [0, 1, 0, 1, 0, 1]  # 相应的标签,1是带有侮辱性的,0不带侮辱性
 17     return postingList, classVec
 18 
 19 '''创建单词表,先用set去重,然后再以list的形式返回'''
 20 def createVocabList(dataSet):
 21     vocabSet = set([])  # create empty set
 22     for document in dataSet:
 23         vocabSet = vocabSet | set(document)  # union of the two sets
 24     return list(vocabSet)
 25 
 26 '''返回一个01列表,表示单词表中的某个单词是否出现在inputSet中'''
 27 def setOfWords2Vec(vocabList, inputSet):
 28     returnVec = [0] * len(vocabList)
 29     for word in inputSet:
 30         if word in vocabList:
 31             returnVec[vocabList.index(word)] = 1
 32         else:
 33             print "the word: %s is not in my Vocabulary!" % word
 34     return returnVec
 35 
 36 '''文档词袋模型,即把原来“单词是否出现在文档上”改为“单词在文档上出现了几次”'''
 37 def bagOfWords2VecMN(vocabList, inputSet):
 38     returnVec = [0] * len(vocabList)
 39     for word in inputSet:
 40         if word in vocabList:
 41             returnVec[vocabList.index(word)] += 1   #把原先的 “=1”改为“+=1”
 42     return returnVec
 43 
 44 '''求出P(c1)、P(w|c1)、P(w|c0).   当P(c1)求出时,P(c0) = 1-P(c1)'''
 45 '''其中P(w|c1)是一个列表,等于[P(w1|c1),P(w2|c1),P(w3|c1)……],P(w|c0)也是一个列表;P(c0)为一个实数'''
 46 def trainNB0(trainMatrix, trainCategory):
 47     numTrainDocs = len(trainMatrix)     #训练数据集的大小,即第一维
 48     numWords = len(trainMatrix[0])      #一条训练数据集的特征数,也就是单词表的长度,即第二维
 49     pAbusive = sum(trainCategory) / float(numTrainDocs)  #P(c1)
 50     '''
 51         以下是计算P(w|c1)、P(w|c0)的初始化阶段。
 52         在计算P(w1|c1)*P(w2|c0)*……时,如果其中一个为0,那么结果就为0,为了降低这种影响,
 53         可使用拉普拉斯平滑:分子初始化为1,分母初始化为2(有几个分类就初始化为几。这里有两个分类,所以初始化为2)
 54     '''
 55     p0Num = ones(numWords)
 56     p1Num = ones(numWords)
 57     p0Denom = 2.0
 58     p1Denom = 2.0
 59     ''''''
 60     for i in range(numTrainDocs):
 61         if trainCategory[i] == 1:
 62             p1Num += trainMatrix[i]
 63             p1Denom += sum(trainMatrix[i])
 64         else:
 65             p0Num += trainMatrix[i]
 66             p0Denom += sum(trainMatrix[i])
 67     '''
 68         以下是计算P(w|c1)、P(w|c0)的最终部分。
 69         在计算P(w1|c1)*P(w2|c0)*……时,由于太多很小的数相乘,很容易造成下溢,当四舍五入时结果就很可能为0,
 70         解决办法是对乘积取对数,就有:ln(ab) = lna+lnb把“小数相乘”转化为小数相加,避免了下溢。
 71         由于x与lnx在x>0处有相同的增减性,两者的最值不相同,但最值点是相同的,所以不会影响最终的分类。
 72     '''
 73     p1Vect = log(p1Num / p1Denom)  # P(w|c1)
 74     p0Vect = log(p0Num / p0Denom)  # P(w|c0)
 75     ''''''
 76     return p0Vect, p1Vect, pAbusive
 77 
 78 '''利用朴素贝叶斯进行分类,其中vec2Classify为输入数据,他是有关单词表的01串,
 79 p0Vec, p1Vec, pClass1则为trainNB0()的3个返回值,即P(w|c0)、P(w|c1)、P(c1)'''
 80 def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
 81     '''
 82         vec2Classify * p1Vec是什么意思?
 83         可知p1Vec为训练数据集中的P(w|c1),它是一个列表(对应着单词表)。在计算P(w|c1)时,每一个单词的概率即P(wi|c1)都计算了,
 84         但对于输入数据而言,有些单词出现了,有些单词没有出现,而我们只需要计算基础了的单词,所以要乘上系数ec2Classify
 85     '''
 86     '''
 87         sum(vec2Classify * p1Vec)计算的是P(w|c1),log(pClass1)计算的是P(c1)
 88         按照贝叶斯公式,理应还要减去P(w)的那一部分。但由于p1、p0都需要减去这一部分的值,
 89         且我们只需要比较p1、p0的大小而不需求求出具体的值,所以可以省去这一部分的计算
 90     '''
 91     p1 = sum(vec2Classify * p1Vec) + log(pClass1)  # element-wise mult
 92     p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
 93     if p1 > p0:
 94         return 1
 95     else:
 96         return 0
 97 
 98 def testingNB():
 99     listOPosts, listClasses = loadDataSet()         #提取数据
100     myVocabList = createVocabList(listOPosts)
101     trainMat = []
102     for postinDoc in listOPosts:        #数据加工,trainMat、listClasses为训练数据集,其中trainMat为特征X,listClasses为标签Y
103         trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
104     p0V, p1V, pAb = trainNB0(array(trainMat), array(listClasses))       #计算出概率P(c1)、P(w|c1)、P(w|c0)
105     testEntry = ['love', 'my', 'dalmation']     #测试数据
106     thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
107     print testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb)
108     testEntry = ['stupid', 'garbage']
109     thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
110     print testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb)
111 
112 if __name__=="__main__":
113     testingNB()
View Code

相关文章:

  • 2021-10-30
  • 2021-12-16
  • 2021-11-01
  • 2021-06-18
  • 2021-11-16
  • 2022-12-23
  • 2021-09-25
猜你喜欢
  • 2022-01-14
  • 2022-12-23
  • 2022-12-23
  • 2022-03-05
  • 2021-08-17
  • 2021-09-13
相关资源
相似解决方案