朴素贝叶斯(naive Bayes)原理与应用

本文介绍了朴素贝叶斯分类方法及其在文本分类中的应用,包括模型导出、学习描述及一个具体的句子情感色彩分类实例。

**

说明

**:
本文系转载,原作者博客:
http://blog.youkuaiyun.com/tanhongguang1/article/details/45016421

我稍微做了一些补充: naive Bayes实际上就是要求一组后验概率,有多少个呢?
咱们假设样本共有K个类别,样本的特征维度是M,每个维度上取值(离散)有Ci个,则总共要计算的厚颜概率有这么多个:
这里写图片描述

本文主要描述了朴素贝叶斯分类方法,包括模型导出和学习描述。实例部分总结了《machine learning in action》一书中展示的一个该方法用于句子感情色彩分类的程序。1

  • 方法概述
  • 学习(参数估计)
  • 实现:朴素贝叶斯下的文本分类

模型概述

朴素贝叶斯方法,是指
朴素:特征条件独立
贝叶斯:基于贝叶斯定理

根据贝叶斯定理,对一个分类问题,给定样本特征x,样本属于类别y的概率是

p(y|x)=p(x|y)p(y)p(x)1
在每一类的条件概率就可以了。类别y的先验概率可以通过训练集算出,同样通过训练集上的统计,可以得出对应每一类上的,条件独立的特征对应的条件概率向量。
如何统计,就是下一部分——学习——所关心的内容。

学习(参数估计)

下面介绍如何从数据中,学习得到朴素贝叶斯分类模型。概述分类方法,并提出一个值得注意的问题。

学习

训练集TrainingSet= {(x1,y1),(x2,y2),...,(xN,yN)}为指示函数,若括号内成立,则计1,否则为0。

学习 2.接下来计算分子中的条件概率,设M

经过上述步骤,我们就得到了模型的基本概率,也就完成了学习的任务。

分类

通过学到的概率,给定未分类新实例 X
于是我们得到了新实例的分类结果

拉普拉斯平滑

到这里好像方法已经介绍完了,实则有一个小问题需要注意,在公式(3)(4)中,如果从样本中算出的概率值为0该怎么办呢? 下面介绍一种简单方法,给学习步骤中的两个概率计算公式,分子和分母都分别加上一个常数,就可以避免这个问题。更新过后的公式如下:
p(y=ck)=Ni=1Iyi=ck+λN+Kλ7
维特征的最大取值

可以证明,改进以后的(7)(8)仍然是概率。平滑因子λ=0则避免了0概率问题,这种方法被称为拉普拉斯平滑

实现:朴素贝叶斯下的文本分类

根据上面的算法流程,在这里实现一个句子极性划分的例子。所谓句子极性是指,句子所表达的情感色彩,例如积极/消极,这里(书里)使用的是侮辱性/非侮辱性。其实是什么类别不重要,只要给定有标签的训练数据,就可以得到分类模型。
下面简述实现思想和流程,给出代码。

算法思想和流程

给定的训练集是标定了 侮辱性/非侮辱性 的句子(因为是英语句子,所以基本视分词为已经解决的问题,如果是汉语,则要先进行分词),我们认为特征就是句子中的单个词语。单个词语有极性表征,整个句子所包含的单词的极性表征就是句子的极性。 由以上的基础,应用朴素贝叶斯分类,就变成了这样的问题
初始化步,构建可以表征句子的特征向量(词汇表)。并根据这个特征向量,把训练集表征出来。从训练集中分离部分数据作为测试集。
学习步,计算 类的先验概率特征向量对应每一类的条件概率向量
分类步, 计算测试集中待分类句子在每一类的分类后验概率,取最大值作为其分类,并与给定标签比较,得到误分类率。

代码

初始化:

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 bagOfWord2VecMN(vocabList,inputSet):#根据词汇表,讲句子转化为向量
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

训练:

def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    p0Num = ones(numWords);p1Num = ones(numWords)#计算频数初始化为1
    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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

分类:

def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)#注意
    p0 = sum(vec2Classify * p0Vec) + log(1-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(trainMat,listClasses)#训练
    #测试
    testEntry = ['love','my','dalmation']
    thisDoc = setOfWords2Vec(myVocabList,testEntry)
    print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

注意:上述代码中标有注意的地方,是公式中概率连乘变成了对数概率相加。此举可以在数学上证明不会影响分类结果,且在实际计算中,避免了因概率因子远小于1而连乘造成的下溢出。



  1. 参考:
    李航. (2012). 统计学习方法.
    Harrington, P. (2013). 机器学习实战. 人民邮电出版社, 北京
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值