《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该刚好瓜仍是恰坏瓜

《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该刚好瓜仍是恰坏瓜

几率论,能够说是在机器学习当中扮演了一个很是重要的角色了。Taoye对几率论知识的掌握目前也还仅仅只是停留在本科期间所接触到的,并且还都已经忘了很多。快速的复习回顾一下以后,用来理解机器学习中的贝叶斯算法,仍是足够的。html

手撕机器学习系列文章目前已经更新了支持向量机SVM、决策树、K-近邻(KNN),如今咱们来玩玩贝叶斯算法,其余机器学习系列文章可根据本身需求来食用(持续更新中):算法

本篇文章主要包括如下几个部分的内容:数据库

  • 到底啥是贝叶斯,很厉害嘛???主要介绍了贝叶斯的一些基础知识,而后写了下笔者对贝叶斯的我的见解,这个部分的内容不难,认真阅读应该都能理解
  • 介绍贝叶斯决策所涉及到的一些理论,其中包括条件几率、全几率、贝叶斯推断等内容,而且经过几个比较生动的案例或是题目帮助你们对理论的理解。这里须要特别值得注意的是:最后一个案例(罐子和石头)务必要理解清楚贝叶斯真正所要表达的实际意义。
  • 这第三部分的内容主要是经过一个西瓜的案例来给大伙进行一下贝叶斯实战,Taoye命名为:“吃瓜群众”应该刚好瓜仍是坏瓜。此“吃瓜群众”就单纯字面上的意思,而非网络用语之“梗”。另外,在这部份内容里面,还会详细介绍标称型数据和数值型数据的具体处理方式,以及经常使用的“平滑”处理——拉普拉斯修正。固然了,这部份内容仍是会照常给你们经过代码的形式来实战这个案例。

1、到底啥是贝叶斯,很厉害嘛???

贝叶斯定理由英国数学家贝叶斯 ( Thomas Bayes 1702-1761 ) 发展,用来描述两个条件几率之间的关系,好比 P(A|B) 和 P(B|A)。按照乘法法则,能够马上导出:P(A∩B) = P(A)P(B|A)=P(B)P(A|B)。如上公式也可变形为:P(A|B)=P(B|A)*P(A)/P(B)。微信

托马斯·贝叶斯(Thomas Bayes,1702-1761),18世纪英国神学家、数学家、数理统计学家和哲学家,几率论理论创始人,贝叶斯统计的创立者,“概括地”运用数学几率,“从特殊推论通常、从样本推论全体”的第一人。网络

放一张大佬的图片镇文:机器学习

图片来源网络

对于贝叶斯算法来说,其优势是在简单易懂,学习效率高,数据较少的状况下仍然有效,而且能够处理多分类问题。函数

至于缺点嘛,在贝叶斯算法中,假设属性与属性之间是有必定的相关性的,这个时候计算量相对会比较复杂,并且处理起来也不是那么的容易。因此就衍生出了朴素贝叶斯来下降属性与属性之间的关系(一句话,没有任何关系),也就是属性之间是彻底独立的,但咱们知道在实际问题中,属性之间很难作到彻底独立。即便这样,朴素贝叶斯依然会有广的应用。学习

上面所提到的属性之间是独立的,这句话应该怎么来理解呢???测试

独立性能够说是几率论当中的常客了。就是说,二者之间没有什么任何关系,我无论你,请你也不要管我,你过你的独木桥,我走个人阳光道,单人作的事情都不会对他人形成任何的影响。(须要重点理解)优化

关于对上述的理解,若有些许疑惑也不要紧,Taoye会在下面经过案例来详细介绍的,以帮助你们对独立性的理解。

另外,在《机器学习实战》这本书中,还提到了该算法的适用数据类型为标称型数据。但从实际来说,除了适用标称型数据来以外,还能适用数值型数据。

这里稍微解释下标称型数据和数值型数据: 标称型数据通常用来表示离散属性,好比身高咱们不对其作具体的多少cm,而是高和矮两种结果。而数值型数据通常针对于连续属性,好比身高咱们能够具体到:170cm、175cm、180cm等等。

在贝叶斯算法中,不一样类型的数据,咱们会有不同的方式来处理。对于标称型数据来说,能够直接经过频率来处理,高的人有几个???矮的人有几个???而对于数值型数据或者说是连续性数据来说,咱们通常考虑几率密度函数来处理,假设连续性数据知足高斯分布。(这里不理解也不要紧,咱们后面会详细来抠抠高斯分布在这里的应用)

以上就是关于贝叶斯算法所涉及到的一些基础概念了,Taoye尽量作到白话了,对于有基础的读者来说应该不是很难理解。有些许疑问也不要紧,下面咱们来具体看看贝叶斯到底是何方神圣???

