• 郑捷《机器学习算法原理与编程实践》学习笔记(第二章 中文文本分类(二)—朴素贝叶斯算法)


    (上接第二章)

      2.3 分类算法:朴素贝叶斯

      2.3.1 贝叶斯公式推导(略)

      分类的流程:  

      第一阶段:训练数据生成训练样本集:TF-IDF

      第二阶段:对每个类别计算p(yi)。

      第三个阶段:对每个特征属性计算所有划分的条件概率

      第四个阶段:对每个类别计算P(x|yi)P(yi)。

      第五个阶段:以P(x|yi)P(yi)的最大项作为x的所属类别。

      2.3.2  朴素贝叶斯算法实现

      创建Nbayes_lib.py的文件,这个文件用来导入数据和朴素贝叶斯类的代码。

      使用简单的英文语料作为数据集:

      

    def loadDataSet():
        postingList =[['my','dog','has','flea','problem','help','please'],
                      ['maybe','not','take','him','to','dog','park','stupid'],
                      ['my','dalmation','is','so','cute','I','love','him','my'],
                      ['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 is abusive,0 not
        return postingList,classVec

      posstingList 是训练集文本,classVec是每个文本对应的分类:

      (1)编写一个贝叶斯算法类,并创建默认的构造方法:

    class NBayes(object):
        def __init__(self):
            self.vocabulary = []        #词典
            self.idf        = 0         #词典的IDF权值向量
            self.tf         = 0         #训练值的权值矩阵
            self.tdm        = 0         #P(x|yi)
            self.Pcates     = {}        #P(yi)是一个类别字典
            self.labels     = []        #对应每个文本的分类,是一个外部导入的列表
            self.doclength  = 0         #训练集文本数
            self.vocablen   = 0         #词典词长
            self.testset    = 0         #测试集

      (2)导入和训练数据集,生成算法必需的参数和数据结构

    def train_set(self,trainset,classVec):
        self.cate_prob(classVec)       #计算每个分类在数据集中的概率P(yi)
        self.doclength       = len(trainset)
        tempset              = set()
        [tempset.add(word) for doc in trainset for word in doc]  #生成词典
        self.vocabulary      = list(tempset)
        self.vocablen        = len(self.vocabulary)
       self.calc_wordfreq(trainset)
       self.build_tdm() #按分类累计向量空间的每维值P(x|yi)

      (3)cate_prob函数:计算在数据集中每个分类的概率P(yi

    def cate_prob(self,classVec):
        self.labels          = classVec
        labeltemps           = set(self.labels)                   #获取全部分类
        for labeltemp in labeltemps:
            #统计列表中重复的分类:  self.labels.count(labeltemp)
            self.Pcates[labeltemp] = float(self.labels.count(labeltemp))/float(len(self.labels))

      (4)calc_wordfreq函数:生成普通的词频向量

      

    def calc_wordfreq(self,trainset):
        self.idf             = np.zeros([1,self.vocablen])        #1*词典数
        self.tf              = np.zeros([self.doclength,self.vocablen]) #训练集文件数*词典数
        for indx in xrange(self.doclength):                      #遍历所有的文本
            for word in trainset[indx]:                          #遍历文本中的每个词
                #找到文本的词在字典中的位置+1
                self.tf[indx,self.vocabulary.index(word)] += 1
            for signleword in set(trainset[indx]):               #idf词数
                self.idf[0,self.vocabulary.index(signleword)] += 1

      (5)Build_tdm函数:按分类累计计算向量空间的每维值P(x|yi

        def build_tdm(self):
            self.tdm = np.zeros([len(self.Pcates),self.vocablen])     #类别行*词典列
            sumlist  = np.zeros([len(self.Pcates),1])                #统计每个分类的总值
            for indx in xrange(self.doclength):
                #将同一类别的词向量空间值加总
                self.tdm[self.labels[indx]] += self.tf[indx]
                #统计每个分类的总值--是一个标量
                sumlist[self.labels[indx]]    = np.sum(self.tdm[self.labels[indx]])
            self.tdm = self.tdm/sumlist                              #生成P(x|yi)

      (6)map2vocab函数:将测试集映射到当前词典

       # (6)map2vocab函数:将测试集映射到当前词典
        def map2vocab(self,testdata):
            self.testset = np.zeros([1,self.vocablen])
            for word in testdata:
                self.testset[0,self.vocabulary.index(word)] += 1

      (7)predict函数:预测分类结果,输出预测的分类类别

      

     def predict(self,testset):
            if np.shape(testset)[1] != self.vocablen: #如果测试集长度与词典不相等,则退出程序
                print "输入错误"
                exit(0)
            predvalue = 0                             #初始化类别概率
            predclass = ""                            #初始化类别名称
            for tdm_vect,keyclass in zip(self.tdm,self.Pcates):
                #P(x|yi)*P(yi)
                #变量tdm,计算最大分类值
                temp = np.sum(testset*tdm_vect*self.Pcates[keyclass])
                if temp > predvalue:
                    predvalue = temp
                    predclass = keyclass
            return predclass

      2.3.3 算法的改进

      此算法的改进是为普通的词频向量使用TF-IDF策略,使之有能力修正多种偏差

      calc_tfidf函数:以TF-IDF方式生成向量空间。

      

    #生成tf-idf
    def calc_tfidf(self,trainset):
        self.idf = no.zeros([1,self.vocablen])
        self.tf  = np.zeros([self.doclength,self.vocablen])
        for indx in xrange(self.doclength):
            for word in trainset[indx]:
                self.tf[indx,self.vocabulary.index(word)] += 1
            #消除不同句长导致的偏差
            self.tf[indx] = self.tf[indx]/float(len(trainset[indx]))
            for signleword in set(trainset[indx]):
                self.idf[0,self.vocabulary.index(signleword)] += 1
        self.idf = np.log(float(self.doclength)/self.idf)
        self.tf  = np.multiply(self.tf,self.idf)    #矩阵与向量的点乘 TF*IDF

      2.3.4 评估分类结果

      

    #coding:utf-8
    import sys
    import os
    from numpy import *
    import numpy as np
    from Nbayes_lib import *
    #评估分类结果
    
    dataSet,listClasses = loadDataSet() #导入外部数据集
    #dataSet:句子的词向量
    #listClass是句子所属的类别[0,1,0,1,0,1]
    nb                  = NBayes()      #实例化
    nb.train_set(dataSet,listClasses)   #训练数据集
    nb.map2vocab(dataSet[0])            #随机选择一个测试语句
    print nb.predict(nb.testset)

    分类结果如下:
    1

      

      

    参考资料及版权所有:郑捷《机器学习算法原理与编程实践》

  • 相关阅读:
    centos7 修复引导
    Django 过滤器
    Django 面向对象orm
    Django models字段查询谓词表
    linux常用的监控命令
    常用SQL语句
    python实现FTP服务器
    用python做一个图片验证码
    rsync
    jsonp的理解
  • 原文地址:https://www.cnblogs.com/wuchuanying/p/6232282.html
走看看 - 开发者的网上家园