朴素贝叶斯分类算法和实例演示

本文开始,我们来学习一种新的机器学习方法:贝叶斯算法。
这次从最基础的朴素贝叶斯分类算法出发,了解相关的算法原理。

考虑如下一种分类问题:样本中只包含2类特征,标签只有0和1。
目前要评估两个特征值分别为a和b时的分类结果。

使用朴素贝叶斯分类算法的核心逻辑是:基于概率论的相关理论直接计算两个特征值分别为a和b时,标签值为0和1的概率,然后选择更大的概率值对应的标签值作为分类结果。

贝叶斯公式

既然是基于概率论,那就得先清楚算法使用所必要的概率论原理。
说来尴尬,虽然我本科概率论的课程成绩还看得过去,但是实际上大部分内容都已经忘记了,所以还是从尽量基础的条件概率公式开始
P ( B ∣ A ) = P ( A B ) / P ( A ) P(B|A)=P(AB)/P(A) P(BA)=P(AB)/P(A)
此处, P ( B ∣ A ) P(B|A) P(BA)指的是B在A发生的条件下发生的概率(后验概率), P ( A B ) P(AB) P(AB)指的是A和B同时发生的概率,P(A)指的是A发生的概率(先验概率)。

先找个简单实例重温一下条件概率公式:假设有5个完全相同的箱子,只有一个箱子内有钱,定义A为第1箱子内无钱,B为第2个箱子有钱。用最朴素的直观逻辑,可以得知
P ( A ) = 4 / 5 , P ( A B ) = 1 / 5 , P ( B ∣ A ) = 1 / 4 P(A)=4/5,P(AB)=1/5,P(B|A)=1/4 P(A)=4/5,P(AB)=1/5,P(BA)=1/4
显然,该实例中的概率值是满足之前的条件概率公式的。

将条件概率中的A和B换一下,可以得到
P ( A ∣ B ) = P ( A B ) / P ( B ) P(A|B)=P(AB)/P(B) P(AB)=P(AB)/P(B)
由此可以得到
P ( B ∣ A ) ∗ P ( A ) = P ( A ∣ B ) ∗ P ( B ) = P ( A B ) P(B|A)*P(A)=P(A|B)*P(B)=P(AB) P(BA)P(A)=P(AB)P(B)=P(AB)
再做一下变形
P ( B ∣ A ) = P ( A ∣ B ) ∗ P ( B ) P ( A ) P(B|A)=\frac{P(A|B)*P(B)}{P(A)} P(BA)=P(A)P(AB)P(B)
哈,终于得到贝叶斯公式了。

算法原理

看上面那个公式,好像和机器学习没多少关系,所以我们需要用机器学习的语言去理解一下这个公式:
P ( 类别 ∣ 特征 ) = P ( 特征 ∣ 类别 ) ∗ P ( 类别 ) P ( 特征 ) P(类别|特征)=\frac{P(特征|类别)*P(类别)}{P(特征)} P(类别特征)=P(特征)P(特征类别)P(类别)
回到本文开始的分类问题,有两组特征,那么可以分别计算 P ( 0 ∣ 特征 1 = a , 特征 2 = b ) P(0|特征1=a,特征2=b) P(0∣特征1=a,特征2=b) P ( 1 ∣ 特征 1 = a , 特征 2 = b ) P(1|特征1=a,特征2=b) P(1∣特征1=a,特征2=b),如果前者的P值更大,那么分类为0,反之则分类为1。

接下来以 P ( 0 ∣ 特征 1 = a , 特征 2 = a ) P(0|特征1=a,特征2=a) P(0∣特征1=a,特征2=a)为例,分析一下其具体的计算过程。
P ( 0 ∣ 特征 1 = a , 特征 2 = b ) = P ( 特征 1 = a , 特征 2 = b ∣ 0 ) ∗ P ( 0 ) P ( 特征 1 = a , 特征 2 = b ) P(0|特征1=a,特征2=b)=\frac{P(特征1=a,特征2=b|0)*P(0)}{P(特征1=a,特征2=b)} P(0∣特征1=a,特征2=b)=P(特征1=a,特征2=b)P(特征1=a,特征2=b∣0)P(0)
先计算最简单的 P ( 0 ) P(0) P(0):给定训练集后, P ( 0 ) P(0) P(0)可以直接通过统计训练集中的标签值数量得到。

