机器学习--朴素贝叶斯分类器(python手动实现)

简介

朴素贝叶斯(Naive Bayes)是基于贝叶斯定理和概率论预测样本类别的概率算法,而朴素一词的来源就是假设各特征之间相互独立。朴素贝叶斯属于监督学习的生成模型,实现简单,没有迭代,并有坚实的数学理论(即贝叶斯定理)作为支撑。在大量样本下会有较好的表现,不适用于输入向量的特征条件有关联的场景。
关于贝叶斯定理的详细介绍

名词介绍

拿西瓜是否成熟举例,假设判断西瓜成熟的特征有:瓜蒂是否脱落,敲打的声音-浊响|清脆

  • 先验概率:
    先验概率是根据以往经验和分析得到的概率,先验概率无需样本数据,不受任何条件的影响。比如有1000个西瓜,其中熟瓜600,涩瓜400,则先验概率p(熟瓜)=0.6,p(涩瓜)=0.4,并不受瓜蒂和敲打声音的影响。再比如硬币正反面概率各为0.5也是先验概率。
  • 后验(条件)概率:
    已知结果或者某一条件(结果也是一种条件),求知条件或者结果的概率。比如已知某西瓜瓜蒂脱落,判断瓜成熟的概率,即p(成熟|瓜蒂脱落)。
  • 拉普拉斯平滑(Laplace smoothing):
    它的思想非常简单,就是对先验概率的分子(划分的计数)加1,分母加上类别数;对条件概率分子加1,分母加上对应特征的可能取值数量。这样在解决零概率问题的同时,也保证了概率和依然为1。
    直接的作用就是防止模型“过拟合”,提高了模型的泛化性能。
    也是解决样本为0的时概率为0的问题,因为若p(B)为0,则P(B|A)也为0,而实际并非如此。
  • 概率密度函数:
    用于描述连续型随机变量所服从的概率分布,由此判断不可列的连续型随机变量的概率。

公式

  • 贝叶斯公式:
    在这里插入图片描述

  • 朴素贝叶斯基本公式:在这里插入图片描述
    即P(B|A) = P(A|B)P(B)

  • 概率密度函数:
    在这里插入图片描述

  • 正态分布:
    在这里插入图片描述

概率分布

  • 高斯分布型:
    正态曲线呈钟型,两头低,中间高,左右对称因其曲线呈钟形,因此人们又经常称之为钟形曲线
  • 多项式型:
    用于离散值模型里。比如文本分类问题里面我们提到过,我们不光看词语是否在文本中出现,也得看出现次数。如果总词数为n,出现词数为m的话,有点像掷骰子n次出现m次这个词的场景。
  • 伯努利型:
    亦称“零一分布”、“两点分布”:一个事情有两种可能的结果,其中结果为1的发生概率为a,结果2发生的概率为1-a

数据集及代码实现

数据集是使用了分层抽样的十折交叉验证的,所以分为了十个名字相似的各类样本相近的数据集桶文件,如下:
该数据集为国会投票的样本:
在这里插入图片描述
分析数据集:
democrat为民主党,republican为共和党,即标签,表示类别
此后y和n表示特征,共16个特征,每个特征两个类别
在这里插入图片描述

代码实现

定义容器对象

存储从数据集中提取的数据,存储对数据统计分析的结果
数据分为三类:标签类别(democrat/republican),字符型特征(y/n),数值型(即连续型,该数据集没有此类型)

        '''
        params:
            bucketPrefix: 桶文件名的前缀
            testBucketNumber:测试数据所在的桶的编号
            dataFormat: 数据文件格式列表
        
        '''
        total=0    #记录总数据量
        classes={
   } #存类别出现的次数
        counts={
   } #每个类别对应的属性值出现的次数
        self.format = dataFormat.strip().split('\t') # 切分每一列的数据类型
        
        '''
        存储数值型数据信息
        '''
        totals={
   } # 每种类别对应的值的总和
        numericValues={
   } #存每种类别对应的列的取值  
        
        '''
        存储计算出的概率
        '''
        self.prior={
   } #先验概率
        self.condition={
   } #条件概率

循环提取十个桶文件中的数据,分门别类存储

十个桶文件中根据传入的参数指定一个为测试数据集,其他九个都为训练数据集

        for i in range(1,11): #循环10次
            if i!=testBucketNumber: #判断是否为测试集
                filename='%s-%02i'%(bucketPrefix,i)
                f=open(filename,'r')
                lines = f.readlines()
                f.close()
                for line in lines:
                    
                    total=total+1 #统计总数
                    fields = line.strip().split('\t') #分割文件的每列 
                    vector =[]  #存储字符型特征
                    '''
                    保存每一条数据的数值型数据
                    '''
                    nums=[]
                    #分门别类存储标签和不同类型的特征
                    for i in range(len(fields)):
                        if self.format[i]=='attr':
                            vector.append(fields[i])
                        elif self.format[i]=='class':
                            category=fields[i]
                        elif self.format[i]=='num':
                            nums.append(float(fields[i]))
                            
                    #记录每个列别出现的次数
                    classes.setdefault(category,0)
                    counts.setdefault(category,{
   })
                    classes[category]+=1
                    
                    '''
                    记录每个数值型数据
                    '''
                    totals.setdefault(category,{
   })
                    numericValues.setdefault(category,{
   })
                    
                    #循环处理么每条记录出现的属性值
                    #循环vector 取出每列值
                    col=0
                    for columnValue in vector:
                        col+=1
                        counts[category].setdefault(col,{
   })
                        counts[category][col].setdefault(columnValue,0)
                        counts[category][col][columnValue]+=1
                    '''
                    counts形成的结构为:
                    {
                    'democrat': 
                        {
                            1: {'y': 64, 'n': 48}, 
                            2: {'n': 64, 'y': 48},
                            ...
                            16: {'y': 105, 'n': 7}
                        },
                   'republican': 
                       {
                           1: {'y': 22, 'n': 76},
                           2: {'y': 46, 'n': 52},
                           ...
                           16: {'n': 30, 'y': 68}
                        }
                    }
                    '''
                    
                    '''
                    保存每个数值型数据与类别的对应字典
                    '''
                    col=0
                    for columnValue in nums:
                        col+=1
                        totals[category].setdefault(col,0)
                        totals[category][col]+=columnValue
                        numericValues[category].setdefault(col,[])
                        numericValues[category][col].append(columnValue)
                        

计算先验概率,条件概率

多项式类型数据的概率,利用贝叶斯公式(引入拉普拉斯平滑)计算先验概率,再计算条件概率

#开始计算概率
		# classes:  {'democrat': 112, 'republican': 98}
        for (category, count) in classes.items():
            self.prior[category] = count/total
            
        #条件概率: 注意:columns是一个字典
        for (category, columns) in counts.items():
            self.condition.setdefault(category,{
   })
            
            for (col,valueCount) in columns.items():
                self.condition[category].setdefault(col, {
   })
                
                # 此处引入拉普拉斯平滑处理已存在值
                for (attrValue, count) in valueCount.items():
                    # 此处先计算所有在样本中已存在值的条件概率 ( nc+(mp))/(N+m)
                    m=len(counts[category][col].items())
                    self.condition[category][col][attrValue] = (count+1)/(classes[category]+m
  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值