文章目录
一、朴素贝叶斯基础
(1)条件概率
条件概率就是指事件 AA 在另外一个事件 BB 已经发生条件下的概率。
其中:
- P ( A ) P(A) P(A) 表示 A A A 事件发生的概率。
- P ( B ) P(B) P(B) 表示 B B B 事件发生的概率。
- P ( A B ) P(AB) P(AB) 表示 A , B A, B A,B 事件同时发生的概率。
而最终计算得到的 P ( A ∣ B ) P(A \mid B) P(A∣B) 便是条件概率,表示在 B B B 事件发生的情况下 A A A 事件发生的概率。
(2)贝叶斯定理
已知:事件
B
B
B 发生的情况下事件
A
A
A 发生的概率
P
(
A
∣
B
)
P(A \mid B)
P(A∣B),如何求
P
(
B
∣
A
)
P(B \mid A)
P(B∣A) 呢?
(1)
P
(
B
∣
A
)
=
P
(
A
B
)
P
(
A
)
P(B \mid A)=\frac{P(AB)}{P(A)} \tag1
P(B∣A)=P(A)P(AB)(1)
由上面的条件概率已知:
(2)
P
(
A
B
)
=
P
(
A
∣
B
)
∗
P
(
B
)
P(AB)=P(A \mid B)*P(B) \tag2
P(AB)=P(A∣B)∗P(B)(2)
(2)式代入(1),可得:
(3)
P
(
B
∣
A
)
=
P
(
A
B
)
P
(
A
)
=
P
(
A
∣
B
)
∗
P
(
B
)
P
(
A
)
P(B \mid A)=\frac{P(AB)}{P(A)}=\frac{P(A \mid B)*P(B)}{P(A)} \tag{3}
P(B∣A)=P(A)P(AB)=P(A)P(A∣B)∗P(B)(3)
(3)先验概率
先验概率(Prior Probability)指的是根据以往经验和分析得到的概率。
例如以上公式中的 P ( A ) , P ( B ) P(A), P(B) P(A),P(B),又例如: X X X 表示投一枚质地均匀的硬币,正面朝上的概率,显然在我们根据以往的经验下,我们会认为 X X X 的概率 P ( X ) = 0.5 P(X) = 0.5 P(X)=0.5 。其中 P ( X ) = 0.5 P(X) = 0.5 P(X)=0.5 就是先验概率。
(4)后验概率
后验概率(Posterior Probability)是事件发生后求的反向条件概率;即基于先验概率通过贝叶斯公式求得的反向条件概率。
例如公式中的 P ( B ∣ A ) P(B|A) P(B∣A) 就是通过先验概率 P ( A ) P(A) P(A)和 P ( B ) P(B) P(B) 得到的后验概率,其通俗的讲就是「执果寻因」中的「因」。
(5)朴素贝叶斯
那什么是朴素贝叶斯呢?
朴素贝叶斯(Naive Bayes)就是将贝叶斯原理以及条件独立结合而成的算法
(4) P ( B ∣ A ) = P ( A ∣ B ) ∗ P ( B ) P ( A ) P(B \mid A)=\frac{P(A \mid B)*P(B)}{P(A)} \tag{4} P(B∣A)=P(A)P(A∣B)∗P(B)(4)
变换下:
(5) P ( 类 别 ∣ 特 征 ) = P ( 特 征 ∣ 类 别 ) ∗ P ( 类 别 ) P ( 特 征 ) P(类别 \mid 特征)=\frac{P(特征 \mid 类别) * P(类别)}{P(特征)} \tag{5} P(类别∣特征)=P(特征)P(特征∣类别)∗P(类别)(5)
利用先验概率,即特征和类别的概率;再利用不同类别中各个特征的概率分布,最后计算得到后验概率,即各个特征分布下的预测不同的类别。
朴素贝叶斯则人为的将各个特征割裂开,认定特征之间相互独立。
朴素贝叶斯中的「朴素」,即条件独立,
表示其假设预测的各个属性都是相互独立的,每个属性独立地对分类结果产生影响,条件独立在数学上的表示为: P ( A B ) = P ( A ) ∗ P ( B ) P(AB)=P(A)*P(B) P(AB)=P(A)∗P(B)。
二、朴素贝叶斯算法实现
第 1 步:设 X = { a 1 , a 2 , a 3 , … , a n } X = \left \{ a_{1},a_{2},a_{3},…,a_{n} \right \} X={a1,a2,a3,…,an} 为预测数据,其中 a i a_{i} ai 是预测数据的特征值。
第 2 步:设 Y = { y 1 , y 2 , y 3 , … , y m } Y = \left \{y_{1},y_{2},y_{3},…,y_{m} \right \} Y={y1,y2,y3,…,ym} 为类别集合。
第 3 步:计算 P ( y 1 ∣ x ) P(y_{1}\mid x) P(y1∣x), P ( y 2 ∣ x ) P(y_{2}\mid x) P(y2∣x), P ( y 3 ∣ x ) P(y_{3}\mid x) P(y3∣x), … … …, P ( y m ∣ x ) P(y_{m}\mid x) P(ym∣x)。
第 4 步:寻找 P ( y 1 ∣ x ) P(y_{1}\mid x) P(y1∣x), P ( y 2 ∣ x ) P(y_{2}\mid x) P(y2∣x), P ( y 3 ∣ x ) P(y_{3}\mid x) P(y3∣x), … … …, P ( y m ∣ x ) P(y_{m}\mid x) P(ym∣x) 中最大的概率 P ( y k ∣ x ) P(y_{k}\mid x) P(yk∣x) ,则 x x x 属于类别 y k y_{k} yk。
举个例子:
利用 python 完成一个朴素贝叶斯算法的分类。
首先生成一组示例数据:由
A
和B
两个类别组成,每个类别包含x
,y
两个特征值,其中x
特征包含r,g,b(红,绿,蓝)
三个类别,y
特征包含s,m,l(小,中,大)
三个类别,如同数据X=[g,l]
。
(1)生成数据
import pandas as pd
def create_data():
data = {"x": ['r', 'g', 'r', 'b', 'g', 'g', 'r', 'r', 'b', 'g', 'g', 'r', 'b', 'b', 'g'],
"y": ['m', 's', 'l', 's', 'm', 's', 'm', 's', 'm', 'l', 'l', 's', 'm', 'm', 'l'],
"labels": ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B']}
data = pd.DataFrame(data, columns=["labels", "x", "y"])
return data
"""加载并预览数据
"""
data = create_data()
data
(2)参数估计
在来看遍公式:
(5)
P
(
类
别
∣
特
征
)
=
P
(
特
征
∣
类
别
)
∗
P
(
类
别
)
P
(
特
征
)
P(类别 \mid 特征)=\frac{P(特征 \mid 类别) * P(类别)}{P(特征)} \tag{5}
P(类别∣特征)=P(特征)P(特征∣类别)∗P(类别)(5)
由此可见,P(特征)
相同下,只需比较 P(特征 | 类别) * P(类别)
那如何求得 P(特征 | 类别)
和 P(类别)
呢?
可以应用极大似然估计法以及贝叶斯估计法来估计相应的概率
1. 极大似然估计
前提:
假如有两个外形完全相同箱子,甲箱中有99
个白球,1
个黑球;乙箱中有99
个黑球,1
个白球。
问题:
当我们进行一次实验,并取出一个球,取出的结果是白球。那么,请问白球是从哪一个箱子里取出的?
极大似然估计提供了一种给定观察数据来评估模型参数的方法,即:「模型已定,参数未知」。通过若干次试验,观察其结果,利用试验结果得到某个参数值能够使样本出现的概率为最大,则称为极大似然估计。
在概率论中求解极大似然估计的方法比较复杂,基于实验,我们将讲解
P
(
B
)
P(B)
P(B) 和
P
(
B
/
A
)
P(B/A)
P(B/A) 是如何通过极大似然估计得到的。
P
(
种
类
)
P(种类)
P(种类) 用数学的方法表示 :
(6)
P
(
y
i
=
c
k
)
=
∑
N
i
=
1
I
(
y
i
=
c
k
)
N
,
k
=
1
,
2
,
3
,
…
,
m
P(y_{i}=c_{k})=\frac{\sum_{N}^{i=1}I(y_{i}=c_{k})}{N},k=1,2,3,…,m \tag{6}
P(yi=ck)=N∑Ni=1I(yi=ck),k=1,2,3,…,m(6)
可以通俗的理解为,在现有的训练集中,每一个类别所占总数的比例,例如:生成的数据中
P
(
Y
=
A
)
=
8
15
P(Y=A)=\frac{8}{15}
P(Y=A)=158,表示训练集中总共有 15 条数据,而类别为 A
的有 8 条数据。
"""P(种类) 先验概率计算
"""
def get_P_labels(labels):
labels = list(labels) # 转换为 list 类型
P_label = {} # 设置空字典用于存入 label 的概率
for label in labels:
P_label[label] = labels.count(
label) / float(len(labels)) # p = count(y) / count(Y)
return P_label
P_labels = get_P_labels(data["labels"])
P_labels
得到 : {‘A’: 0.5333333333333333, ‘B’: 0.4666666666666667}
实际需要求的先验估计是特征的每一个类别对应的每一个种类的概率,例如:生成数据 中
P
(
x
1
=
"
r
"
∣
Y
=
A
)
=
4
8
P(x_{1}="r" \mid Y=A)=\frac{4}{8}
P(x1="r"∣Y=A)=84, A
的数据有 8 条,而在种类为 A
的数据且特征 x
为 r
的有 4 条。
"""导入特征数据并预览
"""
import numpy as np
train_data = np.array(data.iloc[:, 1:])
train_data
"""类别 A,B 索引
"""
labels = data["labels"]
label_index = []
for y in P_labels.keys():
temp_index = []
# enumerate 函数返回 Series 类型数的索引和值,其中 i 为索引,label 为值
for i, label in enumerate(labels):
if (label == y):
temp_index.append(i)
else:
pass
label_index.append(temp_index)
label_index
"""特征 x 为 r 的索引
"""
x_index = [i for i, feature in enumerate(train_data[:, 0]) if feature == 'r'] # 效果等同于求类别索引中 for 循环
x_index
x_label = set(x_index) & set(label_index[0])
print('既符合 x = r 又是 A 类别的索引值:', x_label)
x_label_count = len(x_label)
print('先验概率 P(r|A):', x_label_count / float(len(label_index[0])))
整理成一个函数,
可以得到当特征 x
和 y
的值为 r
和 m
时,在不同类别下的先验概率。
"""P(特征∣种类) 先验概率计算
"""
def get_P_fea_lab(P_label, features, data):
P_fea_lab = {}
train_data = data.iloc[:, 1:]
train_data = np.array(train_data)
labels = data["labels"]
for each_label in P_label.keys():
label_index = [i for i, label in enumerate(
labels) if label == each_label] # labels 中出现 y 值的所有数值的下标索引
# features[0] 在 trainData[:,0] 中出现的值的所有下标索引
for j in range(len(features)):
feature_index = [i for i, feature in enumerate(
train_data[:, j]) if feature == features[j]]
# set(x_index)&set(y_index) 列出两个表相同的元素
fea_lab_count = len(set(feature_index) & set(label_index))
key = str(features[j]) + '|' + str(each_label)
P_fea_lab[key] = fea_lab_count / float(len(label_index))
return P_fea_lab
features = ['r', 'm']
get_P_fea_lab(P_labels, features, data)
2. 贝叶斯估计
在做极大似然估计时,若类别中缺少一些特征,则就会出现概率值为 0
的情况。
此时,就会影响后验概率的计算结果,使得分类产生偏差。而解决这一问题最好的方法就是采用贝叶斯估计。
在计算先验概率
P
(
种
类
)
P(种类)
P(种类) 中,贝叶斯估计的数学表达式为:
(8)
P
(
y
i
=
c
k
)
=
∑
N
i
=
1
I
(
y
i
=
c
k
)
+
λ
N
+
k
λ
P(y_{i}=c_{k})=\frac{\sum_{N}^{i=1}I(y_{i}=c_{k})+\lambda }{N+k\lambda} \tag{8}
P(yi=ck)=N+kλ∑Ni=1I(yi=ck)+λ(8)
其中
λ
≥
0
\lambda \geq 0
λ≥0 等价于在随机变量各个取值的频数上赋予一个正数,当
λ
=
0
\lambda=0
λ=0 时就是极大似然估计。在平时常取
λ
=
1
\lambda=1
λ=1,这时称为拉普拉斯平滑。例如:生成数据 中,
P
(
Y
=
A
)
=
8
+
1
15
+
2
∗
1
=
9
17
P(Y=A)=\frac{8+1}{15+2*1}=\frac{9}{17}
P(Y=A)=15+2∗18+1=179,取
λ
=
1
\lambda=1
λ=1 此时由于一共有 A
,B
两个类别,则 k
取 2。
同样计算
P
(
特
征
∣
种
类
)
P(特征 \mid 种类)
P(特征∣种类) 时,也是给计算时的分子分母加上拉普拉斯平滑。例如:生成数据 中,
P
(
x
1
=
"
r
"
∣
Y
=
A
)
=
4
+
1
8
+
3
∗
1
=
5
11
P(x_{1}="r" \mid Y=A)=\frac{4+1}{8+3*1}=\frac{5}{11}
P(x1="r"∣Y=A)=8+3∗14+1=115 同样取
λ
=
1
\lambda=1
λ=1 此时由于 x
中有 r
, g
, b
三个种类,所以这里 k 取值为 3。
三、朴素贝叶斯算法实现
- 注:分类器实现的公式,请参考《机器学习》- 周志华 P151 页*
"""朴素贝叶斯分类器
"""
def classify(data, features):
# 求 labels 中每个 label 的先验概率
labels = data['labels']
P_label = get_P_labels(labels)
P_fea_lab = get_P_fea_lab(P_label, features, data)
P = {}
P_show = {} # 后验概率
for each_label in P_label:
P[each_label] = P_label[each_label]
for each_feature in features:
key = str(each_label)+'|'+str(features)
P_show[key] = P[each_label] * \
P_fea_lab[str(each_feature) + '|' + str(each_label)]
P[each_label] = P[each_label] * \
P_fea_lab[str(each_feature) + '|' +
str(each_label)] # 由于分母相同,只需要比较分子
print(P_show)
features_label = max(P, key=P.get) # 概率最大值对应的类别
return features_label
classify(data, ['r', 'm'])
对于特征为 [r,m]
的数据通过朴素贝叶斯分类得到不同类别的概率值,经过比较后分为 A
类。
四、朴素贝叶斯的三种常见模型
在实际数据中,我们可以依照特征的数据类型不同,在计算先验概率方面对朴素贝叶斯模型进行划分,并分为:多项式模型,伯努利模型和高斯模型。
(1)多项式模型
当特征值为离散时,常常使用多项式模型。事实上,在以上实验的参数估计中,我们所应用的就是多项式模型。为避免概率值为 0 的情况出现,多项式模型采用的是贝叶斯估计。
(2)伯努利模型
与多项式模型一样,伯努利模型适用于离散特征的情况,所不同的是,伯努利模型中每个特征的取值只能是 1
和 0
(以文本分类为例,某个单词在文档中出现过,则其特征值为 1
,否则为 0
)。
在伯努利模型中,条件概率 P ( x i ∣ y k ) P(x_{i} \mid y_{k}) P(xi∣yk) 的计算方式为:
-
当特征值 x i = 1 x_{i}=1 xi=1 时, P ( x i ∣ y k ) = P ( x i = 1 ∣ y k ) P(x_{i} \mid y_{k})=P(x_{i}=1 \mid y_{k}) P(xi∣yk)=P(xi=1∣yk);
-
当特征值 x i = 0 x_{i}=0 xi=0 时, P ( x i ∣ y k ) = P ( x i = 0 ∣ y k ) P(x_{i} \mid y_{k})=P(x_{i}=0 \mid y_{k}) P(xi∣yk)=P(xi=0∣yk)。
(3)高斯模型
当特征是连续变量的时候,在不做平滑的情况下,运用多项式模型就会导致很多 P ( x i ∣ y k ) = 0 P(x_{i} \mid y_{k})=0 P(xi∣yk)=0,此时即使做平滑,所得到的条件概率也难以描述真实情况。所以处理连续的特征变量,采用高斯模型。高斯模型是假设连续变量的特征数据是服从高斯分布的,高斯分布函数表达式为:
P ( x i ∣ y k ) = 1 2 π σ y k , i e x p ( − ( x − μ y k , i ) 2 2 σ y k 2 , i ) P(x_{i}|y_{k})=\frac{1}{\sqrt{2\pi}\sigma_{y_{k},i}}exp(-\frac{(x-\mu_{y_{k},i}) ^{2}}{2\sigma ^{2}_{y_{k}},i}) P(xi∣yk)=2πσyk,i1exp(−2σyk2,i(x−μyk,i)2)
其中:
- μ y k , i \mu_{y_{k},i} μyk,i 表示类别为 y k y_{k} yk 的样本中,第 i i i 维特征的均值。
- σ y k 2 , i \sigma ^{2}_{y_{k}},i σyk2,i 表示类别为 y k y_{k} yk 的样本中,第 i i i 维特征的方差。
五、小结
- 为什么使用朴素贝叶斯进行分类?
在概率框架下实施决策,通过概率和误判来选择最优的类别标识。 - 一个有趣的视频
http://labfile.oss.aliyuncs.com/courses/1081/beyes_video.mp4