朴素贝叶斯算法实现分类以及Matlab实现

  • 开始

其实在学习机器学习的一些算法,最近也一直在看这方面的东西,并且尝试着使用Matlab进行一些算法的实现。这几天一直在看得就是贝叶斯算法实现一个分类问题。大概经过了一下这个过程:

看书算法公式推演网上查询资料进一步理解搜集数据集开始尝试写代码调试代码整理与优化自编代码结果与Matlab自带函数fitcnb结果对比验证朴素贝叶斯算法优缺点总结

经过这几天的努力,总算是把这个算法彻底弄明白了,也发现,很多算法只有自己去亲自写一写才会发现自己的不足,还是需要多努力。

  • 贝叶斯分类

    • 分类问题理解
      贝叶斯分类是一类分类算法的总称,这类算法以贝叶斯定理为基础,因此称之为贝叶斯分类。
      而对于分类问题,其实谁都不会陌生,说我们每个人每天都在执行分类操作一点都不夸张,只是我们没有意识到罢了。例如,当你看到一个陌生人,你的脑子下意识判断TA是男是女;你可能经常会走在路上对身旁的朋友说“这个人一看就很有钱、那边有个非主流”之类的话,其实这就是一种分类操作。
      从数学角度来说,分类问题可做如下定义:
      已知集合,C={y1,y2,,yn}I={x1,x2,,xm,}确定映射规则y=f(x),使得任意的xI有且仅有一个yiC使得yi=f(xi)成立。
      其中C叫做类别集合,其中每一个元素是一个类别,而I叫做项集合,其中每一个元素是一个待分类项,f叫做分类器。分类算法的任务就是构造分类器f
      这里要着重强调,分类问题往往采用经验性方法构造映射规则,即一般情况下的分类问题缺少足够的信息来构造100%正确的映射规则,而是通过对经验数据的学习从而实现一定概率意义上正确的分类,因此所训练出的分类器并不是一定能将每个待分类项准确映射到其分类,分类器的质量与分类器构造方法、待分类数据的特性以及训练样本数量等诸多因素有关。

    • 贝叶斯定理
      该定理最早Thomas Bayes发明,显然这个定理可能就是为了纪念他而已他的名字命名的吧。这个定理是概率论中的一个结论,大学学习概率论的时候学习过的。它是跟随机变量的条件概率以及边缘概率分布有关的。该定理可以让人们知道如何用新的信息进行以后看法或者结论的修改。一般来说,事件A在事件B已经发生的条件下发生的概率与事件B在事件A已经发生的条件下发生的概率是不一样的。但是这个两者是有一定的联系的。下面就开始搬出这个伟大的定理:

      P(X,Y)=P(Y|X)P(X)=P(X|Y)P(Y)

      那么对这个公式进行变形有:

      P(Y|X)=P(X|Y)P(Y)P(X)

      由上面可以看出来,这个定理允许使用先验概率P(Y)、条件概率P(X|Y)和证据P(X)来表示后验概率

    • 朴素贝叶斯分类原理
      朴素贝叶斯分类是一种十分简单的分类算法,叫它朴素贝叶斯分类是因为这种方法的思想真的很朴素。
      朴素贝叶斯的思想基础是这样的:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。
      通俗来说,就好比这么个道理,你在街上看到一个黑人,我问你你猜这哥们哪里来的,你十有八九猜非洲。为什么呢?因为黑人中非洲人的比率最高,当然人家也可能是美洲人或亚洲人,但在没有其它可用信息下,我们会选择条件概率最大的类别,这就是朴素贝叶斯的思想基础。
      朴素贝叶斯分类器建立在一个类条件独立性假设(朴素假设)的基础之上,给定类变量后,各个变量之间相互独立。根据朴素贝叶斯独立性假设,有:

      P(X|Ci)=mk=1P(XK|Ci)

      其中,当给定训练数据集的时候,条件概率P(X1|Ci)P(X2|Ci),P(X3|Ci),...,P(Xn|Ci)可以算出来,因此,根据这个方法,对一个未知类别的样本X,可以先分别计算X属于每个类别Ci的概率P(X|Ci)P(Ci),然后选择其中概率最大的类别作为其类别。

    • 算法流程
      朴素贝叶斯分类的一个基本算法流程为:
      (1)设x={x1,x2,,xm}为一个待分类的项,而每一个xix的一个属性,每一个属性有k个取值xi={a1,a2,,ak}
      (2)有一个类别集合C={y1,y2,,yn}
      (3)计算P(y1|x),P(y2|x),...,P(yn|x)
      (4)如果P(yk|x)=max{P(y1|x),P(y2|x),...,P(yn|x)},则xyk
      因此,从上面我们可以看出来,该算法的关键步骤就是第(3)中的各个条件概率的计算,基于独立性假设,可以这样计算:
      1、找到一个已知分类的待分类项集合,这个集合叫做训练样本集。
      2、统计得到在各个类别下各个特征属性的条件概率估计值,即:
      P(a1|y1),P(a2|y1),...,P(am|y1)
      P(a1|y2),P(a2|y2),...,P(am|y2)

      P(a1|y1),P(a2|y1),...,P(am|y1)
      3、如果各个特征属性是条件独立的,则根据贝叶斯定理有如下推导:
      P(yi|x)=P(x|yi)P(yi)P(x)
      因为分母对于所有类别来说都是常数,因此,该算法就是求解分子最大化问题。因为各个特征属性之间是条件独立的,所以有:
      依据上面的分析,可以得到朴素贝叶斯分类的一个基本流程图如下:
      朴素贝叶斯分类流程图
  • Matlab程序实现

    • 程序
      使用Matlab实现朴素贝叶斯算法的数据来源:http://archive.ics.uci.edu/ml/machine-learning-databases/balance-scale/balance-scale.data。
      不多说先开始上程序吧
