机器学习之Naive Bayes&&python实践

最为广泛的两种分类模型是决策树模型(Decision Tree Model)和朴素贝叶斯模型(Naive Bayesian Model,NBC)。

贝叶斯定理是在250多年前发明的算法,在信息领域内有着无与伦比的地位。贝叶斯分类是一系列分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。朴素贝叶斯算法(Naive Bayesian) 是其中应用最为广泛的分类算法之一。

 

贝叶斯定理(朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法)

描述

贝叶斯定理是关于随机事件A和B的条件概率的一则定理。

clip_image001

在贝叶斯定理中,每个名词都有约定俗成的名称:

按这些术语,Bayes定理可表述为:

后验概率 = (相似度*先验概率) / 标准化常量

P(B|A)称为“可能性函数”,这是个调整因子,使得预估计概率更接近真实概率。

所以,条件概率可以理解为式子:

       后验概率 = 先验概率 * 调整因子

这就是贝叶斯推断的含义:我们先预测一个“先验概率”,然后加入实验结果,看这个实验到底是增强还是削弱了“先验概率”,由此得到更加真实的“后验概率”。

在这里,如果“可能性函数”P(B|A)/P(B)>1,意味着“先验概率”被增强,事件A发生的可能性增大;如果“可能性函数”P(B|A)/P(B)=1,意味着事件B无助于判断事件A的可能性;如果“可能性函数”P(B|A)/P(B)<1,意味着“先验概率”被减弱,事件A发生的可能性变小。

推导

根据条件概率的定义。在事件B发生的条件下事件A发生的概率是

clip_image002

同样地,在事件A发生的条件下事件B发生的概率

clip_image003

整理与合并这两个方程式,我们可以找到

clip_image004

这个引理有时称作概率乘法规则。上式两边同除以P(B),若P(B)是非零的,我们可以得到贝叶斯定理:

clip_image005

贝叶斯定理通常可以再写成下面的形式:

clip_image006

其中AC是A的补集。故上式亦可写成:

clip_image007

在更一般化的情况,假设{Ai}是事件集合里的部分集合,对于任意的Ai,贝叶斯定理可用下式表示:

clip_image008

案例

clip_image009clip_image010clip_image011clip_image012clip_image013clip_image014                   30                                                                                                                                               20     

clip_image015clip_image016                   10                                                                                                                                               20

                                                                                                                                                       

 

暗箱操作,现在从其中一个箱子中得到一个绿球,问是从黑箱中取得的概率是?

分析:假定“从黑箱中取球”为事件A,“从红箱中取球”为事件B,“取到绿球”为事件M.

则问题为求P(A|M)

由贝叶斯定理得:P(A|M) = P(A) * P(M|A) / P(M)

= P(A) * P(M|A) /[ P(M|A)*P(A) + P(M|B) *P(B)]

其中,P(A)=P(B) = 1/2, P(M|A) = 3/4, P(M|B) = 1/2

结果为0.6,表明,来自黑箱的概率为0.6。也就是得到绿球后,事件A(取自于黑箱)的可能性增强了。

总论

朴素贝叶斯法是典型的生成学习方法。生成方法由训练数据学习联合概率分布P(X,Y),然后得到后验概率P(Y|X)。即:

一)利用训练数据得到P(X|Y)P(Y)的估计

二)根据公式P(X,Y)=P(Y)P(X|Y)得到P(X,Y)

三)根据公式P(Y|X)=clip_image002得到 P(Y|X)

展开

假设

输入空间χ⊆Rnn维向量的集合

输出空间为类标记集合У={c1,c2,…cK}

输入为特征向量x∈χ

输出为类标记yУ

X是定义在输入空间χ上的随机变量

Y是定义在输出空间У上的随机变量

训练数据集为T={(x1,x2),(x2,y2),…(xN,yN)}

特征的总个数为n

每一个特征的可能取值为Sj

训练数据的总个数为N

类标记个数为K

推导