2、贝叶斯决策相关理论

条件几率:

关于条件几率,其实早在中学时期就有接触过吧,我还犹新记得当时Taoye学这部份内容的时候贼起劲,上课老是与老师疯狂互动。

先这样,再那样,最后再这样搞一下不就解决了嘛,小意思啦

Taoye还特地给你们找出了这本书,就是数学 选修2-3。若是有机会再夕拾这本书的话,必定会很是的有意思,想一想就有点刺激。总共分为A、B版两本,喏,就是紫色皮皮和蓝色皮皮的这本“神书”(有机会必定要夕拾一哈):

好了,好了,咱们来快速回顾一下条件几率吧!

上图的术语,咱们能够把它叫作文氏图、Venn图、温氏图、维恩图、范氏图,都行。它主要用来帮助咱们理解集合与集合之间的关系,根据上图,咱们能够很清楚的看到在B事件发生的状况下,事件A发生的几率\(P(A|B)\)(不明的话能够把它理解成面积,是否是秒懂???):

\[P(A|B) = \frac{P(A \cap B)}{P(B)} \tag{2-1} \]


为了表达对“神书”的敬意,咱们从其中抽一道题目来看看吧~~~

题目来源:人教版高中数学B版选修2-3

Q:抛掷红、蓝两颗骰子,设事件B=“蓝色骰子的点数为3或6”,事件A=“两颗骰子的点数之和大于8”,那么问题来了,在已知蓝色骰子的点数为3或6的时候,事件A发生的几率是多少呢?

咱们知道,每颗筛子有6种可能,抛掷两颗筛子总共有36种可能(6x6=36),对吧?而事件A和事件B同时发生的可能有5种,即\(P(A \cap B)=\frac{5}{36}\),而事件A发生的可能有12种,因此\(P(A)=\frac{12}{36}\),因此咱们能够获得\(P(A|B)\)的值以下:

\[\begin{aligned} P(A|B) & = \frac{P(A \cap B)}{P(B)} \\ & = \frac{\frac{5}{36}}{\frac{12}{36}}=\frac{5}{12} \end{aligned} \]


怎么样,挺简单的吧?上述的条件几率的表达形式是咱们中学时所接触到的,而在贝叶斯算法中的条件几率则稍微有点不一样,只是作了小小的变更。

是酱紫的

前面咱们不是获得了\(P(A|B) = \frac{P(A \cap B)}{P(B)}\)嘛,变更后即:

\[P(A \cap B) = P(A|B) * P(B) \tag{2-2} \]

同理:

\[P(A \cap B) = P(B|A) * P(A) \tag{2-3} \]

因此:

\[P(A|B) * P(B) = P(B|A) * P(A) \tag{2-4} \]

即:

\[P(A|B) = \frac{P(B|A) * P(A)}{P(B)} \tag{2-5} \]

其中,式2-5就是咱们贝叶斯当中得所使用的到的条件几率公式。

全几率公式:

假设样本空间S,是两个事件A与A'的和,以下图:

上图中,事件A和事件A'共同构成了样本空间S。

这种状况下,事件B能划分红两个部分。以下图:

即:

\[P(B) = P(B \cap A) + P(B \cap A^{'}) \tag{2-6} \]

由上面的推导可知:

\[P(B \cap A) = P(B|A)P(A) \tag{2-7} \]

因此

\[P(B) = P(B|A)P(A) + P(B|A^{'})P(A^{'}) \tag{2-8} \]

这就是全几率公式。它的含义是,若是A和A'构成样本空间的一个划分,那么事件B的几率,就等于A和A'的几率分别乘以B对这两个事件的条件几率之和。

将这个全几率公式代入到上面的条件几率公式中,就能够获得条件几率的另外一种写法:

\[P(A|B) = \frac{P(B|A)P(A)}{P(B|A)P(A) + P(B|A^{'})P(A^{'})} \tag{2-9} \]

贝叶斯推断

对条件几率公式进行变形,能够获得以下形式:

\[P(A|B) = P(A)\frac{P(B|A)}{P(B)} \tag{2-10} \]

咱们把P(A)称为"先验几率"(Prior probability),即在B事件发生以前,咱们对A事件几率的一个判断,也就是说这个时候单纯的考虑事件A,与事件B无关。
P(A|B)称为"后验几率"(Posterior probability),即在B事件发生以后,咱们对A事件几率的从新评估,这个时候就要考虑事件B了。
P(B|A)/P(B)称为"可能性函数"(Likelyhood),这是一个调整因子,使得预估几率更接近真实几率。

因此,条件几率能够理解成下面的式子:

\[后验几率 = 先验几率 x 调整因子 \]

这就是贝叶斯推断的含义。咱们先预估一个"先验几率",而后加入实验结果,看这个实验究竟是加强仍是削弱了"先验几率",由此获得更接近事实的"后验几率"。

在这里,若是"可能性函数"P(B|A)/P(B)>1,意味着"先验几率"被加强,事件A的发生的可能性变大;若是"可能性函数"=1,意味着B事件无助于判断事件A的可能性;若是"可能性函数"<1,意味着"先验几率"被削弱,事件A的可能性变小。

上述内容,来自于阮一峰老师的网络日志: http://www.ruanyifeng.com/blog/2011/08/bayesian_inference_part_one.html

为了加深对贝叶斯推断的理解,咱们来看看下面的一个例子:


例子参考于:《机器学习实战》

如今有彻底同样的一、2号两个罐子,其中1号罐有4块石头,分别是2白2黑;2号罐子有3块石头,分别1白2黑。如今随机选择一个罐子,从中抓起1块石头,发现是白色的,请问这块白色石头更可能来自于哪个罐子???

这道题目是Taoye根据《机器学习实战》这本书上的例子进行改动的,主要是为了方便你们更容易理解贝叶斯在分类问题中的应用。注意这道题问的是:更可能来自于哪个罐子?

总共就两个罐子,不是1号罐子就是2号罐子,而更可能描述的是一个可能性,其实就至关于一个分类问题。来自哪个罐子的可能性更大,咱们最终就把这个白石头归类于哪个罐子。

换句话讲,咱们能够把石头的颜色表示为样本的属性特征,而罐子的类别则表示为样本所对应的标签。(这种问题的转化思惟必定要引发重视)至此的话,咱们就能够分别计算出来自于一、2号罐子的几率,哪个更大,那么就将该石头归类于那一个罐子。

咱们不妨经过上述的条件几率公式来进行分析,条件几率重现以下:

\[P(A|B) = P(A)\frac{P(B|A)}{P(B)} \]

对此,咱们令事件A=“来自1号罐子”,事件B=“选中了白色石头”。

则咱们能够知道,由于2个罐子是彻底同样的,因此:

\[P(A) = \frac{1}{2} \]

\(P(B|A)\)表示的是在1号罐子中选中白色石头的几率,咱们知道1号罐子中有四块石头,其中有两块是白色的,因此:

\[P(B|A) = \frac{2}{4}=\frac{1}{2} \]

\(P(B)\)很简单,就是在全局中选中白色石头的几率,全局有7块,其中白色石头有3块,因此:

\[P(B) = \frac{3}{7} \]

综上,咱们就能够获得咱们的条件几率结果,即在发现是白色的前提下,这块石头来自1号罐子的几率为:

\[\begin{aligned} P(A|B) & = P(A)\frac{P(B|A)}{P(B)} \\ & = \frac{1}{2}\frac{\frac{1}{2}}{\frac{3}{7}}=\frac{7}{12} \end{aligned} \]

同理可知,假设事件C=“来自2号罐子”,咱们能够计算出此时的条件几率:

\[\begin{aligned} P(C|B) & = P(A)\frac{P(C|A)}{P(C)} \\ & = \frac{1}{2}\frac{\frac{1}{3}}{\frac{3}{7}}=\frac{7}{18} \end{aligned} \]

对于这道题来说,先验几率\(P(A)=P(C)=\frac{1}{2}\),通过调整因子(可能性函数)处理以后获得的后验几率\(P(A|B)=\frac{7}{12}\),而\(P(C|B)=\frac{7}{18}\)。也就是说在取出一个白石头以前,事件A和事件C的可能性是相同的,而在取出一个白石头以后,事件A的可能性获得了加强,而事件C的可能性获得了的减弱。且\(P(A|B) > P(C|B)\),为此,咱们更情愿将取到的这个白球归类于1号罐子。

上面这段话,各位读者必定要重点理解清楚,这个对于理解朴素贝叶斯的实际意义有着很是重要的做用。咱们能够这样说:在被检测样本的各个属性已知的前提下,咱们须要经过贝叶斯算法来计算该样本分别为各种别的几率状况,以此来判断该被检测样本的最终分类。

不知道各位读者有没有注意噢,对于上述问题,白球的归类不是1号罐就是2号罐,按道理来说\(P(A|B)+P(C|B)=1\),然而咱们发现,将计算出来的这两个值相加以后并无等于1,这不是彻底不讲道理嘛,真的是讨厌。。。

首先,值得确定的是,存在这种疑问的读者很是的棒,说明在阅读的过程有认真的在思考。其实,有这疑问的读者忽视了“域”的问题,咱们所理解的\(P(A|B)+P(C|B)=1\)是在总体“域”当中,也就是7个石头,而考虑条件几率的时候,“域”就已经发生了改变,此时的“域”就再也不是一个总体了,而是被分割成了两个子“域”,因此此时计算的两个几率和并不会必定为1。(重点理解)

关于上述“域”的问题,为Taoye在学习过程当中独立思考所得,暂时没有参考任何的权威资料,因此不能彻底保证上述说法的正确性。若有问题,还请各位读者不吝赐教,在下方留言或是私聊Taoye。

最后再提醒一句,将这道题的真正意义搞懂,对于理解贝叶斯算法真的尤其重要。


3、贝叶斯实战之恰瓜群众应该刚好瓜仍是坏瓜

在本节内容中,咱们主要用周志华老师的西瓜书上的一个例子来理解下贝叶斯的应用,随后会经过代码的形式来解决问题。整体上的过程与上述例子大体相同,主要在于读者对于不一样的问题要学会变通,要学会对问题的转换。就像《周易》里说的那样,穷则变,变则通,通则久。这一点仍是挺重要的,尤为是对于咱们学生来说。

下面咱们开始进入到正题。

例子参考于:周志华-《机器学习》第四章

为了让读者在阅读的过程当中不是那么的无趣,或是能更好的进入到这个案例,Taoye编个简短的故事来做为引子吧。

注意:此“吃瓜群众”就单纯字面上的意思,而非网络用语之“梗”。

从前有座山,山上有座庙,庙里有位吃瓜群众在吃瓜。(唱起来还挺顺口的,hhhhhh)

同时,庙里面也有成千上百的西瓜可供吃瓜群众食用。一开始的时候,吃瓜群众仍是很是开心的,一口一个西瓜吞吞的下肚。可是这西瓜恰到必定数量的时候,他发现有的瓜是好瓜,而有的瓜是坏瓜,当时就困惑着:我滴乖乖,这坏瓜该不会是过时了吧???

那咋行呢?我要每次恰以前可以挑选出坏瓜才行,至少说挑选出好瓜的几率要比坏瓜大才能够吧。为此,他收集了以前恰西瓜时候的一些属性特征以及对应标签,以此来做为他判别好瓜仍是坏瓜的依据。

吃瓜群众收集到的西瓜数据以下所示:

这个数据样本集总共有17个西瓜,其中好瓜有8个,坏瓜有9个。

这个吃瓜群众的案例相较于前面罐子石头的来说就复杂一点点,但也只是一点点而已。这里涉及到了多个属性特征,并且除了标称型数据以外,还有数值型数据,这些不一样类型的数据咱们须要怎么处理呢???另外还有一点须要说的是,假如说咱们的检测西瓜中的特征值在17个样本里面不存在,那么这个时候又应该须要怎么处理呢???

以上所提到的都是咱们这节内容中所须要解决的问题。

  • 属性问题的解决

在前面罐子石头的案例中,咱们的属性特征只有颜色一个,而在这个吃瓜群众的案例里面,属性特征却有色泽、根蒂、敲声、纹理、脐部、触感、密度、含糖率8个。

经过前面几篇手撕机器学习的文章来看,咱们能够知道,当一个样本数据中的属性特征有多个的时候,这个时候咱们能够把这多个属性特征看作是一个总体,什么总体呢???没错,就是一个特征向量。

咱们不妨将这里的特征向量表示为\(x=(色泽,根蒂,敲声,纹理,脐部,触感,密度,含糖率)\),而好瓜、坏瓜标签表示为\(c\),则在已知一个被检测西瓜样本的属性特征的前提下,咱们要来判断这个瓜是好瓜仍是坏瓜,则经过贝叶斯定理,咱们有

\[P(c|x)=\frac{P(c)P(x|c)}{P(x)} \tag{3-1} \]

经过上式,咱们不不难发现,基于贝叶斯公式3-1来估计后验几率\(P(c|x)\)的主要困难在于:类条件几率\(P(x|c)\)是全部属性上的联合几率,很难从有限的训练样本中直接估计而得。还有一点就是,这种形式的表示就至关于笛卡尔积,这个对计算也不是很友好。(关于笛卡尔积,读者可自行了解,后期有机会的话Taoye也会来介绍)

为了避开上述这个问题,“朴素贝叶斯分类器”就采用了“属性条件独立性假设”:对已知类别,假设全部属性相互独立,互相不会产生任何的影响。这个时候,咱们再来从新阅读前面所说到的一句话: 我无论你,请你也不要管我,你过你的独木桥,我走个人阳光道,单人作的事情都不会对他人形成任何的影响。

是否是独立的理解有点感受了???

基于属性条件独立性假设,式子3-1,咱们能够重写为:

\[P(c|x)=\frac{P(c)P(x|c)}{P(x)}=\frac{P(c)}{P(x)}\Pi_{i=1}^8P(x_i|c) \tag{3-2} \]

而咱们知道,对于一个检测西瓜样原本讲,该样本每个属性特征值在每一个样本类别里计算获得的结果都是同样的,好比说对于好瓜与坏瓜的判别来说,计算获得的\(P(x)\)都是相同的。换句话讲,\(P(x)\)的计算结果并不会对不一样标签计算后验几率结果产生任何的影响,也就是说,要想判别这个是好瓜仍是坏瓜,咱们没有必要去计算\(P(x)\)的值,这是画蛇添脚、画蛇添足。对此,咱们获得以下所示:

\[h_{nb}(x) = arg \ maxP(c)\Pi_{i=1}^8P(x_i|c) \tag{3-3} \]

这也就是咱们的朴素贝叶斯的表达式,表达的意思就是比较不一样类别时候的\(P(c)\Pi_{i=1}^8P(x_i|c)\),值最大者所对应的标签就是咱们想要的分类结果。

不难吧???应该能看懂吧???也应该能理解吧???感受解释的已经很白话了 (ノへ ̄、)

  • 不一样数据类型的处理方式

咱们观察数据,能够发现样本的属性特征有两类,一类是标称型属性数据:色泽、根蒂、敲声、纹理、脐部、触感,另外一类是数值型数据:密度、含糖率。咱们能够把标称型数据理解成离散型的,而把数值型数据理解成连续型的,而在贝叶斯算法中,不一样类型的数据会有不一样的处理方式。

对于离散属性来说,令\(D_{c,x_i}\)表示\(D_c\)中在第i属性上取值为\(x_i\)的样本组成的集合,则条件几率\(P(x_i|c)\)能够估计为:

\[P(x_i|c)=\frac{|D_{c,x_i}|}{|D_c|} \tag{3-4} \]

换言之,就是频率的一种计算。

而对于连续属性来说,咱们能够考虑几率密度函数,假定\(p(x_i|c)\)服从\(N(u_{c,i},\sigma_{c,i}^2)\),其中\(u_{c,i}\)\(\sigma_{c,i}^2\)分别是第c类样本在第i个属性上取值的均值和方差,则有:

\[p(x_i|c)=\frac{1}{\sqrt{2\pi}\sigma_{c,i}}exp(-\frac{(x_i-u_{c,i})^2}{2\sigma_{c,i}^2}) \tag{3-5} \]

也就是说此时的\(p(x_i|c)\)就至关于把数据样本集中所对应特征的全部数值型数据服从高斯分布,依次来计算\(p(x_i|c)\)的结果

ok,这两个问题搞懂了以后,咱们就能够来计算下吃瓜群众所恰西瓜的好坏了

咱们不妨假设此时恰瓜群众此时拿到的一个西瓜所对应属性特征以下,咱们经过贝叶斯来判断该西瓜的好坏:

咱们首先计算先验几率\(P(c)\),因为总共有17个瓜,其中好瓜8个,坏瓜9个,因此有:

\[\begin{aligned} & P(好瓜=是)=\frac{8}{17}=0.471 \\ & P(好瓜=否)=\frac{9}{17}=0.529 \end{aligned} \]

以后,为每一个属性估计条件几率\(P(x_i|c)\)

\[\begin{aligned} & P_{青绿|是}=P(色泽=青绿|好瓜=是)=\frac{3}{8}=0.375 \\ & P_{青绿|否}=P(色泽=青绿|好瓜=否)=\frac{3}{9}=0.333 \\ & P_{蜷缩|是}=P(根蒂=蜷缩|好瓜=是)=\frac{5}{8}=0.625 \\ & P_{蜷缩|否}=P(根蒂=蜷缩|好瓜=否)=\frac{3}{9}=0.333 \\ & P_{浊响|是}=P(敲声=浊响|好瓜=是)=\frac{6}{8}=0.750 \\ & P_{浊响|否}=P(敲声=浊响|好瓜=否)=\frac{4}{9}=0.444 \\ & P_{清晰|是}=P(纹理=清晰|好瓜=是)=\frac{7}{8}=0.875 \\ & P_{清晰|否}=P(纹理=清晰|好瓜=否)=\frac{2}{9}=0.222 \\ & P_{凹陷|是}=P(脐部=凹陷|好瓜=是)=\frac{6}{8}=0.625 \\ & P_{凹陷|否}=P(脐部=凹陷|好瓜=否)=\frac{2}{9}=0.222 \\ & P_{硬滑|是}=P(触感=硬滑|好瓜=是)=\frac{6}{8}=0.750 \\ & P_{硬滑|否}=P(触感=硬滑|好瓜=否)=\frac{6}{9}=0.667 \\ \end{aligned} \]

\[\begin{aligned} P_{密度:0.697|是} & =P(密度=0.697|好瓜=是) \\ & = \frac{1}{\sqrt{2\pi}0.129}exp(-\frac{(0.697-0.574)^2}{2*0.129^2}) \\ & = 1.962 \\ P_{密度:0.697|否} & =P(密度=0.697|好瓜=否) \\ & = \frac{1}{\sqrt{2\pi}0.195}exp(-\frac{(0.697-0.496)^2}{2*0.195^2}) \\ & = 1.194 \\ P_{含糖:0.460|是} & =P(含糖=0.460|好瓜=是) \\ & = \frac{1}{\sqrt{2\pi}0.101}exp(-\frac{(0.460-0.279)^2}{2*0.101^2}) \\ & = 0.669 \\ P_{含糖:0.460|否} & =P(含糖=0.460|好瓜=否) \\ & = \frac{1}{\sqrt{2\pi}0.108}exp(-\frac{(0.460-0.154)^2}{2*0.108^2}) \\ & = 0.42 \\ \end{aligned} \]

这里有必要说一点:在周志华西瓜书中\(P_{凹陷|是}\)计算结果是有错误的,实际结果应该是0.625,而非0.750,读者可自行计算从而验证

因而,咱们能够计算获得该瓜是好瓜和坏瓜的可能性以下

\[\begin{aligned} & P(好瓜=是)*P_{青绿|是}*P_{蜷缩|是}*P_{浊响|是}*P_{清晰|是} \\ & \quad \quad \quad \quad \quad \quad *P_{凹陷|是}*P_{硬滑|是}*P_{密度:0.697|是}*P_{含糖:0.460|是}=0.046 \\ & P(好瓜=否)*P_{青绿|否}*P_{蜷缩|否}*P_{浊响|否}*P_{清晰|否}\\ & \quad \quad \quad \quad \quad \quad*P_{凹陷|否}*P_{硬滑|否}*P_{密度:0.697|否}*P_{含糖:0.460|否}=4.36*10^{-5} \end{aligned} \]

由计算能够获得,\(0.046>4.36*10^{-5}\),因此咱们理应将这个判别样本归类于“好瓜”

下面,咱们不妨经过代码来描述上述贝叶斯的判别过程。

首先,创建一个establish_data方法用于准备数据:

定义一个calc_label_countcalc_p_c方法,分别用于统计不一样类别标签的数量,以及计算各种别在数据样本集中的频率,即各种别的\(P(c)\)值:

程序运行结果以下,可见与咱们前面手动计算的结果一致

根据上述贝叶斯分类的流程,还需定义一个calc_dispersed_p_xi_c方法以及calc_continuity_p_xi_c来分别计算\(P(x_i|c)\)的值,方法分别对应着离散型数据和连续型数据

不过有一点还须要说明的是,在计算连续型数据的\(P(x_i,c)\)的时候,咱们还应该提早得知数据的均值以及方差,为此还需定义一个calc_mean_standard方法来实现这个功能,该三个核心方法的具体代码以下(都挺简单的):

运算结果以下图所示:

能够看到,此时的贝叶斯算法判断该瓜为好瓜,与咱们实际的标签一致,说明预测正确。固然了,这个代码只是预测了一个西瓜样本,读者可自行根据程序代码预测多个样本西瓜,从而判断该贝叶斯的正确率。

完整代码:

import numpy as np

"""
    Author: Taoye
    微信公众号: 玩世不恭的Coder
    Explain: 用于生成样本的属性特征以及对应的标签
    Return:
        x_data: 数据样本的属性,其中包括8个属性
        y_label: 样本属性所对应的标签
"""
def establish_data():
    x_data = [[1, 1, 1, 1, 1, 1, 0.697, 0.460],
             [2, 1, 2, 1, 1, 1, 0.774, 0.376],
             [2, 1, 1, 1, 1, 1, 0.634, 0.264],
             [1, 1, 2, 1, 1, 1, 0.608, 0.318],
             [3, 1, 1, 1, 1, 1, 0.556, 0.215],
             [1, 2, 1, 1, 2, 2, 0.403, 0.237],
             [2, 2, 1, 2, 2, 2, 0.481, 0.149],
             [2, 2, 1, 1, 2, 1, 0.437, 0.211],
             [2, 2, 2, 2, 2, 1, 0.666, 0.091],
             [1, 3, 3, 1, 3, 2, 0.243, 0.267],
             [3, 3, 3, 3, 3, 1, 0.245, 0.057],
             [3, 1, 1, 3, 3, 2, 0.343, 0.099],
             [1, 2, 1, 2, 1, 1, 0.639, 0.161],
             [3, 2, 2, 2, 1, 1, 0.657, 0.198],
             [2, 2, 1, 1, 2, 2, 0.360, 0.370],
             [3, 1, 1, 3, 3, 1, 0.593, 0.042],
             [1, 1, 2, 2, 2, 1, 0.719, 0.103]]
    y_label = [0, 0, 0, 0, 0, 0, 0, 0,
              1, 1, 1, 1, 1, 1, 1, 1, 1]
    return np.array(x_data), np.array(y_label)

"""
    Author: Taoye
    微信公众号: 玩世不恭的Coder
    Explain: 用于统计不一样标签的样本数量
    Parameters:
        y_label: 样本属性所对应的标签
    Return:
        label_count: 不一样样本标签的数量
"""
def calc_label_count(y_label):
    label_count_0, label_count_1 = 0, 0; data_number = y_label.shape[0]
    for label in y_label:    # 遍历y_label,统计不一样类别的数量
        if int(label) == 0: label_count_0 += 1
        if int(label) == 1: label_count_1 += 1
    return label_count_0, label_count_1

"""
    Author: Taoye
    微信公众号: 玩世不恭的Coder
    Explain: 用于计算各种别在数据样本集中的频率,即各种别的$P(c)$值:
    Parameters:
        y_label: 样本属性所对应的标签
    Return:
        pc: 指定对应标签的频率值
"""
def calc_p_c(y_label):
    data_number = y_label.shape[0]
    label_count_0, label_count_1 = calc_label_count(y_label)
    return label_count_0 / data_number, label_count_1 / data_number

"""
    Author: Taoye
    微信公众号: 玩世不恭的Coder
    Explain: 用于计算各种别在数据样本集中的频率,即各种别的$P(c)$值,主要用于标称型数据
    Parameters:
        y_label: 样本属性所对应的标签
    Return:
        pc: 指定对应标签的频率值
"""
def calc_dispersed_p_xi_c(test_data, x_data, y_label, attribute_index):
    label_count_0, label_count_1  = calc_label_count(y_label)
    attribute_count_0, attribute_count_1 = 0, 0
    for item in x_data[:label_count_0]:
        if test_data[attribute_index] == item[attribute_index]:
            attribute_count_0 += 1
    for item in x_data[label_count_0:]:
        if test_data[attribute_index] == item[attribute_index]:
            attribute_count_1 += 1
    return attribute_count_0 / label_count_0, attribute_count_1 / label_count_1

"""
    Author: Taoye
    微信公众号: 玩世不恭的Coder
    Explain: 用于计算均值和标准差
"""
def calc_mean_standard(x_data):
    mean_value_0, mean_value_1 = np.mean(x_data[:8, 6:8], axis = 0), np.mean(x_data[8:, 6:8], axis = 0)
    std_value_0, std_value_1 = np.std(x_data[:8, 6:8], axis = 0), np.std(x_data[8:, 6:8], axis = 0)
    return mean_value_0, mean_value_1, std_value_0, std_value_1

"""
    Author: Taoye
    微信公众号: 玩世不恭的Coder
    Explain: 将数据进行高斯转化
"""
def calc_gaussian(data, mean_value, std_value):
    return (1 / (np.sqrt(2*np.pi) * std_value)) * (np.e ** ((- (data - mean_value) ** 2) / (2 * (std_value) ** 2)))

"""
    Author: Taoye
    微信公众号: 玩世不恭的Coder
    Explain: 计算数值型数据的p_xi_c
"""
def calc_continuity_p_xi_c(test_data, x_data):
    mean_value_0, mean_value_1, std_value_0, std_value_1 = calc_mean_standard(x_data)  
    pxi_density_0 = calc_gaussian(test_data[6], mean_value_0[0], std_value_0[0])
    pxi_density_1 = calc_gaussian(test_data[6], mean_value_1[0], std_value_1[0])
    pxi_sugar_0 = calc_gaussian(test_data[7], mean_value_0[1], std_value_0[1])
    pxi_sugar_1 = calc_gaussian(test_data[7], mean_value_1[1], std_value_1[1])
    return pxi_density_0, pxi_density_1, pxi_sugar_0, pxi_sugar_1

if __name__ == "__main__":
    test_data = [1, 1, 1, 1, 1, 1, 0.697, 0.460]
    x_data, y_label = establish_data()
    attr0 = calc_dispersed_p_xi_c(test_data, x_data, y_label, 0)
    attr1 = calc_dispersed_p_xi_c(test_data, x_data, y_label, 1)
    attr2 = calc_dispersed_p_xi_c(test_data, x_data, y_label, 2)
    attr3 = calc_dispersed_p_xi_c(test_data, x_data, y_label, 3)
    attr4 = calc_dispersed_p_xi_c(test_data, x_data, y_label, 4)
    attr5 = calc_dispersed_p_xi_c(test_data, x_data, y_label, 5)
    print("标称型数据的P_{(x_i,c)}:", attr0, attr1, attr2, attr3, attr4, attr5)
    pxi_density_0, pxi_density_1, pxi_sugar_0, pxi_sugar_1 = calc_continuity_p_xi_c(test_data, x_data)
    print("数值型数据的P_{(x_i,c)}:", pxi_density_0, pxi_density_1, pxi_sugar_0, pxi_sugar_1)
    p1, p2 = calc_p_c(y_label)
    print("数据样集中的各种别的几率状况分别为:", p1, p2)
    p_good_melon = p1 * attr0[0] * attr1[0] * attr2[0] * attr3[0] * attr4[0] * attr5[0] * pxi_density_0 * pxi_sugar_0
    p_bad_melon = p2 * attr0[1] * attr1[1] * attr2[1] * attr3[1] * attr4[1] * attr5[1] * pxi_density_1 * pxi_sugar_1
    print("分类为好瓜和坏瓜的可能性分别为:", p_good_melon, p_bad_melon)
    print("恰瓜群众拿到这个是好瓜") if p_good_melon >= p_bad_melon else print("恰瓜群众拿到这个是好瓜")

在本节开始的时候,咱们提出了三个问题,其中已经已经解决了两个,如今咱们来解决最后一个问题。

  • 假如说咱们的检测西瓜中的特征值在17个样本里面都不存在,那么这个时候又应该须要怎么处理呢???

就是说,若某个属性值在训练集中没有与某个类同时出现,则咱们根据前面所提到的朴素贝叶斯进行判别将会出现问题。例如,在使用西瓜数据集训练朴素贝叶斯的时候,对一个“敲声=清脆”的测试样例,有:

\[P_{清脆|是}=P(敲声=清脆|好瓜=是)=\frac{0}{8}=0 \]

由连乘式计算出的几率值为0,所以,不管该样本的其余属性特征是什么,哪怕在其余属性上明显是好瓜,分类的结果都是“好瓜=否”,这个显然不是很合理。

为了不其余属性携带的信息被训练集中未出现的属性值“抹去”,在估计几率值时一般要进行“平滑”操做,经常使用的是“拉普拉斯修正”。具体来讲,令N表示训练集D中可能的类别数,\(N_i\)表示第i个属性可能的取值数,则此时的式子3-4和3-5分别修正为:

\[\hat{P}(c) = \frac{|D_c| + 1}{|D| + N} \\ \hat{P}(x_i|c)=\frac{|D_{c,x_i}|+1}{|D_c|+N_i} \]

例如,在本节例子中,类先验几率可估计为:

\[\hat{P}(好瓜=是)=\frac{8+1}{17+2},\hat{P}(好瓜=否)=\frac{9+1}{17+2}=0.526 \]

这个拉普拉斯修正没什么难点,主要是处理单个属性在数据样本中不存在的问题,读者可根据拉普拉斯修正的方式来将上述完整代码进行改进。

关于贝叶斯算法,其实后面还有些内容,限于篇幅缘由,咱们留着后面有机会再来肝。

若是这篇文章对您有所帮助,点个赞、分享下吧~~~

这篇文章就不唠嗑了。

我是Taoye,爱专研,爱分享,热衷于各类技术,学习之余喜欢下象棋、听音乐、聊动漫,但愿借此一亩三分地记录本身的成长过程以及生活点滴,也但愿能结实更多志同道合的圈内朋友,更多内容欢迎来访微信公主号:玩世不恭的Coder。

咱们下期再见,拜拜~~~

参考资料:

[1] 《机器学习实战》:Peter Harrington 人民邮电出版社
[2] 《统计学习方法》:李航 第二版 清华大学出版社
[3] 《机器学习》:周志华 清华大学出版社
[4] 人教版高中数学B版选修2-3
[5] 贝叶斯推断及其互联网应用:http://www.ruanyifeng.com/blog/2011/08/bayesian_inference_part_one.html

推荐阅读

《Machine Learning in Action》—— 女同窗问Taoye,KNN应该怎么玩才能通关
《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非线性支持向量机
《Machine Learning in Action》—— hao朋友,快来玩啊,决策树呦
《Machine Learning in Action》—— Taoye给你讲讲决策树究竟是支什么“鬼”
《Machine Learning in Action》—— 剖析支持向量机,优化SMO
《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM
print( "Hello,NumPy!" )
干啥啥不行,吃饭第一名
Taoye渗透到一家黑平台总部,背后的真相细思极恐
《大话数据库》-SQL语句执行时,底层究竟作了什么小动做?

相关文章
相关标签/搜索