然后考虑 P ( 特征 1 = a , 特征 2 = b ∣ 0 ) P(特征1=a,特征2=b|0) P(特征1=a,特征2=b∣0):给定训练集后,特征值恰好分别a和b的情况可能不多,甚至为0,所以期望在训练集中直接寻找该组合的数量的方式是不可靠的。
为了稳定地计算该P值,我们在此处做出假设:各特征之间相互独立。
这样,该值可以等价为
P ( 特征 1 = a , 特征 2 = b ∣ 0 ) = P ( 特征 1 = a ∣ 0 ) ∗ P ( 特征 2 = b ∣ 0 ) P(特征1=a,特征2=b|0)=P(特征1=a|0)*P(特征2=b|0) P(特征1=a,特征2=b∣0)=P(特征1=a∣0)P(特征2=b∣0)
上式的右侧各项值是很容易通过训练集统计得到的。

接下来简单证明一下上述公式。先将条件概率公式做一下扩展
P ( A B ∣ C ) = P ( A B C ) P ( C ) P(AB|C)=\frac{P(ABC)}{P(C)} P(ABC)=P(C)P(ABC)
将右式做变换
P ( A B ∣ C ) = P ( A C ) P ( C ) ∗ P ( A B C ) P ( A C ) P(AB|C)=\frac{P(AC)}{P(C)}*\frac{P(ABC)}{P(AC)} P(ABC)=P(C)P(AC)P(AC)P(ABC)
显然右式是两个条件概率值
P ( A B ∣ C ) = P ( A ∣ C ) ∗ P ( B ∣ A C ) P(AB|C)=P(A|C)*P(B|AC) P(ABC)=P(AC)P(BAC)
因为A和B相互独立,所以在C发生的条件下,A发生与否并不影响B发生的概率,即
P ( B ∣ A C ) = P ( B ∣ C ) P(B|AC)=P(B|C) P(BAC)=P(BC)
将上式带入上上式,得到
P ( A B ∣ C ) = P ( A ∣ C ) ∗ P ( B ∣ C ) P(AB|C)=P(A|C)*P(B|C) P(ABC)=P(AC)P(BC)
设定A为“特征1=a”,B为“特征2=b”,C为“标签值=0”,上式变为
P ( 特征 1 = a , 特征 2 = b ∣ 0 ) = P ( 特征 1 = a ∣ 0 ) ∗ P ( 特征 2 = b ∣ 0 ) P(特征1=a,特征2=b|0)=P(特征1=a|0)*P(特征2=b|0) P(特征1=a,特征2=b∣0)=P(特征1=a∣0)P(特征2=b∣0)
至此,公式得到了证明。

最后看一下 P ( 特征 1 = a , 特征 2 = b ) P(特征1=a,特征2=b) P(特征1=a,特征2=b):在特征相互独立的假设上,该值等价于
P ( 特征 1 = a , 特征 2 = b ) = P ( 特征 1 = a ) ∗ P ( 特征 2 = b ) P(特征1=a,特征2=b)=P(特征1=a)*P(特征2=b) P(特征1=a,特征2=b)=P(特征1=a)P(特征2=b)

