第2关:基于朴素贝叶斯的文本分类

文章介绍了如何利用朴素贝叶斯理论进行文本分类,包括贝叶斯决策理论的基础,特征独立假设,以及文本分类的三个步骤:拆分文本、数字化构建词向量、计算条件概率并分类。通过训练数据计算概率,然后对新文本进行分类决策。
摘要由CSDN通过智能技术生成

任务描述

本关任务:根据本关所学有关朴素贝叶斯的知识,编写基于朴素贝叶斯理论进行文本分类的程序,并通过所有测试用例。

相关知识

为了完成本关任务,你需要掌握:

  1. 贝叶斯决策理论思想;

  2. 朴素贝叶斯分类器的实现。

贝叶斯决策理论

在学习朴素贝叶斯分类之前,我们先回顾一下贝叶斯决策理论和条件概率。贝叶斯决策理论的核心思想是选择最高概率对应的类别,也就是选择具有最高概率的决策。贝叶斯准则是计算条件概率的有效方法,可以告诉我们如何交换条件概率中的条件与结果,即如果已知P(X∣C),要求P(C∣X),那么就可以使用下面的计算方法: P(Ci​∣X)=P(X)P(X∣Ci​)P(Ci​)​

假设我们有一个二维数据集,由两类数据组成,现在我们结合贝叶斯决策理论使用条件概率来给这些数据点分类。即给定数据点(x,y),判断是属于类别1还是类别2的方法是,分别计算该数据点来自类别1和来自类别2的概率。所以真正需要比较的是P(C1​∣x,y)和P(C2​∣x,y)。若已知从给定类别中取出该数据的概率,即P(x,y∣Ci​),应用贝叶斯准则可以得到: P(Ci​)=P(x,y)P(x,y∣Ci​)​

当P(C1​∣x,y)>P(C2​∣x,y),那么属于类别1; 当P(C2​∣x,y)>P(C1​∣x,y),那么属于类别2;

以上是贝叶斯准则的简要理论,我们在对文档进行分的类常用算法朴素贝叶斯分类- 器中“朴素”一词基于两个假设:

  • 特征之间相互独立,在上述二维数据中的体现就是 x 与 y 相互独立;
  • 每个特征同等重要。即 x 与 y 有同样的重要性。

在应用于文档分类时,尽管很多情况下特征难以完全符合上述假设,但朴素贝叶斯的实际效果却很好。接下来我们将介绍如何使用朴素贝叶斯理论进行文本分类。

朴素贝叶斯分类器的实现

在文档分类中,整个文档(如一封电子邮件)是实例,文档中的某些元素构成特征。我们把每个词的出现或不出现作为一个特征。整个文本分类的过程分为三步:

  • 拆分文本,获取特征。在英文文档分类中,特征来自文本的词条(token),一个词条可以是单词,也可以是 URL、IP 地址等任意其他字符串;

  • 将文本数字化,构建词向量。每一个文本片段表示为一个词条向量,其中值为1表示词条出现在文档中,0表示词条未出现;

  • 计算条件概率并分类。应用朴素贝叶斯分类原理,通过词向量计算条件概率。这里w是一个向量,由多个数值组成,它代表着由多个单词组成的一段文本或者一组单词。

基于朴素贝叶斯理论进行文本分类的具体实现: 1、准备数据,从文本中构建词向量 先将所有文档中出现过的词构建词汇表,然后把每篇文档中的词转换成词汇表上的向量。

  1. def setofWords2Vec(vocabList,inputSet): # 将每个文档转换成词向量
  2. returnVec=[0]*len(vocabList) # 创建一个与词汇表等长且所有元素都为0的向量
  3. for word in inputSet: # 遍历文档
  4. if word in vocabList: # 若文档中出现词表中的词
  5. returnVec[vocabList.index(word)]=1 # 则文档向量中的对应值设为1
  6. else:
  7. print ("the word: %s is not in my Vocabulary!" % word)
  8. return returnVec # 得到的与词汇表同等长度的词向量