clc
clear
close all
data=importdata('data.txt');
wholeData=data.data;
%交叉验证选取训练集和测试集
cv=cvpartition(size(wholeData,1),'holdout',0.04);%0.04表明测试数据集占总数据集的比例
trainData=wholeData(training(cv),:);
testData=wholeData(test(cv),:);
label=data.textdata;
attributeNumber=size(trainData,2);
attributeValueNumber=5;
%%
%将分类标签转化为数据
sampleNumber=size(label,1);
labelData=zeros(sampleNumber,1);
for i=1:sampleNumberif label{i,1}=='R'labelData(i,1)=1;elseif label{i,1}=='B'labelData(i,1)=2;else labelData(i,1)=3;end
end
trainLabel=labelData(training(cv),:);
trainSampleNumber=size(trainLabel,1);
testLabel=labelData(test(cv),:);
%计算每个分类的样本的概率
labelProbability=tabulate(trainLabel);
%P_yi,计算P(yi)
P_y1=labelProbability(1,3)/100;
P_y2=labelProbability(2,3)/100;
P_y3=labelProbability(3,3)/100;
%%
%
count_1=zeros(attributeNumber,attributeValueNumber);%count_1(i,j):y=1情况下,第i个属性取j值的数量统计
count_2=zeros(attributeNumber,attributeValueNumber);%count_1(i,j):y=2情况下,第i个属性取j值的数量统计
count_3=zeros(attributeNumber,attributeValueNumber);%count_1(i,j):y=3情况下,第i个属性取j值的数量统计
%统计每一个特征的每个取值的数量
for jj=1:3for j=1:trainSampleNumberfor ii=1:attributeNumberfor k=1:attributeValueNumberif jj==1if trainLabel(j,1)==1&&trainData(j,ii)==kcount_1(ii,k)=count_1(ii,k)+1;endelseif jj==2if trainLabel(j,1)==2&&trainData(j,ii)==kcount_2(ii,k)=count_2(ii,k)+1;endelseif trainLabel(j,1)==3&&trainData(j,ii)==kcount_3(ii,k)=count_3(ii,k)+1;endendendendend
end
%计算第i个属性取j值的概率,P_a_y1是分类为y=1前提下取值,其他依次类推。
P_a_y1=count_1./labelProbability(1,2);
P_a_y2=count_2./labelProbability(2,2);
P_a_y3=count_3./labelProbability(3,2);
%%
%使用测试集进行数据测试
labelPredictNumber=zeros(3,1);
predictLabel=zeros(size(testData,1),1);
for kk=1:size(testData,1)testDataTemp=testData(kk,:);Pxy1=1;Pxy2=1;Pxy3=1;%计算P(x|yi)for iii=1:attributeNumberPxy1=Pxy1*P_a_y1(iii,testDataTemp(iii));Pxy2=Pxy2*P_a_y2(iii,testDataTemp(iii));Pxy3=Pxy3*P_a_y3(iii,testDataTemp(iii));end%计算P(x|yi)*P(yi)PxyPy1=P_y1*Pxy1;PxyPy2=P_y2*Pxy2;PxyPy3=P_y3*Pxy3;if PxyPy1>PxyPy2&&PxyPy1>PxyPy3predictLabel(kk,1)=1;disp(['this item belongs to No.',num2str(1),' label or the R label'])labelPredictNumber(1,1)=labelPredictNumber(1,1)+1;elseif PxyPy2>PxyPy1&&PxyPy2>PxyPy3predictLabel(kk,1)=2;labelPredictNumber(2,1)=labelPredictNumber(2,1)+1;disp(['this item belongs to No.',num2str(2),' label or the B label'])elseif   PxyPy3>PxyPy2&&PxyPy3>PxyPy1predictLabel(kk,1)=3;labelPredictNumber(3,1)=labelPredictNumber(3,1)+1;disp(['this item belongs to No.',num2str(3),' label or the L label'])end
end
testLabelCount=tabulate(testLabel);
% 计算混淆矩阵
disp('the confusion matrix is : ')
C_Bayes=confusionmat(testLabel,predictLabel)