事实上,无论是计算 P ( 0 ∣ 特征 1 = a , 特征 2 = b ) P(0|特征1=a,特征2=b) P(0∣特征1=a,特征2=b)还是 P ( 1 ∣ 特征 1 = a , 特征 2 = b ) P(1|特征1=a,特征2=b) P(1∣特征1=a,特征2=b),分母都是 P ( 特征 1 = a , 特征 2 = b ) P(特征1=a,特征2=b) P(特征1=a,特征2=b)
如果只需要评估 P ( 0 ∣ 特征 1 = a , 特征 2 = b ) P(0|特征1=a,特征2=b) P(0∣特征1=a,特征2=b) P ( 1 ∣ 特征 1 = a , 特征 2 = b ) P(1|特征1=a,特征2=b) P(1∣特征1=a,特征2=b)的大小关系,并不需要计算 P ( 特征 1 = a , 特征 2 = b ) P(特征1=a,特征2=b) P(特征1=a,特征2=b)的值。

实例演示

本节我们参考网上使用很多的一个实例,来演示一下朴素贝叶斯分类算法的计算过程。

以下表格列举了一个女生在男生具有不同特征值的情况下,是否愿意嫁的多种情况。
此处特征包括颜值(1表示高、0表示低)、性格(1表示好、0表示坏)、身高(2/1/0分别表示高/中/低)和上进心(1表示有、0表示无);特征是嫁(1表示是、0表示否)。

现在假设有一个男生的特征值为:颜值=0,性格=0,身高=0,上进心=0,那么该女生是嫁或者不嫁呢?

暂且抛开算法不谈,先从我们朴素的认知来预测。
从上表的数值可以简单判断出,女生在嫁的情况下,男生总会有些特征是优秀的,也就是说,起码是个“正常人”的逻辑思维。
所以当面对一个4个特征都是差的情况下,自然会选择不嫁。
也就是说,如果从概率的角度来看,不嫁的概率要远高于嫁的概率。

接下来我们看一下,如果是从算法角度,会得出什么样的结论以及如何得到这个结论。
首先是计算嫁的概率:

P ( 嫁 = 1 ∣ 颜值 = 0 , 性格 = 0 , 身高 = 0 , 上进心 = 0 ) = P ( 颜值 = 0 ∣ 嫁 = 1 ) ∗ P ( 性格 = 0 ∣ 嫁 = 1 ) ∗ P ( 身高 = 0 ∣ 嫁 = 1 ) ∗ P ( 上进心 = 0 ∣ 嫁 = 1 ) ∗ P ( 嫁 = 1 ) P ( 颜值 = 0 ) ∗ P ( 性格 = 0 ) ∗ P ( 身高 = 0 ) ∗ P ( 上进心 = 0 ) P(嫁=1|颜值=0,性格=0,身高=0,上进心=0)=\frac{P(颜值=0|嫁=1)*P(性格=0|嫁=1)*P(身高=0|嫁=1)*P(上进心=0|嫁=1)*P(嫁=1)}{P(颜值=0)*P(性格=0)*P(身高=0)*P(上进心=0)} P(=1∣颜值=0,性格=0,身高=0,上进心=0)=P(颜值=0)P(性格=0)P(身高=0)P(上进心=0)P(颜值=0∣=1)P(性格=0∣=1)P(身高=0∣=1)P(上进心=0∣=1)P(=1)

上式中, P ( 嫁 = 1 ) 、 P ( 颜值 = 0 ) 、 P ( 性格 = 0 ) 、 P ( 身高 = 0 ) P(嫁=1)、P(颜值=0)、P(性格=0)、P(身高=0) P(=1)P(颜值=0)P(性格=0)P(身高=0) P ( 上进心 = 0 ) P(上进心=0) P(上进心=0)的计算逻辑相同,我们以 P ( 嫁 = 1 ) P(嫁=1) P(=1)为例,简述一下这几个值的计算过程。

表中一共有10个样本,其中嫁=1的样本数量为6,所以
P ( 嫁 = 1 ) = 6 / 10 = 3 / 5 P(嫁=1)=6/10=3/5 P(=1)=6/10=3/5
参考该逻辑,可以得到
P ( 颜值 = 0 ) = 2 / 5 , P ( 性格 = 0 ) = 3 / 10 , P ( 身高 = 0 ) = 1 / 2 , P ( 上进心 = 0 ) = 3 / 10 P(颜值=0)=2/5, P(性格=0)=3/10,P(身高=0)=1/2,P(上进心=0)=3/10 P(颜值=0)=2/5,P(性格=0)=3/10,P(身高=0)=1/2,P(上进心=0)=3/10

