朴素贝叶斯算法实现分类以及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,一经查实,立即删除!

相关文章

编写自定义的AssertJ断言

AssertJ是广泛使用的Hamcrest匹配器的替代匹配库。 实际上,对于我自己的项目,我已经更改为仅使用AssertJ-我只是发现流畅的界面和可扩展性非常吸引人。 您可以编写自定义断言,如下所示: 想象一下一种具有强度和饮料类型的咖啡 &…

LintCode-A + B 问题

文章转载 http://blog.csdn.net/wangyuquanliuli/article/details/47755461 给出两个整数a和b, 求他们的和, 但不能使用 等数学运算符。 您在真实的面试中是否遇到过这个题? Yes样例 如果 a1 并且 b2,返回3 注意 你不需要从输入流读入数据,…

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

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

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

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

使用JDK 8轻松进行细粒度排序

Java的8的推出流和有用的静态 / 默认的方法比较接口可以很容易地根据个人的领域两个对象比较“值,而不需要实现一个比较(T,T)在其对象的类方法被比较。 我将使用一个简单的Song类来帮助演示这一点,接下来显示其Song.j…

主成分分析以及应用:企业综合实力排序

这段时间一直在学习数据挖掘的一些算法,今天通过不断查阅资料,学习整理了一下主成分分析这个数据降维算法。并且结合一个实例进行matlab编程实现。 主成分基本原理 在数据挖掘中,经常会遇到一个问题就是一个问题出现了n多个变量,…

自定义MongoDB的Spring Social Connect框架

在上一篇文章中 ,我谈到了我面临的第一个挑战是更改数据模型并添加连接框架。 在这里,我想提供有关我如何做的更多详细信息。 Spring Social项目已经提供了基于jdbc的连接存储库实现,以将用户连接数据持久保存到关系数据库中。 但是&#xff…

算法题:输入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获取消息 …

使用JShell的Java 9 Streams API

这篇文章着眼于使用JShell的Java 9 Streams API。 Streams API的更改以Java 8中Streams的成功为基础,并引入了许多实用程序方法– takeWhile,dropWhile和iterate。 这篇文章延续了My Top Java 9功能,并使用Jshell探索了这些方法。 流API Str…

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

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

算法题:输入一个表示整数的字符串,把该字符串转换成整数并输出。例如输入字符串“12345”,则输出整数“12345”

今天这道算法题比较简单,主要考察的思考问题的全面性。这个需要考虑的几种情况。 如果输入的整数字符串是个负数,怎么处理? 如果输入的第一个字符是0,则怎么处理? 如果输入的是非0~9之间的字符怎么处理?…

排序算法一:冒泡排序,插入排序以及选择排序原理与MATLAB实现

最近在学习排序算法的一些知识。还是比较有趣的。所以好好研究了一下各个算法。并且使用matlab进行了个基本的实现,目前仅仅是实现吧,优化什么的可能目前的水平达不到吧,毕竟是用matlab实现,还是比较简单。以后还是希望使用C/C&am…

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个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总对数为多…

Spring Webflux –编写过滤器

Spring Webflux是Spring 5的一部分提供的新的响应式Web框架。 在传统的基于Spring MVC的应用程序( Servlet Filter , HandlerInterceptor )中编写过滤器的方式与在基于Spring Webflux的应用程序中编写过滤器的方式非常不同,本文将…

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

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