一)通过训练数据得到

1.  先验概率P(Y=ck), k=1,2,…K

2.  条件概率分布P(X=x|Y=ck)=P(X(1)=x(1),…X(n)=x(n)|Y=ck)

朴素贝叶斯法的基本假设为条件独立性,即用于分类的特征在类确定的条件下都是条件独立的。所以

P(X=x|Y=ck)=P(X(1)=x(1),…X(n)=x(n)|Y=ck)

           clip_image004P(X(j)=x(j) |Y=ck)

对于参数P(Y=ck)P(X(j=x|Y=ck)的估计可以是极大似然估计也可以是贝叶斯估计。

极大似然估计

P(Y=ck)=clip_image006

设第j个特征x(j)可能的取值为{aj1,aj2,…ajsj}个数为Sj

P(X(j)=xjl|Y=ck)=clip_image008

贝叶斯估计

用几大似然估计可能会出现所要估计的概率值为0的情况,这时候影响到后验概率的计算结果,使分类产生偏差。解决这一问题的方法是采用贝叶斯估计的方法估计。此时条件概率的贝叶斯估计为

Pclip_image010 (X(j)=xjl|Y=ck)=clip_image012

等价于在随机变量的各个取值的频数上加上一个正数clip_image014。当clip_image016时为极大似然估计,常去clip_image018,此时成为拉普拉斯平滑。显然有

Pclip_image010[1] (X(j)=xjl|Y=ck)>0

clip_image020Pclip_image010[2] (X(j)=xjl|Y=ck) = 1

同样P(Y=ck)=clip_image022

二)根据公式P(X,Y)=P(Y)P(X|Y)得到P(X,Y)

三)根据公式P(Y|X)=clip_image002[1]得到 P(Y|X)

P(X)=clip_image024

    =clip_image026

P(Y|X)=clip_image002[2] =P(Y=ck)clip_image028P(X(j)=x(j) |Y=ck) / clip_image030

可以看出此时分母是一样的,所以,

y=argclip_image032 P(Y=ck)clip_image028[1]P(X(j)=x(j) |Y=ck)

后验概率最大化的含义

y=argclip_image032[1] P(Y=ck)clip_image034P(X(j)=x(j) |Y=ck)

等价式是取得最大值,原因是:朴素贝叶斯法将实例分到后验概率最大的类中,这等价于期望风险最小化。后验概率最大等价于0-1损失函数的期望风险最小化。

假设选择0-1损失函数:

L(Y,f(X)) = clip_image036,f(X)是分类决策函数

此时,期望风险函数为

Rexp(f) = E[L(Y,f(X))]

=clip_image038

clip_image040

=clip_image042

=Exclip_image044)

 

可以看出是取条件期望,设

f(x)=clip_image046

clip_image048 (0-1损失函数,相等的为0)

=clip_image050 

=argmaxP(y=ck|X=x)

这样一来,风险最小化准则得到后验概率最大化准则:

f(x)=argmaxP(ck|X=x)

 4.Python源代码:

          (1).NaiveBayes.py  训练朴素贝叶斯模型(仅针对属性值为离散型情况)

#-*- coding:utf-8 -*-

from __future__ import division

