找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1449|回复: 0
打印 上一主题 下一主题
收起左侧

朴素贝叶斯公式推导

[复制链接]
跳转到指定楼层
楼主
ID:419062 发表于 2018-11-1 13:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前言

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

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

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

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

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

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

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

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

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



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



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

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

朴素贝叶斯的算法实现

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

    使用简单的英文语料作为数据集合,其中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



    下面逐步实现贝叶斯算法,第一步即编写一个贝叶斯算法类,并创建默认的构造方法

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#测试集



    导入和训练数据集,生成算法必须的参数和数据结构

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)



    计算在数据集中每个分类的概率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))



    生成普通的词频向量

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



    按分类累计计算向量空间的每维值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)



    将测试集映射到当前词典

def map2vocab(self,testdata):

    self.testset=np.zeros([1,self.vocablen])

    for word in testdata:

        self.testset[0,self.vocabulary.index(word)]+=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



    算法还可以进行一些改进,将步骤e中的函数替换掉,普通的词频向量改为使用TF-IDF策略,使之有能力修正多种偏差,下面函数以TF-IDF方式生成向量空间
    评估分类结果,执行我们创建的朴素贝叶斯类,获取执行结果

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))

工程代码
不知道为什么显示不了数学公式了非常尴尬
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表