本文开始,我们来学习一种新的机器学习方法:贝叶斯算法。
这次从最基础的朴素贝叶斯分类算法出发,了解相关的算法原理。
考虑如下一种分类问题:样本中只包含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(B∣A)=P(AB)/P(A)
此处,
P
(
B
∣
A
)
P(B|A)
P(B∣A)指的是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(B∣A)=1/4
显然,该实例中的概率值是满足之前的条件概率公式的。
将条件概率中的A和B换一下,可以得到
P
(
A
∣
B
)
=
P
(
A
B
)
/
P
(
B
)
P(A|B)=P(AB)/P(B)
P(A∣B)=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(B∣A)∗P(A)=P(A∣B)∗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(B∣A)=P(A)P(A∣B)∗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(AB∣C)=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(AB∣C)=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(AB∣C)=P(A∣C)∗P(B∣AC)
因为A和B相互独立,所以在C发生的条件下,A发生与否并不影响B发生的概率,即
P
(
B
∣
A
C
)
=
P
(
B
∣
C
)
P(B|AC)=P(B|C)
P(B∣AC)=P(B∣C)
将上式带入上上式,得到
P
(
A
B
∣
C
)
=
P
(
A
∣
C
)
∗
P
(
B
∣
C
)
P(AB|C)=P(A|C)*P(B|C)
P(AB∣C)=P(A∣C)∗P(B∣C)
设定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)=52∗103∗21∗10321∗61∗61∗61∗53
类似的,我们可以算出女生不嫁的概率为
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)=52∗103∗21∗10341∗21∗1∗21∗52
由于嫁的概率小于不嫁的概率后,可以判定该女生会选择不嫁。
我们进一步计算一下两者的比值,可以发现不嫁的概率是嫁的概率的18倍,这和之前的预期是一样的。
代码实现
在朴素贝叶斯分类算法中,并没有使用任何优化算法,所以从个人角度来说,没有必要做代码实现。
不过强迫症的自己,非要有标准化的“代码实现”模块,所以就有了这一节。