class BayesClassifier():            #简单贝叶斯分类器

    def __init__(self):

        pass

    def train(self,features,labels):                          #训练简单贝叶斯分类器

        featuresNum=len(features[1])                  #样本特征数目

        self.sampleNum=len(features)                 #样本数目

        self.countDic={}                                    #统计各个条件概率的出现次数

        self.labelSet=set([])                               #集合存放类标,如:Y=1 or Y=-1

        for i in range(0,len(labels)):                    #统计类标不同值出现的次数

            tempStr='Y='+str(labels[i])

            self.labelSet.add(str(labels[i]))

            if tempStr in self.countDic:    

                self.countDic[tempStr]+=1

            else:

                self.countDic[tempStr]=1

        for i in range(0,len(features)):               #统计各个条件概率组合出现的次数

            for j in range(0,featuresNum):

                tempStr='F'+str(j)+'='+str(features[i][j])+'|'+'Y='+str(labels[i])

                if tempStr in self.countDic:

                    self.countDic[tempStr]+=1

                else:

                    self.countDic[tempStr]=1

        for key in self.countDic.keys():        #遍历次数统计字典计算概率

            if key.find('|')!=-1:                      #计算条件概率P(Fi=a|Y=b)

                targetStr=key[key.find('|')+1:]       #类标字符串:  Y=1 or Y=-1

                self.countDic[key]/=self.countDic[targetStr]    #算出条件概率P(Fi=a|Y=b)=Count(Fi=a,Y=b)/Count(Y=b)

        for label in self.labelSet:          #计算类标概率P(Y=b)

            tempStr="Y="+str(label)

            self.countDic[tempStr]/=self.sampleNum                                     

               

    def classify(self,feature):                                 #使用训练后的贝叶斯分类器分类新样本

        #计算后验概率P(Y=b|Sample=feature)

        probabilityMap={}

        for label in self.labelSet:

            tempProbability=1.0

            for i in range(0,len(feature)):

                tempStr='F'+str(i)+'='+str(feature[i])+'|Y='+label

                if tempStr not in self.countDic:        #遇到新的特征值,导致该概率P(Fi=a|Y=b)为0,将它校正为非0值(1/Count(Y=b))

                    tempProbability*=(1.0/self.countDic['Y='+label])/self.sampleNum

                else:

                    tempProbability*=self.countDic[tempStr]

            tempProbability*=self.countDic['Y='+label]

            probabilityMap[label]=tempProbability

        maxProbability=0.0

        for label in self.labelSet:                       #选取使后验概率P(Y=b|Sample=feature)最大的类标作为目标类标

            if  probabilityMap[label]>maxProbability:

                maxProbability=probabilityMap[label]

                targetLabel=label

        probabilityMap.clear()

        return targetLabel

    def __del__(self):

        self.countDic.clear()

                (2).  TestBayes.py 使用数据集测试前面训练的朴素贝叶斯模型

#-*- coding:utf-8-*-

from NaiveBayes import BayesClassifier

from numpy import *

def main():

    file=open("D:\\CF\\Weather.txt",'r')

    features=[]            #数据集特征集

    labels=[]                #数据集类标集

    for line in file:         #一行行读数据文件

        line=line.strip()

        tempVec=line.split(',')

        labels.append(tempVec[len(tempVec)-1])

        tempVec2=[tempVec[i] for i in range(0,len(tempVec)-1)]

        features.append(tempVec2)

    Bay=BayesClassifier()

    Bay.train(features,labels)

    correct=0

    for i in range(0,len(features)):

        label=Bay.classify(features[i])

        print("Original:"+str(labels[i])+"==>"+"Classified:"+label)

        if str(label)==str(labels[i]):

            correct+=1

    print("Accuracy:",correct/len(features))    #正确率

if __name__=='__main__':

    main()    

  (3).针对Weather.txt 小数据集:

sunny,hot,high,FALSE,no

sunny,hot,high,TRUE,no

overcast,hot,high,FALSE,yes

rainy,mild,high,FALSE,yes

rainy,cool,normal,FALSE,yes

rainy,cool,normal,TRUE,no

overcast,cool,normal,TRUE,yes

sunny,mild,high,FALSE,no

sunny,cool,normal,FALSE,yes

rainy,mild,normal,FALSE,yes

sunny,mild,normal,TRUE,yes

overcast,mild,high,TRUE,yes

overcast,hot,normal,FALSE,yes

rainy,mild,high,TRUE,no  

输出结果:

   


   输出结果:
  ....................................
  Original:1==>Classified:2
Original:2==>Classified:2
Original:1==>Classified:1
Original:1==>Classified:1
Original:1==>Classified:1
Accuracy: 0.8376811594202899

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值