机器学习实战--Task02:朴素贝叶斯

在这里插入图片描述

1.基于贝叶斯决策理论的分类方法

在这里插入图片描述
朴素贝叶斯是贝叶斯决策理论的一部分,所以讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论。
假设现在我们有一个数据集,它由两类数据组成,数据分布如图:
在这里插入图片描述
我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中三角形表示的类别)的概率,那么对于一个新数据点(x,y),可以用以下规则判断它的类别:

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

也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。
接下来,我们要详述p1及p2概率计算方法,下面将介绍条件概率。

2.条件概率

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.使用条件概率来分类

在这里插入图片描述
在这里插入图片描述
使用贝叶斯准则,可以通过已知的三个概率值来计算未知的概率值。后面就会给出利用贝叶斯准则来计算概率并对数据进行分类的代码。下一节将介绍一个简单但功能强大的贝叶斯分类器的应用案例。

4.使用朴素贝叶斯进行文档分类

机器学习的一个重要应用就是文档的自动分类。
在文档分类中,整个文档(如一封电子邮件)是实例,而电子邮件中的某些元素则构成特征。我们可以观察文档中出现的词,并把每个词的出现或者不出现作为一个特征,这样得到的特征数目就会跟词汇表中的词目一样多。朴素贝叶斯是贝叶斯分类器的一个拓展,是用于文档分类的常用算法。
在这里插入图片描述
假设词汇表中由1000个单词。要得到好的概率分布,就需要足够的数据样本,假定样本数为N。由统计学,如果每个特征需要N个样本,那么对于10个特征将需要N10个样本,对于包含1000个特征的词汇表将需要N^1000个样本(这个地方有点不太明白)。
如果特征之间相互独立,那么样本数就可以从N^1000减少到1000*N。所谓独立指的是统计意义上的独立,即一个特征或者单词出现的可能性与它和其他单词相邻没有关系。

5.使用python进行文本分类

要从文本中获取特征,需要先拆分文本
具体如何做呢?这里的特征是来自文本的词条,一个词条是字符的任意组合。可以把词条想象为单词,也可以使用非单词词条,如URL、IP地址或者其他任意字符串。然后将每一个文本片段表示为一个词条向量,其中值为1表示词条出现在文档中,0表示词条未出现。

接下来首先给出将文本转换为数字向量的过程,然后介绍如何基于这些向量来计算条件概率,并在此基础上构建分类器,最后还要介绍一些利用python实现朴素贝叶斯过程中需要考虑的问题。

(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]
    return postingList,classVec
def createVocabList(dataSet):
    vocabSet=set([])
    for document in dataSet:
        vocabSet=vocabSet | set(document)
    return list(vocabSet)
def set0fWords2Vec(vocabList,inputSet):
    returnVec=[0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]=1
        else:
            print("the word"+word+"is not in my Vocabulary!")
    return returnVec

listOPosts,listClasses=loadDataSet()
myVocabList=createVocabList(listOPosts)

myVocabList
Out[7]: 
['please',
 'cute',
 'love',
 'quit',
 'my',
 'ate',
 'park',
 'to',
 'food',
 'so',
 'not',
 'help',
 'mr',
 'licks',
 'problems',
 'stop',
 'steak',
 'dog',
 'how',
 'dalmation',
 'has',
 'him',
 'maybe',
 'is',
 'posting',
 'worthless',
 'garbage',
 'flea',
 'I',
 'buying',
 'stupid',
 'take']

set0fWords2Vec(myVocabList,listOPosts[0])
Out[8]: 
[1,
 0,
 0,
 0,
 1,
 0,
 0,
 0,
 0,
 0,
 0,
 1,
 0,
 0,
 1,
 0,
 0,
 1,
 0,
 0,
 1,
 0,
 0,
 0,
 0,
 0,
 0,
 1,
 0,
 0,
 0,
 0]

在这里插入图片描述

(2).训练算法:从词向量计算概率

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

from numpy import *
def trainNB0(trainMatrix,trainCategory):
    """
    分类器训练函数
    - - - -
    trainMatrix - 训练文档矩阵
	trainCategory - 训练类别标签向量,即classVec
    """
    #训练的文档数目
    numTrainDocs =len(trainMatrix)
    #词条数
    numWords = len(trainMatrix[0])
    #文档属于侮辱类的概率
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    #初始化概率
    p0Num = np.zeros(numWords)
    p1Num = np.zeros(numWords)
    p0Denom = 0.0
    p1Denom = 0.0
    for i in range(numTrainDocs):
        #统计属于侮辱类的条件概率所需的数据,即P(wi|1)
		if trainCategory[i] == 1:
			p1Num += trainMatrix[i]
			p1Denom += sum(trainMatrix[i])
        #统计属于非侮辱类的条件概率所需的数据,即P(wi|0)
		else:		
			p0Num += trainMatrix[i]
			p0Denom += sum(trainMatrix[i])
    #对每个元素做除法
    p1Vect = p1Num/p1Denom
    p0Vect = p0Num/p0Denom 
    return p0Vect,p1Vect,pAbusive
(3).测试算法:根据实际情况修改分类器

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

将trainNB0()对应部分修改为:

p0Num = np.ones(numWords)
p1Num = np.ones(numWords)
p0Denom = 2.0
p1Denom = 2.0

另一个遇到的问题是下溢出,这是由于太多很小的数相乘造成的。
一种解决办法是对乘积取自然对数。在代数中有ln(a*b) = ln(a)+ln(b),于是通过求对数可以避免下溢出或者浮点数舍入导致的错误。

将trainNB0()对应部分修改为:

p1Vect = np.log(p1Num/p1Denom)
p0Vect = np.log(p0Num/p0Denom)

最后分类和测试函数如下:

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    """
    朴素贝叶斯分类器分类函数
    - - - -
    vec2Classify - 待分类的词条数组

	p0Vec - 侮辱类的条件概率数组

	p1Vec -非侮辱类的条件概率数组

	pClass1 - 文档属于侮辱类的概率
    """
    p1 = np.sum(vec2Classify * p1Vec) + np.log(pClass1)
    p0 = np.sum(vec2Classify * p0Vec) + np.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(np.array(trainMat),np.array(listClasses))
    
    #测试样本1
    testEntry = ['love', 'my', 'dalmation']
    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
    print (testEntry,'classified as:' ,classifyNB(thisDoc,p0V,p1V,pAb))
   
    #测试样本2
    testEntry = ['stupid', 'garbage']										
    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
    print (testEntry,'classified as:' ,classifyNB(thisDoc,p0V,p1V,pAb))
#['love', 'my', 'dalmation'] classified as: 0
#['stupid', 'garbage'] classified as: 1
(5).准备数据:文档词袋模型

目前为止,我们将每个词的出现与否作为一个特征,这可以被描述为词集模型(set-of-wordsmodel)。
如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,这种方法被称为词袋模型(bag-of-words model)。

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

def bagOfWords2VecMN(vocabList, inputSet): 
    """
    根据词汇表,将inputSet向量化(词袋化)
    - - - -
    vocabList - 词汇表

    inputSet - 切分的词条列表
    """
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList: 
            returnVec[vocabList.index(word)] += 1
    return returnVec

小结
还有过滤垃圾邮件实例没有看,未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值