模式识别课程(一):贝叶斯决策及python实现 莺尾花分类

前言

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

  • 本文为笔者学习过程的原创笔记,转载请附本文链接及作者信息。
  • 后附连续型数据的贝叶斯分类器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
  • 码字不易,好心人随手点个赞👍
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容