美文网首页
一.朴素贝叶斯进行文本分类

一.朴素贝叶斯进行文本分类

作者: 编号633 | 来源:发表于2018-03-12 18:56 被阅读0次

    最近在做一个商品评论分类的需求,主要是将商品的差评根据主题进行多次二分类,例如评论的内容是不是质量问题,物流问题等。

    由于对机器学习属于小白水平,所以先从最简单的朴素贝叶斯算法下手。

    优点:易懂易实现,文本容易向量化    

    缺点:分类效果一般

    朴素贝叶斯算法是用统计学的方法来对数据进行二分类,其主要思想就是贝叶斯公式,这个公式大学本科就学过,所以它的原理很容易理解,

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

    即 事件A在事件B发生的前提下发生的概率=事件A在事件B发生的前提下发生的概率*事件B发生的概率/事件A发生的概率。

    我们这里的事件主要是两类:

     1)这个评论是A分类的概率是多大,记做P(A)

     2)某个词Bi在A分类下出现的概率是多大,记做P(Bi|A),其中i为某个词 

    通过大数定律可知,当样本的数量足够大,某件事情发生的概率是收敛于这件事发生的期望的。所以当训练样本数量足够多时,我们就可以把某件事发生的概率近似作为期望。而上述两类事情的概率,都是可以通过训练集统计到的。然后对于一个新的文本,可以根据它的词向量来判断各种分类的概率,然后取最大概率的分类即可。

    一.文本分词

    使用python的结巴中文分词库对文本进行处理,由于评论主要是用户的主观感受,文本异常字符较多,所以这里需要对文本进行清洗,例如特殊字符,标点符号,停用词等;而对于某些领域,需要自己添加分词词典,方便提取有用的关键词(这里不考虑词频,所以分词的最终结果都做去重处理)。

    训练集分词前:

    训练集分词后:

    二.构建分词向量

    首先创建一个所有评论中不重复词的列表,然后向量化所有的评论,函数代码如下:

    def setOfWords2Vec(vocabList,inputSet):

          returnVec=[0]*len(vocabList)

          for word in inputSet:

              if word in vocabList:

                  returnVec[vocabList.index(word)]=1

              else:

                  pass

                  # print "the word:%s is not in myVocabulary!" % word

          return returnVec

    其中 vocabList为所有训练集中不重复词的列表,可以选择集合作为它的数据类型,由于集合中每个元素都是唯一的,所以不需要考虑去重的问题。inputSet为评论分词后的结果,这样就将一个评论转化为一个向量,对于测试集或测试数据中的词如果在vocabList不存在则不予考虑。这个向量的维数就是vocabList的长度,如果某个词存在,则这个词的位数为1,否则为0.

    选中20条评论作为训练数据,一共分出了129个词,生成的词向量组成的矩阵为20*129

    三.训练  

    根据上文的描述,假设 P(A)表示这个评论是A分类的概率是多大,P(Bi|A)表示在A分类的前提下词Bi出现的概率,则向量B在A分类下的概率为P(B|A)=P(b0,b1,b2...bn|A),假设所有的词都互相独立,则上面的表达式也可写为P(b0|A)P(b1|A)P(b2|A)...P(bn|A)。根据训练数据,可以求出P(A),P(bi|A)。

    若要判断一个向量C是属于A1还是A2,则求出向量C是A1和A2分类的概率并比较大小,哪个类别的概率大,则将其归为哪个类。其中:

    P(A1|C)=P(C|A1)*P(A1)/P(C)

    P(A2|C)=P(C|A2)*P(A2)/P(C)

    要比较P(A1|C)和P(A2|C)的大小,只需要比较P(C|A1)*P(A1)和P(C|A2)*P(A2)的大小即可。

    #朴素贝叶斯分类器训练函数,trainCategory为分类数组,trainMatrix为所有的评论向量

    def trainNB0(trainMatrix,trainCategory):

        numTrainDocs=len(trainMatrix)

        numWords=len(trainMatrix[0])

        #pAbusive表示为所有评论中出现,是该分类的概率

        pAbusive=sum(trainCategory)/float(numTrainDocs)

        p0Num=zeros(numWords);p1Num=zeros(numWords) #p0Num和p1Num为两个全0数组,长度为numWords,

        # 这两个向量用来统计P0分类中每个词的个数和P1中每个词的个数

        p0Denom=0.0;p1Denom=0.0#初始化

        #for循环扫描每一个评论生成的向量

        for i in range(numTrainDocs):

            # 如果向量判定为1,p1Num加上每个词的个数

            if trainCategory[i]==1:

                p1Num =p1Num+trainMatrix[i]

                #p1Denom是词向量中关键词的个数

                p1Denom =p1Denom+sum(trainMatrix[i])

            # 如果向量判定为0,p1Num加上每个词的个数

            else:

                p0Num =p0Num+ trainMatrix[i]

                p0Denom =p0Denom+ sum(trainMatrix[i])

        p1Vect=p1Num/p1Denom

        p0Vect=p0Num/p0Denom

        return p0Vect,p1Vect,pAbusive

    p0Vect:P0分类下每个词的概率

    p1Vect:P1分类下每个词的概率

    pAbusive:P1分类的概率。

    上面的算法有两个问题:

    1)P(b0|A)P(b1|A)P(b2|A)...P(bn|A),如果其中一个概率值为0,那么最后的乘积也为0,所以我们将所有词的出现次数初始化为1,将出现的总次数初始化为2

     p0Num=ones(numWords);p1Num=ones(numWords)

     p0Denom=2.0;p1Denom=2.0

    2)P(b0|A)P(b1|A)P(b2|A)...P(bn|A)大部分因子都很小,所以结果很容易四舍五入得到0,为了降低这种影响,我们对其取对数则,虽然函数并不一样,但是对他们比较大小的结果并不影响,所以

     p1Vect=log(p1Num/p1Denom)

     p0Vect=log(p0Num/p0Denom)

    四.分类

    传入一个新的向量,判断它是那种分类,即比较P(A1|C)和P(A2|C)的大小

    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

    其中vec2Classify为需要判定的向量,p0Vec表示每个词在分类0中的概率的对数向量,p1Vec表示每个词在分类1中的对数向量,pClass1为分类为1的概率,由于是二分类问题,可知pClass0=1-pClass1

    由于p0Vec和p1Vec是概率的对数,所以对概率的乘积大小比较和对其对数求和的大小比较,结果是一致的。

    五.测试正确率

    将测试数据进行判定,将返回的结果值和人工判定值进行对比,如果结果一致则表示分类成功。

    def testing(testVec,predictVec):

        vecLen=len(testVec)

        count=0.0

        for i in range(vecLen):

            if testVec[i]-predictVec[i]==0:

                count=count+1

        return count/vecLen

    testVec表示人工判定的分类向量,predictVec表示算法判定的分类向量,即可算出正确率。

    #分类效果不能令人满意,需要继续尝试其他方法。

    相关文章

      网友评论

          本文标题:一.朴素贝叶斯进行文本分类

          本文链接:https://www.haomeiwen.com/subject/ecrofftx.html