以上部分就是针对于这个已有的数据集进行的算法的实现。

  • 结果与分析
    C_Bayes是计算出来的混淆矩阵。
    其结果为:
    C_Bayes=
    8300000014

    为了验证该自编程序是否可靠,我再使用了Matlab自带的贝叶斯算法的函数fitcnb进行该数据的分类测试
Nb=fitcnb(trainData,trainLabel);
y_nb=Nb.predict(testData);
C_nb=confusionmat(testLabel,y_nb)

其中C_nb是采用自带函数得到的结果的混淆矩阵
其结果为:
C_nb=

8300000014

可以发现其结果是完全一样的。
为了进一步验证程序的可靠性,我改变了交叉验证中训练集和测试集的比例,设置为0.2,
此时采用自编程序得到的混淆矩阵为:
C_Bayes=
63400000552

而使用自带函数fitcnb得到的结果为:
C_nb=
63400000552

可以发现再次得到了一致的结果。

  • 总结

    1. 从上面的整个程序的实现,可以发现,整个朴素贝叶斯分类分为三个阶段。
      ①. 准备阶段。包括数据搜集,数据导入以及数据清洗阶段。获得可以进行分析的质量比较好的结果。然后将数据划分为训练集和测试集。
      ②. 构建分类器,进行数据训练。要工作是计算每个类别在训练样本中的出现频率及每个特征属性划分对每个类别的条件概率估计,并将结果记录。其输入是特征属性和训练样本,输出是分类器。这一阶段是机械性阶段,根据前面讨论的公式可以由程序自动计算完成。
      ③. 第三阶段——应用阶段。这个阶段的任务是使用分类器对待分类项进行分类,其输入是分类器和待分类项,输出是待分类项与类别的映射关系。这一阶段也是机械性阶段,由程序完成。

    2. 朴素贝叶斯算法成立的前提是各个属性之间是相互独立的。当数据集满足这个独立性假设的时候,分类的准确率较高,否则就可能不是很好。

    3. 朴素贝叶斯分类算法的特点
      ①. 这个算法比较的就简单,但是却很高效,在朴素贝叶斯的假设前提之下,分类结果准确率很高。
      ②. 同样,如果属性之间存在一个相关性联系的话,这个分类的精度就会大大降低。因为此时的独立性假设就会不成立,导致计算得到的条件概率均出现不同程度的偏差。

艾勇-上海交通大学
2017/7/19

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

位操作基础篇之位操作全面总结

转载自 http://blog.csdn.net/morewindows/article/details/7354571 Title: 位操作基础篇之位操作全面总结 KeyWord: C/C 位操作 位操作技巧 判断奇偶 交换两数 变换符号 求绝对值 位操作压缩空间 筛素数 位操作趣味应用 位操作笔试面试 位操作篇共分为基础篇和提高…

机器学习中的算法-支持向量机(SVM)基础

机器学习中的算法-支持向量机(SVM)基础 版权声明: 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用,但请注明出处,如果有问题,请联系wheeleastgmail.com。也可以加我的微博: leftnotea…

算法题:输入aaaabbbcccccc输出a4b3c6。

今日在地铁上浏览今日头条的时候看到这么个小题目,说是输出一长串字符串,输出字母串类别并且统计其出现次数,然后按照顺序将其输出来。例如输入aaaabbbcccccc,输出a4b3c6。 最近也一直在学习,所以就想着就Matlab来试了…

Java World中的GraphQL简介

许多人认为GraphQL仅适用于前端和JavaScript,它在Java等后端技术中没有定位,但事实确实如此。 还经常将GraphQL与REST进行比较,但是这种比较是否合理? 首先,让我开始回答其中最重要的问题。 什么是GraphQL&#xff1…

算法题:在一个字符串中找到只出现一次的字符。如输入abaccdeeff,则输出bd。

今天的算法学习还是和字符串有关,这个题目据说是以前的某公司面试的笔试题目。题目意思就是说,在一个字符串中找到只出现了一次的那些字符,并且输出来。 作为非IT的我,平时使用Matlab比较多。不是科班出身,对于这个题…

