注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

长风明志的博客

不要也不能做下一个谁,应该且可以做第一个自己

 
 
 

日志

 
 

朴素贝叶斯分类Python实现  

2013-10-20 18:17:55|  分类: 数据挖掘 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、朴素贝叶斯分类算法简单介绍:
1.贝叶斯公式:已知某条件概率,如何得到两个事件交换后的概率,也就是在已知P(A|B)的情况下如何求得P(B|A)。
                                                                               
如:已知P(A|B)情况下求P(B|A)则可以利用下面这个公式求解:
                                   
  
 
2.朴素贝叶斯分类原理:
朴素贝叶斯分类Python实现 - changfengmingzhi - 长风明志的博客

朴素贝叶斯分类Python实现 - changfengmingzhi - 长风明志的博客

      1、设为一个待分类项,而每个a为x的一个特征属性。

      2、有类别集合

      3、计算

      4、如果,则

      那么现在的关键就是如何计算第3步中的各个后验概率。

     我们可以这么做:

      1、找到一个已知分类的集合做为训练样本集。

      2、统计得到在各类别下各个特征属性的条件概率。即

      以及计算各个类别的概率P(y1)、p(y2)、.....P(yn)。其中P(ai|yj)=Count(ai,yj)/Count(yj)、P(yi)=Count(yi)/SampleNum.

      3、如果各个特征属性是条件独立的(此为“朴素”两字的来由),则根据贝叶斯定理有如下推导:

      

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

      

    对于一个新的测试样本x,对各个类别计算P(x|yi)P(yi)概率,如果某个类标yi使该概率最大化,则该测试样本的类标则为yi.

3.两个特别情况:特征属性为连续值和条件概率为0

   (1) 我们前面介绍的朴素贝叶斯分类是在特征属性值为离散型的基础上进行的,当特征属性为离散值时,只要很方便的统计训练样本中各个划分在每个类别中出现的频率即可用来估计P(a|y)。而当遇到连续型的属性值时,需要进行离散化处理。

当特征属性为连续值时,通常假定其值服从高斯分布(也称正态分布)。即:

      

      而

      因此只要计算出训练样本中各个类别中此特征项划分的各均值和标准差,代入上述公式即可得到需要的估计值。

(2).另一个需要讨论的问题就是当P(a|y)=0怎么办,当某个类别下某个特征项没有出现时,就是产生这种现象,这会令分类器质量大大降低。为了解决这个问题,我们引入Laplace校准,它的思想非常简单,就是对在某个类别下没出现的特征项的计数加1(及P(ai|yj)=1/Count(yj) ),这样如果训练样本集数量充分大时,并不会对结果产生影响,并且解决了上述频率为0的尴尬局面。

   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  

输出结果:

   朴素贝叶斯分类Python实现 - changfengmingzhi - 长风明志的博客

 (4)针对Bupa.txt数据集(下载数据集:https://code.google.com/p/jadesoul/source/browse/trunk/includes/ml/refernce-python-code/bupa.data?spec=svn27&r=22)
   输出结果:
  ....................................
  Original:1==>Classified:2
Original:2==>Classified:2
Original:1==>Classified:1
Original:1==>Classified:1
Original:1==>Classified:1
Accuracy: 0.8376811594202899
  评论这张
 
阅读(6602)| 评论(5)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017