朴素贝叶斯

一、基于条件概率的分类

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

简单的说就是选择概率高所对应的类别,这就是贝叶斯决策理论的核心思想,选择最高概率的决策。

2.条件概率

什么是条件概率呢?简单的理解就是当一件事情发生时,另一件事情发生的概率。接下来就简单的讨论一下条件概率。

图中一共七个小球,我们很容易得到灰色石头的概率为p(gray)=3/7,黑色石头的概率p(black)=4/7。但是,将这七个球放入不同的桶中,又应该怎么求概率呢?

要想计算p(gray)和p(black),需要考虑到石头所在桶的信息,要计算从B桶中取到灰色石头的概率的方法。这就是条件概率,假定计算的是从B桶中取到灰色石头的概率的,可以记作p(gray|bucketB),称之为在已知石头出自B桶的条件下,取出灰色石头的概率。可以得到p(gray|bucketA)=2/4,p(gray|bucketB)=1/3。条件概率的计算公式如下:p(gray|bucketB)=p(gray and bucketB) / p(bucketB)。我们来验证一下这个公式。首先,用B桶中灰色石头的个数除以两个桶中总的石头数,得到p(gray and BucketB) = 1/7。其次,由于B桶中有3块石头,总石头数为7,于是选择B桶的概率为p(bucketB)=3/7。于是有p(gray|bucketB)=p(gray and bucketB) / p(bucketB)=(1/7)/(3/7)= 1/3。计算条件概率还有另外一种方法,就是贝叶斯准则。贝叶斯准则告诉我们如何交换条件概率中的条件与结果。即已知p(x|c), 要求p(c|x)。可以使用贝叶斯公式:p(c|x)=\frac{p(x|c)p(c)}{p(x)}

3.使用条件概率来分类

上边我们使用贝叶斯决策理论来计算概率进行分类,但是,那不是贝叶斯决策理论的全部内容,真正需要计算的是p(c_{1}|x,y)p(c_{2}|x,y),意义是给定某个数据点,该数据点来自c_{1}的概率是多少。我们可以通过贝叶斯准则计算:p(c_{i}|x)=\frac{p(x,y|c_{i})p(c_{i})}{p(x,y)}。最后分类的准则就为:

贝叶斯准则,可以通过已知的三个概率来计算未知的概率值。下面,我们就要使用贝叶斯准则计算概率并对数据进行分类。 

  • 如果p(c_{1}|x,y) > p(c_{2}|x,y),那么属于类别1
  • 如果p(c_{2}|x,y) > p(c_{1}|x,y),那么属于类别2

二、使用朴素贝叶斯进行文档分类

在文档分类中,整个文档是一个实例,而文档中的某些元素构成特征。我们观察文档中出现的词,并把每个词出现与不出现作为一个特征。这样得到的特征数目就会跟词汇表中的词目一样多。朴素贝叶斯中朴素的含义就是假设数据特征是相互独立的,即一个特征或者单词出现的可能性与它和其他单词相邻没有关系。另一个假设是每个特征是同等重要的。

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]   # 1代表侮辱性词汇,0代表正常言论
    return postingList, classVec

def createVocabList(dataSet):
    """ 创建词汇表 """
    vocabSet = set([])
    for document in dataSet:
        vocabSet = vocabSet | set(document)   # 合并两个集合,求并集
    return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet):
    """ 转换为词汇向量 """
    returnVec = [0] * len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
        else:
            print("the word: %s is not in my Vocabulary!" % word)
    return returnVec

2. 从词向量计算概率

根据贝叶斯公式计算条件概率,我们用w表示词向量,则计算条件概率的贝叶斯公式为:p(c_{i}|w)=\frac{p(w|c_{i})p(c_{i})}{p(w)},我们需要计算p(c_{i})p(w|c_{i})p(c_{i})。我们利用矩阵来实现计算过程。

def trainNB0(trainMatrix, trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory) / float(numTrainDocs) # 属于侮辱性文档的概率
    p0Num = ones(numWords)
    p1Num = ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.0
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = log(p1Num / p1Denom)  # 侮辱性文档中每个词出现的概率
    p0Vect = log(p0Num / p0Denom)  # 正常言论每个词出现的概率
    return p0Vect, p1Vect, pAbusive

我们首先计算侮辱性文档的概率,然后初始化计算单词个数的全为1的矩阵p0Num和p1Num,并初始化词的总数p0Denom和p1Denom。分别计算不同类别下每个词出现的概率,最后的概率做对数运算是因为方式小数相乘值溢出的情况。

3. 测试算法

我们根据计算好的概率,计算最后的条件概率并进行分类。最后,定义一个测试函数,测试我们的朴素贝叶斯分类器的效果

def classifyNB(vec2Classigy, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classigy * p1Vec) + log(pClass1)
    p0 = sum(vec2Classigy * 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))
    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))
testingNB()

结果:

['love', 'my', 'dalmation'] classified as: 0
['stupid', 'garbage'] classified as: 1 

三、使用朴素贝叶斯过滤垃圾邮件

使用朴素贝叶斯进行电子邮件的过滤是一个经典的应用。我们实现这个示例,从文本的切分开始,然后利用上边的相关函数实现。

代码链接:https://github.com/guoyuantao/MachineLearning/tree/master/Naive_Bayes

注意:此文章的内容参考《机器学习实战》。博客的主要目的为记录个人所学的知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值