机器学习基础(三):贝叶斯决策及python实现 莺尾花分类

作者: 阿瑟_TJRS | 来源:发表于2019-10-09 17:06 被阅读0次

    前言

    贝叶斯决策是模式识别中最基础的理论,是解决模式分类的一种基本统计途径,是后续学习的基础

    • 本文为笔者学习过程的原创笔记,转载请附本文链接及作者信息。
    • 后附连续型数据的贝叶斯分类器python实现
    • 有问题欢迎在交流区探讨学习,QQ:761322725
    • 码字不易,好心人随手点个赞👍
      总括:
      贝叶斯决策论是解决模式分类问题的一种基本统计途径 。
      出发点是利用概率决策与相应代价之间的折中 。
      (概率学派与频率学派)
      它做了如下假设
    • 决策问题可以用概率形式来描述
    • 所有有关的概率结构均已知

    原理讲解

    所用教材为机械工业出版社所译《模式识别》,使用了鱼分拣的例子,即二分类问题
    问题的抽象描述如下

    模式
    通用的系统框架如下图所示,实现从现实世界到符号世界的转换,完成最后的分类任务。
    分类系统构成 规范化定义 后验概率是后续的关键,理解为当下数据为的条件下,标签为的概率。

    最小错误率决策


    最小错误率解释
    对贝叶斯公式再进行分析如下
    • 从最小错误率的要求出发,利用贝叶斯公式就能得出使错误率最小的分类决策 称之为\color{red}{最小错误率贝叶斯决策}
    • 可知使 错误率最小的决策就是 \color{red}{使后验概率最大的决策}
    • 具体决策规则可以表示如下:
      决策边界
      至于多类情况,同样可以推广利用
      image.png

    最小风险决策

    • 很多场合 不同的错误决策所造成的损失不同(癌症误判 、 鱼分拣)
    • 需要引入更一般的损失函数来替代错误率
    • 计算各种不同误判的风险 采取总风险最小的决策 。
    • 最小风险贝叶斯决策,允许更多行动 ( 而不仅仅是类别判定,当决策风险大于不决策时 可以拒绝做决策 (引申:三支决策)
      image.png 相应决策过程如下:

    分类器、判别函数与决策面

    将分类模型表示进一步形式化,利用判别函数进行表示定义如下:

    贝叶斯分类器的判别函数如下

    正态分布下的贝叶斯决策

    我们讨论一个很常见的情况,在数据呈现正态分布下的贝叶斯决策如何计算。正态分布的相关知识点回顾如下:


    则最小错误率贝叶斯判别函数如下:
    上式是实际计算的关键,当取特殊值时,上式有不同的简化形式,在此不予讨论

    小结

    以上即为贝叶斯决策的基本原理,原理简单易懂,掌握住两种不同思路的决策方法即可

    代码实现

    数据说明

    使用莺尾花标准数据(常用来坐分类实验demo),Iris_data网上都能下载到,数据规格:

    • 多分类问题 150*5大小
    • 各属性值属于连续型数据
    • 数据分布为正态分布

    具体算法实现流程

    image.png

    完整代码

    使用python编程实现,面向对象编程的编写方式,可以训练和预测;
    模型参数存储功能当时比较急没有实现。

    """
    Author:Arthur_Pang
    Time: 2019/09/28
    Description:  [贝叶斯分类算法实现]
    """
    import pandas as pd
    import numpy as np
    import logging
    import math
    import json
    from sklearn.model_selection import train_test_split
    
    logging.basicConfig(format='%(asctime)s - %(levelname)s: %(message)s',
                        level=logging.DEBUG)    
    """
    class:贝叶斯分类器
    功能:- 读取加载数据
        - 数据划分
        - 模型训练
        - 模型预测
        - 模型参数保存
        
    """
    class Bayes_classfier:
        def __init__(self,path):
            # 模型数据集路径
            self.data_path=path
            #模型参数记录
            self.params=dict()
        '''
        func:数据集读取与训练测试集划分
        
        return:None
        '''
        def data_processing(self):
            self.df=pd.read_csv(self.data_path,header=None)
            logging.info('loading datasets,volume:{}'.format(self.df.shape))
            #数据列名称指定
            self.df.columns = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species']
            
            #特征与标签提取
            #features=self.df[[x for x in self.df.columns if x not in ['species']]]
            features=self.df
            label=self.df['species']
            # 训练集与测试集切分
            self.X_train, self.X_valid, self.y_train, self.y_valid=train_test_split(features, label, test_size=0.25, random_state=300,stratify=label)
            
            logging.info('split datasets,train_datasets:{},test_datasets:{}'.format(self.X_train.shape, self.X_valid.shape))
            
            pass
        
        '''
        func: 模型训练过程,即计算贝叶斯各个参数
        
        return :None
        '''
        def fit(self):
            # 计算先验概率:
            
            priori_prob=(self.y_train.value_counts()+1)/(self.y_train.shape[0]+3)
            logging.info('计算训练集先验概率...')
            #print(priori_prob)
            # 记录各模型参数的值用于预测
            self.params['priori_prob']=priori_prob
            # 计算各类均值mu,协方差矩阵的逆,协方差矩阵的行列式
            
            mu_=dict()
            sigma_inv=dict()
            det_=dict()
            logging.info('计算mu,sigma等矩阵运算...')
            for _label,groups in self.X_train.groupby(['species']):
                groups=groups[[x for x in self.df.columns if x not in ['species']]]
                
                #print(_label,groups.mean(axis=0))
                mu_[_label]=groups.mean(axis=0)
                sigma_=np.cov(groups.T, bias=True)
                sigma_inv[_label]=np.linalg.inv(sigma_)
                det_[_label]=np.linalg.det(sigma_)
            self.params['class_mu']=mu_
            self.params['class_sigma_inv']=sigma_inv
            self.params['class_det']=det_
            
        '''
        func: 分类判别函数,即利用代码实现上述判别函数
        return: 判别值
         注: @ 为numpy矩阵乘法运算 
        '''
        def g(self,x, mu, sigma_inv, det, priori_prob):
            #print(mu,sigma_inv)
            return -0.5 * (x - mu).T @ sigma_inv @ (x - mu) - 0.5 * math.log(det) + math.log(priori_prob)
        
        '''
        func: 构建判别函数用于预测,对测试集中各类别进行测试
        
        return None
        '''
        def predict(self):
            # 对各类进行测试
            for _label,test_group in self.X_valid.groupby(['species']):
                logging.info('test the {},volume:{}'.format(_label,test_group.shape[0]))
                test_feature=test_group[[x for x in self.df.columns if x not in ['species']]]
                ##
                print(_label)
                # 记录测试结果是否正确
                test_res=[]
                
                for _,row in test_feature.iterrows():
                    #print(self.params['priori_prob'][_label])
                    score=dict()
                
                    # 计算各类别的得分情况
                    for _l in self.df['species'].unique():
                        
                        score[_l]=self.g(np.array(row.values),
                           self.params['class_mu'][_l].values,
                           self.params['class_sigma_inv'][_l],
                           self.params['class_det'][_l],
                           self.params['priori_prob'][_l])
                    #print(score)
                    predict_res=max(score, key=score.get)
                    
                    print('[测试]当前预测类别:{},实际类别:{},{}'.format(predict_res,_label,predict_res==_label))
                    test_res.append(predict_res==_label)
                print('{}类别测试准确率:{}'.format(_label,test_res.count(True)/len(test_res)))
    
    
    classfier=Bayes_classfier('./data/iris.data')
    classfier.data_processing()
    classfier.fit()
    classfier.predict()
    

    代码输出结果如下:

    2019-09-28 16:04:26,719 - INFO: loading datasets,volume:(150, 5)
    2019-09-28 16:04:26,731 - INFO: split datasets,train_datasets:(112, 5),test_datasets:(38, 5)
    2019-09-28 16:04:26,734 - INFO: 计算训练集先验概率...
    2019-09-28 16:04:26,736 - INFO: 计算mu,sigma等矩阵运算...
    2019-09-28 16:04:26,748 - INFO: test the Iris-setosa,volume:12
    2019-09-28 16:04:26,766 - INFO: test the Iris-versicolor,volume:13
    2019-09-28 16:04:26,784 - INFO: test the Iris-virginica,volume:13
    Iris-setosa
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    [测试]当前预测类别:Iris-setosa,实际类别:Iris-setosa,True
    Iris-setosa类别测试准确率:1.0
    Iris-versicolor
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-versicolor,False
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    [测试]当前预测类别:Iris-versicolor,实际类别:Iris-versicolor,True
    Iris-versicolor类别测试准确率:0.9230769230769231
    Iris-virginica
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    [测试]当前预测类别:Iris-virginica,实际类别:Iris-virginica,True
    Iris-virginica类别测试准确率:1.0
    
    • 本文为笔者学习过程的原创笔记,转载请附本文链接及作者信息。
    • 有问题欢迎在交流区探讨学习,QQ:761322725
    • 码字不易,好心人随手点个赞👍

    相关文章

      网友评论

        本文标题:机器学习基础(三):贝叶斯决策及python实现 莺尾花分类

        本文链接:https://www.haomeiwen.com/subject/hfrcuctx.html