2、从词向量计算概率 要得到类别概率值,首先需要计算P(W∣Ci​)和P(Ci​)。P(Ci​)容易获得,用文档数除以总文档数即可,再计算P(W∣Ci​)。朴素贝叶斯中假设特征相互独立,这里体现为每个词条相互独立。将P(W∣Ci​)展开成P(W0​,W1​,W2​,...,Wn​∣Ci​),根据假设: P(W0​,W1​,W2​,...,Wn​∣Ci​)=P(W0​∣Ci​)P(W1​∣Ci​)P(W2​∣Ci​)...P(Wn​∣Ci​) 我们可以计算上述概率,参考代码如下:

  1. for i in range(numTrainDocs):
  2. if trainCategory[i]==1: #如果是负面文档
  3. p1Num+=trainMatrix[i] #文档对应的词语数量全部加1,向量相加
  4. p1Denom+=sum(trainMatrix[i]) #负面文档词语的总数量
  5. else:
  6. p0Num+=trainMatrix[i] #正常文档对应的词语数量向量
  7. p0Denom+=sum(trainMatrix[i]) #正常文档词语的总数量
  8. p1Vect=p1Num/p1Denom
  9. p0Vect=p0Num/p0Denom

3、进行分类 准备好概率向量和文档概率后,按照贝叶斯准则公式将上述概率进行计算,得到朴素贝叶斯分类函数从而进行分类。参考代码如下:

  1. #计算各概率向量的乘积
  2. if len(p0Cond): # 若p0Cond不为空,即p0VectClassify不全为0
  3. pC0=reduce(operator.mul, p0Cond, 1) # 计算概率向量内元素乘积
  4. else:
  5. pC0=0
  6. if len(p1Cond): # 计算概率
  7. pC1=reduce(operator.mul, p1Cond, 1)
  8. else:
  9. pC1=0
  10. p1=pC1*pAb
  11. p0=pC0*(1.0-pAb)
  12. if p1 > p0: # 基于朴素贝叶斯理论进行概率比较
  13. return 1
  14. else:
  15. return 0

编程要求

在右侧编辑器中的 Begin-End 之间补充 Python 代码,完成基于朴素贝叶斯对所输入文本进行文本分类,并输出文本分类结果。其中文本内容通过 input 从后台获取。

测试说明

平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。

测试输入:

  1. has flea
  2. maybe not take him

预期输出:

  1. 分类结果为: # 由人工标注的文本类别,0代表负面文字,1代表普通文字
  2. ['has', 'flea']: 0
  3. ['maybe', 'not', 'take', 'him']: 1

参考代码:

from functools import reduce
import operator
from numpy import array, zeros

def trainNB(trainMatrix, trainCategory):
    numTrainDocs = len(trainMatrix)  # 文档数量
    numWords = len(trainMatrix[0])  # 第一篇文档的长度,也就是词汇表的长度
    pAbusive = sum(trainCategory) / float(numTrainDocs)  # 负面文档占总文档比例
    p0Num = zeros(numWords)  # 初始化概率
    p1Num = zeros(numWords)
    p0Denom = 0
    p1Denom = 0
    
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:  # 如果是负面文档
            p1Num += trainMatrix[i]  # 文档对应的词语数量全部加1,向量相加
            p1Denom += sum(trainMatrix[i])  # 负面文档词语的总数量
        else:
            p0Num += trainMatrix[i]  # 正常文档对应的词语数量向量
            p0Denom += sum(trainMatrix[i])  # 正常文档词语的总数量
            
    p1Vect = p1Num / p1Denom   # 对p1Num的每个元素做除法,即负面文档中出现每个词语的概率
    p0Vect = p0Num / p0Denom   # 对p0Num的每个元素做除法,即正常文档中出现每个词语的概率
    return p0Vect, p1Vect, pAbusive
    
def classifyNB(vec2Classify, trainMatrix, trainCategory):
    p0Vect, p1Vect, pAb = trainNB(trainMatrix, trainCategory)
    # 计算待分类文档词条对应的条件概率
    p1VectClassify = vec2Classify * p1Vect  
    p0VectClassify = vec2Classify * p0Vect
    p1Cond = [];
    p0Cond = []
    
    for i in range(len(p1VectClassify)):
        if p1VectClassify[i] == 0:
            continue
        else:
            p1Cond.append(p1VectClassify[i])
            
    for i in range(len(p0VectClassify)):
        if p0VectClassify[i] == 0:
            continue
        else:
            p0Cond.append(p0VectClassify[i])
    # 任务:完成对各概率向量的计算
    # ********** Begin *********#
    if len(p0Cond):                        # 若p0Cond不为空,即p0VectClassify不全为0
        pC0=reduce(operator.mul, p0Cond, 1) # 计算概率向量内元素乘积
    else:
        pC0=0
    if len(p1Cond):   # 计算概率
        pC1=reduce(operator.mul, p1Cond, 1)
    else:
        pC1=0
    p1=pC1*pAb 
    p0=pC0*(1.0-pAb)
    # ********** End **********#
    if p1 > p0:
        return 1
    else:
        return 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

畜牧当道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值