Kafka的Spring Cloud Stream

总览 该示例项目演示了如何使用事件驱动的体系结构 , Spring Boot ,Spring Cloud Stream, Apache Kafka和Lombok构建实时流应用程序。 在本教程结束时,您将运行一个简单的基于Spring Boot的Greetings微服务 从REST API获取消息 …

常见的股票技术因子学习以及计算

最近在看《量化投资数据挖掘技术与实践(MATLAB版)》。学习了其中的常见的股票衍生变量,并且利用WIND金融数据终端的matlab借口windmatlab导出一些数据进行了一个简单的学习。特此记录。 下面是我对于书中提到的几个因子的学习总结&#xff1…

Java – HashMap详细说明

HashMap基于哈希算法工作,根据Java文档HashMap具有以下四个构造函数, 建设者 描述 HashMap ​() 构造一个空的 具有默认初始容量(16)和默认加载因子(0.75)的HashMap 。 HashMap ​(int initialCapaci…

Python实现石头-剪刀-布小游戏

近日在学习Python的一些基础知识,觉得还是很有趣的一个一门语言!就目前的学习的一些知识,编写了一些一个简单的石头剪刀布的游戏。主要是熟悉一些Python的一些控制语句。 import random while 1:sint(random.randint(1,3))print(s)print()if…

Python:递归输出斐波那契数列

今天学习Python的时候做一道练习题,题目是这样的: 题目 导入 问题 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总对数为多…

排序算法二:快速排序算法原理以及MATLAB与Python实现

今天继续学习排序算法。今天的主角是快速排序算法。 1. 快速排序基本原理 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。 该方法的基本思想是: 1.先从数列…

排序算法三:堆排序基本原理以及Python实现

1. 基本原理 堆排序就是利用堆的特性进行一个无序序列的排序工作。 堆的特点 堆分为最大堆和最小堆,其实就是完全二叉树。 最大堆要求节点的元素都要不小于其孩子最小堆要求节点元素都不大于其左右孩子。 两者对左右孩子的大小关系不做任何要求,其实…

spring jms 消息_Spring JMS,消息自动转换,JMS模板

spring jms 消息在我的一个项目中,我应该创建一个消息路由器,就像所有路由器一样,它应该从一个主题获取JMS消息并将其放入另一个主题。 该消息本身是JMS文本消息,实际上包含XML消息。 收到消息后,我还应该添加一些其他…

排序算法四:归并排序基本原理以及Python实现

1. 基本原理 归并排序建立在归并操作上的一种算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是将两 个已经有序的序列合成一个有序的序列的过程。 因此,对于一个待排序的序列来说,首先要将其进行…

如何将JAR添加到Jetbrains MPS项目

Jetbrains MPS是创建DSL的绝佳工具。 我们喜欢它,并在我们的咨询工作中定期使用它。 因此,我们之前已经写过关于Jetbrains MPS的文章 。 作为投影编辑器,您可以轻松创建可通过图形界面或数学公式之类使用的DSL。 尽管所有这些功能都需要做一…

Python 3实现k-邻近算法以及 iris 数据集分类应用

前言 这个周基本在琢磨这个算法以及自己利用Python3 实现自主编程实现该算法。持续时间比较长,主要是Pyhton可能还不是很熟练,走了很多路,基本是一边写一边学。不过,总算是基本搞出来了。不多说,进入正题。 1. K-邻近…

UART原理

UART原理 通用异步收发传输器(Universal Asynchronous Receiver / Transmitter),通常称作UART,是一种异步收发传输器,是电脑硬件的一部分。将资料由串行通信与并行通信间作传输转换,作为并行输入成为串行输出的芯片&am…

AttributeError: module 'tensorflow' has no attribute 'placeholder'等一系列tensorflow版本导致的问题

新人tensorflow2.1版本导致程序我无法运行最简单的办法 法1 tensorflow.compat.v1 import tensorflow.compat..v1 as tf tf.disable_v2_behavior() 亲测不好用 法2 卸载2.1,安装老版本 在Terminal界面输入 pip uninstall tensorflow接着输入Y确定卸载。 安装t…

word中一直提示校对错误,如何关闭当前文档校对功能

关闭当前文档校对功能 文件>选项>校对>例外项,选中两个,如图 对比效果:

将测微仪与Spring Boot 2一起使用

这是快速入门,介绍了如何使用出色的Micrometer库来检测基于Spring Boot 2的应用程序并在Prometheus中记录指标 介绍 Micrometer在各种监视工具提供的客户端库上提供了基于Java的外观。 以Prometheus为例,如果我要将Java应用程序与Prometheus集成&#…