zoukankan      html  css  js  c++  java
  • 分类算法——朴素贝叶斯算法python实现(文末附工程代码)

    前言

    朴素贝叶斯是一种十分简单的分类算法,称其朴素是因为其思想基础的简单性,就文本分类而言,他认为词袋中的两两词之间的关系是相互独立的,即一个对象的特征向量中的每个维度都是互相独立的。这是朴素贝叶斯理论的思想基础。

    贝叶斯公式推导

    朴素贝叶斯分类的正式定义:

    1. 设x={}为一个待分类项,而每个a为x的一个特征属性
    2. 有类别集合C={}
    3. 计算P(|x),P(|x),…,P(|x)
    4. 如果P(|x)=max{ P(|x),P(|x),…,P(|x)},则x

    那么关键就是如何计算第三步中的各个条件概率,我们可以这样计算:

    1. 找到一个已知分类的待分类项集合,即训练集
    2. 统计得到在各类别下各个特征属性的条件概率估计,即:

    P(),P(),…,P()

    P(),P(),…,P()

    P(),P(),…,P()

    1. 如果各个特征属性是条件独立的(或者假设他们之间是相互独立的),根据贝叶斯定理,有如下推导:

    因为分母对于所有类别为常数,只要将分子最大化即可,又因为各特征属性是条件独立的,所以有:

    根据上述分析,朴素贝叶斯分类的流程可以表示如下:

    1. 训练数据生成样本集:TF-IDF
    2. 对每个类别计算P()
    3. 对每个特征属性计算所有划分的条件概率
    4. 对每个类别计算P(x|)P()
    5. 以P(x|)P()的最大项作为x的所属类别

    朴素贝叶斯的算法实现

    首先创建一个Nbayes_pre.py文件来编写导入的数据和朴素贝叶斯类的代码

    1. 使用简单的英文语料作为数据集合,其中postingList是训练集文本,classVec是每个文本对应的分类

    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','my'],
                     ['stop','posting','stupid','worthless','garbage'],
                     ['mr','licks','ate','steak','how','to','stop','hime'],
                     ['quit','buying','worthless','dog','food','stupid']]
        classVec=[0,1,0,1,0,1]#1 is abusive, 0 not
       
    return postingList,classVec

    1. 下面逐步实现贝叶斯算法,第一步即编写一个贝叶斯算法类,并创建默认的构造方法
    class NBayes(object):
        def _init_(self):
            self.vocabulary=[]#词典
           
    self.idf=0#词典的IDF权重向量
           
    self.tf=0#训练集的权值矩阵
           
    self.tdm=0#P(x│y_i)
           
    self.Pcates={}#P(y_i)是一个类别字典
           
    self.labels=[]#对应每个文本的分类,是一个外部导入的列表
           
    self.doclength=0#训练集文本数
           
    self.vocablen=0#词典词长
           
    self.testset=0#测试集
    1. 导入和训练数据集,生成算法必须的参数和数据结构
    def train_set(self,trainset,classVec):
        self.cate_prob(classVec)#计算每个分类在数据集中的概率P(y_i)
       
    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|y_i)
    1. 计算在数据集中每个分类的概率P(y_i)
    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))
    1. 生成普通的词频向量
    def calc_wordfreq(self,trainset):
        self.idf=np.zeros([1,self.vocablen])#1x词典数
       
    self.tf=np.zeros([self.doclength,self.vocablen])#训练集文件数x词典数
       
    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]):
                self.idf[0,self.vocabulary.index(signleword)]+=1
    1. 按分类累计计算向量空间的每维值P(x|y_i)
    def build_tdm(self):
        self.tdm=np.zeros([len(self.Pcates),self.vocablen])#类别行x词典列
       
    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|y_i)
    1. 将测试集映射到当前词典
    def map2vocab(self,testdata):
        self.testset=np.zeros([1,self.vocablen])
        for word in testdata:
            self.testset[0,self.vocabulary.index(word)]+=1
    1. 预测分类结果,输出预测的分类类别
    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|y_i) P(y_i)
            #
    变量tdm,计算最大分类值
           
    temp=np.sum(testset*tdm_vect*self.Pcates[keyclass])
            if temp>predvalue:
                predvalue=temp
                predclass=keyclass
        return predclass
    1. 算法还可以进行一些改进,将步骤e中的函数替换掉,普通的词频向量改为使用TF-IDF策略,使之有能力修正多种偏差,下面函数以TF-IDF方式生成向量空间
    2. 评估分类结果,执行我们创建的朴素贝叶斯类,获取执行结果
    j.   def calc_tfidf(self,trainset):
        self.idf=np.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)#矩阵与向量的点乘 TFxIDF
    l.   import numpy as np
    from numpy import *
    from Nbayes_pre 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))

     工程代码

    不知道为什么显示不了数学公式了非常尴尬,原文链接

  • 相关阅读:
    初学node.js,安装nodemon,学习debug模式,安装cpu-stat
    当离开浏览器窗口,提示语title更改
    构建react项目失败解决办法
    vue 安装cli3.0版本,创建项目
    上传js,js修改html
    上传图片
    css3 伸缩百分比的调整
    css3 伸缩布局 display:flex等
    解决HTML5提出的新的元素不被IE6-8识别的解决办法
    web前端,多语言切换,data-localize,
  • 原文地址:https://www.cnblogs.com/kevinzhaozl/p/6625928.html
Copyright © 2011-2022 走看看