P ( 颜值 = 0 ∣ 嫁 = 1 ) 、 P ( 性格 = 0 ∣ 嫁 = 1 ) 、 P ( 身高 = 0 ∣ 嫁 = 1 ) P(颜值=0|嫁=1)、P(性格=0|嫁=1)、P(身高=0|嫁=1) P(颜值=0∣=1)P(性格=0∣=1)P(身高=0∣=1) 和 P ( 上进心 = 0 ∣ 嫁 = 1 ) 和P(上进心=0|嫁=1) P(上进心=0∣=1)的计算逻辑相同
,我们以 P ( 颜值 = 0 ∣ 嫁 = 1 ) P(颜值=0|嫁=1) P(颜值=0∣=1)为例,描述一下这几个值的计算过程。

先按照“嫁=1”的条件,将原表筛选为如下的新表


新表中一共有6个样本,其中颜值=0的样本数量为3,所以
P ( 颜值 = 0 ∣ 嫁 = 1 ) = 3 / 6 = 1 / 2 P(颜值=0|嫁=1)=3/6=1/2 P(颜值=0∣=1)=3/6=1/2
参考该逻辑,可以得到
P ( 性格 = 0 ∣ 嫁 = 1 ) = 1 / 2 , P ( 身高 = 0 ∣ 嫁 = 1 ) = 1 / 6 , P ( 上进心 = 0 ∣ 嫁 = 1 ) = 1 / 6 P(性格=0|嫁=1)=1/2,P(身高=0|嫁=1)=1/6,P(上进心=0|嫁=1)=1/6 P(性格=0∣=1)=1/2,P(身高=0∣=1)=1/6,P(上进心=0∣=1)=1/6
有了以上数据值,我们便可以得到女生嫁的概率为
P ( 嫁 = 1 ∣ 颜值 = 0 , 性格 = 0 , 身高 = 0 , 上进心 = 0 ) = 1 2 ∗ 1 6 ∗ 1 6 ∗ 1 6 ∗ 3 5 2 5 ∗ 3 10 ∗ 1 2 ∗ 3 10 P(嫁=1|颜值=0,性格=0,身高=0,上进心=0)=\frac{\frac{1}{2}*\frac{1}{6}*\frac{1}{6}*\frac{1}{6}*\frac{3}{5}}{\frac{2}{5}*\frac{3}{10}*\frac{1}{2}*\frac{3}{10}} P(=1∣颜值=0,性格=0,身高=0,上进心=0)=52103211032161616153

类似的,我们可以算出女生不嫁的概率为
P ( 嫁 = 0 ∣ 颜值 = 0 , 性格 = 0 , 身高 = 0 , 上进心 = 0 ) = 1 4 ∗ 1 2 ∗ 1 ∗ 1 2 ∗ 2 5 2 5 ∗ 3 10 ∗ 1 2 ∗ 3 10 P(嫁=0|颜值=0,性格=0,身高=0,上进心=0)=\frac{\frac{1}{4}*\frac{1}{2}*1*\frac{1}{2}*\frac{2}{5}}{\frac{2}{5}*\frac{3}{10}*\frac{1}{2}*\frac{3}{10}} P(=0∣颜值=0,性格=0,身高=0,上进心=0)=5210321103412112152
由于嫁的概率小于不嫁的概率后,可以判定该女生会选择不嫁。
我们进一步计算一下两者的比值,可以发现不嫁的概率是嫁的概率的18倍,这和之前的预期是一样的。

代码实现

在朴素贝叶斯分类算法中,并没有使用任何优化算法,所以从个人角度来说,没有必要做代码实现。

不过强迫症的自己,非要有标准化的“代码实现”模块,所以就有了这一节。

猜你喜欢

转载自blog.csdn.net/taozibaby/article/details/128702631