《机器学习实战》第四章----朴素贝叶斯

朴素贝叶斯

贝叶斯分类算法是一类基于贝叶斯定理的分类算法.朴素贝叶斯是贝叶斯算法中最简单的一种,也是常见的机器学习方法之一,它是基于概率的分类算法.

贝叶斯定理

贝叶斯定理可用以下公式表达:

P ( A | B ) = P ( B | A ) P ( A ) P ( B )

其中:

  • P ( A | B ) - 在事件B发生的情况下事件A发生的概率
  • P ( B | A ) - 在事件A发生的情况下事件B发生的概率
  • P ( A ) , P ( B ) - 独立事件A和B的边缘概率

朴素贝叶斯

朴素贝叶斯算法是贝叶斯算法的一种,之所以说其简单,是因为它不但符合贝叶斯定理,还多加了一条特征条件独立性假设.也就是各个特征是相互独立的.条件独立性假设可表达如下:

P ( X = x | Y = c k ) = P ( X ( 1 ) = x ( 1 ) , , X ( n ) = x ( n ) | Y = c k ) = j = 1 n P ( X ( j ) | Y = c k )

条件独立假设等于是说用于分类的特征在类确定的条件下都是条件独立的.这一假设使朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率.


算法实现

朴素贝叶斯算法的原理是很好理解的,在算法实现过程中需要注意的一点是:在条件独立性假设中,我们的概率 P ( X = x | Y = c k ) 是求乘积的形式,这样就会出现两种问题,如果有一个特征的概率为0,这样会导致整个概率为0,因此会初始化所有特征出现的次数为1或者2;当然,由于是乘积的形式,当概率都很小的时候,其乘积会非常小,导致程序算得的结果溢出,最终得到的值为0,因此对我们的乘积取log函数(这是由于log函数的乘法可以变为加法,且log函数为单调增函数).这在下面两段程序都有体现:


#INPUT:trainMatrix:所有样本的词汇集合,即是每个样本通过setOfWords2Vec后得到的集合 trainCategory:类别列表
#OUTPUT:p0Vect p1Vect pAbusive:类别0的条件概率p(w|c=0),类别1的条件概率p(w|c=1),类别概率p(c)
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] #统计类别1中每个单词(特征)出现的次数
            p1Denom += sum(trainMatrix[i])#p1Denom:类别1中单词的总数
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = log(p1Num/p1Denom) #类别1中每个单词(特征)的出现概率
    p0Vect = log(p0Num/p0Denom) #类别0中每个单词(特征)出现的概率
    return p0Vect,p1Vect,pAbusive

#INPUT:vec2Classify:输入词向量的word2vec模型 p0Vec,p1Vec,pClass1:p0Vect,p1Vect,pAbusive
#OUTPUT:输入词向量的类别
#Note:这里用log求和实际上进行合并,log(f),f是一个求乘积的运算,展开后是贝叶斯条件概率公式,分母p(w)对于分类来说是没有影响的
#同理,整个的概率log后也是对分类没影响的,因为p1和p0的相对大小不会变(log是个单调增函数,哪怕p1和p0都是负数)
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1 = sum(vec2Classify*p1Vec)+log(pClass1)
    p0 = sum(vec2Classify*p0Vec)+log(1.0-pClass1)
    if p1>p0:
        return 1
    else:
        return 0

最后要注意的是,由于使用了交叉验证,每次的训练集和测试集都不同,我们可以训练10次求一个分类准确率的平均值作为最终的分类准确率结果.
基于朴素贝叶斯算法的垃圾邮件分类代码在个人的Github上:朴素贝叶斯–垃圾邮件分类


参考资料:
朴素贝叶斯
深入理解朴素贝叶斯

猜你喜欢

转载自blog.csdn.net/qq_28773183/article/details/80781084