朴素贝叶斯(Naive Bayes)算法是基于贝叶斯定理和特征条件独立性假设(在给定样本类别的前提下,任意特征的取值与其他特征都不相关)的分类方法。适用于文本分类、情感分析、垃圾邮件分类等文本分析问题,此外朴素贝叶斯还应用于医学诊断和推荐系统。
原理
贝叶斯定理
假设
X
,
Y
X,Y
X,Y 是一对随机变量,它们的联合概率
p
(
X
=
x
,
Y
=
y
)
p(X=x,Y=y)
p(X=x,Y=y) 是指
X
X
X 取值
x
x
x 且
Y
Y
Y 取值
y
y
y 的概率。条件概率
p
=
(
X
=
x
∣
Y
=
y
)
p=(X=x|Y=y)
p=(X=x∣Y=y) 是指
Y
Y
Y 在取值
y
y
y 的情况下,变量
X
X
X 取值
x
x
x 的概率。且
X
X
X 和
Y
Y
Y 的联合概率和条件概率满足
p
(
X
,
Y
)
=
p
(
X
∣
Y
)
p
(
Y
)
=
p
(
Y
∣
X
)
p
(
X
)
p(X, Y)=p(X|Y)p(Y)=p(Y|X)p(X)
p(X,Y)=p(X∣Y)p(Y)=p(Y∣X)p(X)
可得贝叶斯定理
p
(
Y
∣
X
)
=
p
(
X
∣
Y
)
p
(
Y
)
p
(
X
)
p(Y|X)=\frac{p(X|Y)p(Y)}{p(X)}
p(Y∣X)=p(X)p(X∣Y)p(Y)
假设
X
X
X 代表样本,
Y
Y
Y 代表样本的类别标签,贝叶斯定理是一种把先验知识和从样本获取的证据相结合的统计原理。其中
p
(
Y
)
p(Y)
p(Y) 称为先验分布,
p
(
X
∣
Y
)
p(X|Y)
p(X∣Y) 称为似然函数,
p
(
X
)
p(X)
p(X) 称为证据,
p
(
Y
∣
X
)
p(Y|X)
p(Y∣X) 称为后验分布。
朴素贝叶斯模型
给定带类标签的数据集
D
D
D 中的样本分布于
m
m
m 个类别
C
1
,
C
2
,
…
,
C
m
C_1,C_2,…,C_m
C1,C2,…,Cm,每一个样本以
d
d
d 维属性向量形式表示,
X
=
(
x
1
,
x
2
,
…
,
x
d
)
X=(x_1,x_2,…,x_d)
X=(x1,x2,…,xd)
贝叶斯分类器的目标:
计算后验概率
P
(
C
i
∣
X
)
P(C_i|X)
P(Ci∣X),确定最大的一个
P
(
C
k
∣
X
)
P(C_k|X)
P(Ck∣X),
C
k
C_k
Ck 即为样本
X
X
X 的类别
P
(
C
i
∣
X
)
=
P
(
X
∣
C
i
)
P
(
C
i
)
P
(
X
)
P(C_i|X)=\frac{P(X|C_i)P(C_i)}{P(X)}
P(Ci∣X)=P(X)P(X∣Ci)P(Ci)
其中
P
(
X
)
P(X)
P(X) 可用全概率公式计算,即
P
(
X
)
=
∑
i
=
1
m
P
(
X
∣
C
i
)
P
(
C
i
)
P(X)=\displaystyle \sum^{m}_{i=1}{P(X|C_i)P(C_i)}
P(X)=i=1∑mP(X∣Ci)P(Ci)。
由于
P
(
X
)
P(X)
P(X) 对所有的类都相同,看作常量,只需要比较分子
P
(
X
∣
C
i
)
P
(
C
i
)
P(X|C_i)P(C_i)
P(X∣Ci)P(Ci) 即可。
P
(
C
i
)
P(C_i)
P(Ci):可近似为
∣
C
i
,
D
∣
/
∣
D
∣
|C_{i,D}|/|D|
∣Ci,D∣/∣D∣,
C
i
,
D
C_{i,D}
Ci,D 为
D
D
D 中类别为
C
i
C_i
Ci 的样本的数量。
P
(
X
∣
C
i
)
P(X|C_i)
P(X∣Ci):朴素的假设——假定各个属性之间相互独立,因此
P
(
X
∣
C
i
)
=
∏
P
(
x
k
∣
C
i
)
P(X|C_i)=\prod{P(x_k|C_i)}
P(X∣Ci)=∏P(xk∣Ci)
分类属性
f
f
f:
P
(
x
k
∣
C
i
)
P(x_k|C_i)
P(xk∣Ci)可近似为
c
o
u
n
t
(
f
=
x
k
)
/
∣
C
i
,
D
∣
count(f=x_k)/|C_{i,D}|
count(f=xk)/∣Ci,D∣,其中
c
o
u
n
t
(
f
=
x
k
)
count(f=x_k)
count(f=xk) 为属性
f
f
f 取值为
s
k
s_k
sk 的样本的数量。
连续值属性
f
f
f:假定其值服从均值为
μ
\mu
μ 标准差为
σ
\sigma
σ 的高斯分布,即
g
(
x
,
μ
,
σ
)
=
1
2
π
σ
e
−
x
−
μ
2
σ
2
g(x,\mu,\sigma)=\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{x-\mu}{2\sigma^2}}
g(x,μ,σ)=2πσ1e−2σ2x−μ
则
P
(
x
k
∣
C
i
)
=
g
(
x
k
,
μ
C
i
,
σ
C
i
)
P(x_k|C_i)=g(x_k,\mu_{C_i},\sigma_{C_i})
P(xk∣Ci)=g(xk,μCi,σCi)
其中
μ
c
i
\mu c_i
μci 和
σ
c
i
\sigma c_i
σci 分别为类别
C
i
C_i
Ci 中样本属性
f
f
f 的均值和标准差。
对上式的解释:
g
(
x
,
μ
,
σ
)
g(x,\mu,\sigma)
g(x,μ,σ) 是高斯分布的概率密度函数。对于连续值属性
f
f
f,
P
(
f
=
x
k
)
P(f=x_k)
P(f=xk) 的值接近于0。如:
P
(
H
e
i
g
h
t
=
70
)
=
?
P(Height=70)=?
P(Height=70)=?,可计算
P
(
69
≤
H
e
i
g
h
t
≤
70
)
P(69\leq Height\leq 70)
P(69≤Height≤70) 或
P
(
70
≤
H
e
i
g
h
t
≤
71
)
P(70\leq Height\leq 71)
P(70≤Height≤71)
一般计算的是
f
f
f 的取值落入
x
k
x_k
xk 附近很小的邻域内的概率,即
P
(
x
k
−
ϵ
/
2
≤
f
≤
x
k
+
ϵ
/
2
)
≈
ϵ
×
g
(
x
k
,
μ
,
σ
)
P(x_k-\epsilon/2\leq f\leq x_k+\epsilon/2)\approx\epsilon\times g(x_k,\mu,\sigma)
P(xk−ϵ/2≤f≤xk+ϵ/2)≈ϵ×g(xk,μ,σ)
带入公式
P
(
X
∣
C
i
)
=
∏
k
=
1
n
P
(
x
k
∣
C
i
)
P(X|C_i)=\prod^{n}_{k=1}P(x_k|C_i)
P(X∣Ci)=k=1∏nP(xk∣Ci)
P
(
C
i
∣
X
)
=
P
(
X
∣
C
i
)
P
(
C
i
)
P
(
X
)
P(C_i|X)=\frac{P(X|C_i)P(C_i)}{P(X)}
P(Ci∣X)=P(X)P(X∣Ci)P(Ci)
P
(
X
)
=
∑
i
=
1
m
P
(
X
∣
C
i
)
P
(
C
i
)
P(X)=\displaystyle \sum^{m}_{i=1}{P(X|C_i)P(C_i)}
P(X)=i=1∑mP(X∣Ci)P(Ci)
可约去邻域大小
ϵ
\epsilon
ϵ。因此,只需计算概率密度函数的值。
若该属性的取值不服从高斯分布,可用核密度估计(KDE,Kernel density Estimation)方法计算其概率。
如高斯核的情况
P
(
x
k
∣
C
i
)
=
1
∣
D
c
h
∣
∑
x
j
∈
K
(
x
k
,
x
j
[
f
]
)
P(x_k|C_i)=\frac{1}{|D_ch|}\displaystyle \sum_{x_j\in }K(x_k,x_j[f])
P(xk∣Ci)=∣Dch∣1xj∈∑K(xk,xj[f])
K
(
a
,
b
)
=
1
2
π
e
(
a
−
b
)
2
2
h
2
K(a,b)=\frac{1}{\sqrt{2\pi}}e^{\frac{(a-b)^2}{2h^2}}
K(a,b)=2π1e2h2(a−b)2
其中
h
h
h 为带宽
0概率问题:拉普拉斯校正(Laplacian Smoothing)
若训练集中类别
C
i
C_i
Ci 不包含
f
=
x
k
f=x_k
f=xk 的样本,用公式
P
(
x
k
)
=
∣
C
i
,
D
∣
/
∣
D
∣
P(x_k)=|C_{i,D}|/|D|
P(xk)=∣Ci,D∣/∣D∣ 估计概率,会得到
P
(
x
k
∣
C
i
)
=
0
P(x_k|C_i)=0
P(xk∣Ci)=0。
则样本
X
X
X 中只要包含
f
=
x
k
f=x_k
f=xk 的属性,无论其他属性如何取值,
P
(
X
∣
C
i
)
p
(
C
i
)
P(X|C_i)p(C_i)
P(X∣Ci)p(Ci) 均为0。
拉普拉斯校正方法:
P
(
x
k
∣
C
i
)
=
c
o
u
n
t
(
A
k
=
x
k
)
+
1
∣
C
i
,
D
∣
+
c
o
u
n
t
(
A
k
)
P(x_k|C_i)=\frac{count(A_k=x_k)+1}{|C_{i,D}|+count(A_k)}
P(xk∣Ci)=∣Ci,D∣+count(Ak)count(Ak=xk)+1
其中
c
o
u
n
t
(
f
)
count(f)
count(f) 为属性
f
f
f 的不同取值的数目。
例如训练集中类别
C
i
C_i
Ci 包含1000个样本,其中
i
n
c
o
m
e
=
′
l
o
w
′
(
0
)
income='low'(0)
income=′low′(0)
i
n
c
o
m
e
=
′
m
e
d
i
u
m
′
(
990
)
income='medium'(990)
income=′medium′(990)
i
n
c
o
m
e
=
′
h
i
g
h
′
(
10
)
income='high'(10)
income=′high′(10)
则
P
(
i
n
c
o
m
e
=
′
l
o
w
′
∣
C
i
)
=
1
/
1003
P(income='low'|C_i)=1/1003
P(income=′low′∣Ci)=1/1003
P
(
i
n
c
o
m
e
=
′
m
e
d
i
u
m
′
∣
C
i
)
=
991
/
1003
P(income='medium'|C_i)=991/1003
P(income=′medium′∣Ci)=991/1003
P
(
i
n
c
o
m
e
=
′
h
i
g
h
′
∣
C
i
)
=
11
/
1003
P(income='high'|C_i)=11/1003
P(income=′high′∣Ci)=11/1003
举例
数据:
x 1 x_1 x1 | x 2 x_2 x2 | Y Y Y | |
---|---|---|---|
1 | 1 | S | -1 |
2 | 1 | M | -1 |
3 | 1 | M | 1 |
4 | 1 | S | 1 |
5 | 1 | S | -1 |
6 | 2 | S | -1 |
7 | 2 | M | -1 |
8 | 2 | M | 1 |
9 | 2 | L | 1 |
10 | 2 | L | 1 |
11 | 3 | L | 1 |
12 | 3 | M | 1 |
13 | 3 | M | 1 |
14 | 3 | L | 1 |
15 | 3 | L | -1 |
- 训练结果:
C 1 : Y = 1 C 2 : Y = − 1 C_1:Y=1 \qquad C_2:Y=-1 C1:Y=1C2:Y=−1
P ( C 1 ) = 9 / 15 P ( C 2 ) = 6 / 15 P(C_1)=9/15 \qquad P(C_2)=6/15 P(C1)=9/15P(C2)=6/15
P ( x 1 = 1 ∣ C 1 ) = 2 / 9 P ( x 1 = 2 ∣ C 1 ) = 3 / 9 P ( x 1 = 3 ∣ C 1 ) = 4 / 9 P(x_1=1|C_1)=2/9\qquad P(x_1=2|C_1)=3/9\qquad P(x_1=3|C_1)=4/9 P(x1=1∣C1)=2/9P(x1=2∣C1)=3/9P(x1=3∣C1)=4/9
P ( x 2 = S ∣ C 1 ) = 1 / 9 P ( x 2 = M ∣ C 1 ) = 4 / 9 P ( x 2 = L ∣ C 1 ) = 4 / 9 P(x_2=S|C_1)=1/9\qquad P(x_2=M|C_1)=4/9\qquad P(x_2=L|C_1)=4/9 P(x2=S∣C1)=1/9P(x2=M∣C1)=4/9P(x2=L∣C1)=4/9
P ( x 1 = 1 ∣ C 2 ) = 3 / 6 P ( x 1 = 2 ∣ C 2 ) = 2 / 6 P ( x 1 = 3 ∣ C 2 ) = 1 / 6 P(x_1=1|C_2)=3/6\qquad P(x_1=2|C_2)=2/6\qquad P(x_1=3|C_2)=1/6 P(x1=1∣C2)=3/6P(x1=2∣C2)=2/6P(x1=3∣C2)=1/6
P ( x 2 = S ∣ C 2 ) = 3 / 6 P ( x 2 = M ∣ C 2 ) = 2 / 6 P ( x 2 = L ∣ C 2 ) = 1 / 6 P(x_2=S|C_2)=3/6\qquad P(x_2=M|C_2)=2/6\qquad P(x_2=L|C_2)=1/6 P(x2=S∣C2)=3/6P(x2=M∣C2)=2/6P(x2=L∣C2)=1/6 - 验证
对于 t = ( 2 , S ) t=(2,S) t=(2,S):
P ( C 1 ∣ t ) = P ( C 1 ) P ( x 1 = 2 ∣ C 1 ) P ( x 2 = S ∣ C 1 ) = 9 / 15 ∗ 3 / 9 ∗ 1 / 9 = 1 / 45 P(C_1|t)=P(C_1)P(x_1=2|C_1)P(x_2=S|C_1)=9/15*3/9*1/9=1/45 P(C1∣t)=P(C1)P(x1=2∣C1)P(x2=S∣C1)=9/15∗3/9∗1/9=1/45
P ( C 2 ∣ t ) = P ( C 2 ) P ( x 1 = 2 ∣ C 2 ) P ( x 2 = S ∣ C 2 ) = 6 / 15 ∗ 2 / 6 ∗ 3 / 6 = 1 / 15 P(C_2|t)=P(C_2)P(x_1=2|C_2)P(x_2=S|C_2)=6/15*2/6*3/6=1/15 P(C2∣t)=P(C2)P(x1=2∣C2)P(x2=S∣C2)=6/15∗2/6∗3/6=1/15
所以 t = ( 2 , S ) t=(2,S) t=(2,S) 的标签 Y Y Y 的预测值为 − 1 -1 −1。
代码实现
朴素贝叶斯模型
class bayes:
def __init__(self, lam=None):
self.y_p = {} # 存储不同标签的概率
self.y_x_cnt = [] # 存储相同标签下不同属性值的数量
self.lam = lam # 是否使用拉普拉斯校正,为数值型数据
self.y_x_p = [] # 存储相同标签下不同属性值的概率
self.y_pre = [] # 存储预测结果
def get_y_p(self, data):
if self.lam == None:
y_labels = np.unique(data[:, -1])
for y_label in y_labels:
self.y_p[y_label] = len(data[data[:, -1] == y_label]) / len(data)
else:
y_labels = np.unique(data[:, -1])
for y_label in y_labels:
self.y_p[y_label] = (len(data[data[:, -1] == y_label]) + self.lam) / (len(data) + self.lam*len(y_labels))
def get_y_x_cnt(self, data):
for y_label in self.y_p.keys():
y_label_cnt = len(data[data[:, -1] == y_label])
for x_k in range(0, data.shape[1]-1):
x_k_count = Counter(data[data[:, -1] == y_label][:,x_k])
self.y_x_cnt.append([y_label,y_label_cnt,x_k,dict(x_k_count)])
def get_y_x_p(self):
if self.lam == None:
for i in range(0, len(self.y_x_cnt)):
p = {}
for key in self.y_x_cnt[i][3].keys():
p[key] = self.y_x_cnt[i][3][key] / self.y_x_cnt[i][1]
self.y_x_p.append([self.y_x_cnt[i][0], self.y_x_cnt[i][1], self.y_x_cnt[i][2], p])
else:
for i in range(0, len(self.y_x_cnt)):
p = {}
length = len(self.y_x_cnt[i][3].keys())
for key in self.y_x_cnt[i][3].keys():
p[key] = (self.y_x_cnt[i][3][key]+self.lam) / (self.y_x_cnt[i][1]+length*self.lam)
self.y_x_p.append([self.y_x_cnt[i][0], self.y_x_cnt[i][1], self.y_x_cnt[i][2], p])
def fit(self, data):
data = np.array(data)
self.get_y_p(data)
self.get_y_x_cnt(data)
self.get_y_x_p()
def predict(self, y_test):
y_test = np.array(y_test)
y_x_p_arr = np.array(self.y_x_p)
for j in range(0, len(y_test)):
y = y_test[j]
result = {}
for key in self.y_p.keys():
result[key] = 1*self.y_p[key]
for i in range(0,len(y)):
result[key]=result[key]*y_x_p_arr[(y_x_p_arr[:,0]==key)&(y_x_p_arr[:,2]==i)][:,3][0][str(y[i])]
self.y_pre.append(max(result, key=result.get))
return self.y_pre
模型运用
数据集(使用原理介绍时的例子)
x = np.array([[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3],['S','M','M','S','S','S','M','M','L','L','L','M','M','L','L']])
y = np.array([-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1])
df = pd.DataFrame()
df["x1"] = x[0]
df["x2"] = x[1]
df["label"] = y
朴素贝叶斯
model1 = bayes()
model1.fit(df)
y_test = [[2, 'S'],[2, 'L']]
model1.predict(y_test)
使用拉普拉斯校正
model = bayes(lam = 1)
model.fit(df)
y_test = [[2, 'S'],[2, 'L']]
model.predict(y_test)
总结
优点
- 思想简单,易于实现
- 分类准确率高——即使在属性之间存在相关性的情况下
- 数学基础严密,结果可解释性强
- 可以增量式进行训练
缺点
- 朴素的假设不成立:实际数据的属性之间往往存在相关性