统计学习方法之朴素贝叶斯法
1. 朴素贝叶斯法的学习与分类
1.1 基本方法
输入空间 :
X
⊆
R
n
\mathcal{X} \subseteq \mathbf{R}^{n}
X⊆Rn
输出空间 :
y
∈
Y
=
{
c
1
,
c
2
,
⋅
⋅
⋅
,
c
K
}
y \in \mathcal{Y}=\{c_1,c_2,\cdot \cdot \cdot, c_K\}
y∈Y={c1,c2,⋅⋅⋅,cK}
训练数据集 :
T
=
{
(
x
1
,
y
1
)
,
⋅
⋅
⋅
,
(
x
N
,
y
N
)
}
T=\{(x_1,y_1),\cdot \cdot \cdot, (x_N,y_N)\}
T={(x1,y1),⋅⋅⋅,(xN,yN)}
补充贝叶斯公式 : P ( A ∣ B ) = P ( B ∣ A ) P ( A ) P ( B ) P(A|B) = \frac{P(B|A)P(A)}{P(B)} P(A∣B)=P(B)P(B∣A)P(A)
-
对给定的输入 x x x,通过计算后验概率分布 P ( Y = c k ∣ X = x ) P(Y=c_k|X=x) P(Y=ck∣X=x),将后验概率最大的类作为 x x x的输出
P ( Y = c k ∣ X = x ) = P ( X = x ∣ Y = c k ) P ( Y = c k ) ∑ k P ( X = x ∣ Y = c k ) P ( Y = c k ) P\left(Y=c_{k} \mid X=x\right)=\frac{P\left(X=x \mid Y=c_{k}\right) P\left(Y=c_{k}\right)}{\sum_{k} P\left(X=x \mid Y=c_{k}\right) P\left(Y=c_{k}\right)} P(Y=ck∣X=x)=∑kP(X=x∣Y=ck)P(Y=ck)P(X=x∣Y=ck)P(Y=ck) -
假设用于分类的特征在类确定的条件下都是条件独立的,则上式可变为:
P ( Y = c k ∣ X = x ) = P ( Y = c k ) ∏ j P ( X ( j ) = x ( j ) ∣ Y = c k ) ∑ k P ( Y = c k ) ∏ j P ( X ( j ) = x ( j ) ∣ Y = c k ) , k = 1 , 2 , ⋯ , K P\left(Y=c_{k} \mid X=x\right)=\frac{P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} \mid Y=c_{k}\right)}{\sum_{k} P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} \mid Y=c_{k}\right)}, \quad k=1,2, \cdots, K P(Y=ck∣X=x)=∑kP(Y=ck)∏jP(X(j)=x(j)∣Y=ck)P(Y=ck)∏jP(X(j)=x(j)∣Y=ck),k=1,2,⋯,K -
所以朴素贝叶斯分类器可表示为:
y = f ( x ) = arg max c k P ( Y = c k ) ∏ j P ( X ( j ) = x ( j ) ∣ Y = c k ) ∑ k P ( Y = c k ) ∏ j P ( X ( j ) = x ( j ) ∣ Y = c k ) \begin{array}{l} \qquad y=f(x)=\argmax _{c_{k}} \frac{ P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} \mid Y=c_{k}\right)}{\sum_{k} P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} \mid Y=c_{k}\right)} \end{array} y=f(x)=ckargmax∑kP(Y=ck)∏jP(X(j)=x(j)∣Y=ck)P(Y=ck)∏jP(X(j)=x(j)∣Y=ck) -
由于上式中分母对所有的 c k c_k ck是相同的,所以上式可转化为:
y = arg max c k P ( Y = c k ) ∏ j P ( X ( j ) = x ( j ) ∣ Y = c k ) y=\argmax_{c_k} P(Y=c_k) \prod_j P(X^{(j)}=x^{(j)}|Y=c_k) y=ckargmaxP(Y=ck)j∏P(X(j)=x(j)∣Y=ck)
1.2 后验概率最大化的含义
假设选择0-1损失函数
L
(
Y
,
f
(
X
)
)
=
{
1
,
Y
≠
f
(
X
)
0
,
Y
=
f
(
X
)
L(Y, f(X))=\left\{\begin{array}{ll} 1, & Y \neq f(X) \\ 0, & Y=f(X) \end{array}\right.
L(Y,f(X))={1,0,Y=f(X)Y=f(X)
则期望风险函数为
R
e
x
p
(
f
)
=
E
[
L
(
Y
,
f
(
X
)
)
]
R_{exp}(f) = E[L(Y,f(X))]
Rexp(f)=E[L(Y,f(X))]
由上式取条件期望:
R
exp
(
f
)
=
E
X
∑
k
=
1
K
[
L
(
c
k
,
f
(
X
)
)
]
P
(
c
k
∣
X
)
R_{\exp }(f)=E_{X} \sum_{k=1}^{K}\left[L\left(c_{k}, f(X)\right)\right] P\left(c_{k} \mid X\right)
Rexp(f)=EXk=1∑K[L(ck,f(X))]P(ck∣X)
为了使期望风险最小化,只需对
X
=
x
X=x
X=x逐个极小化,
f
(
x
)
=
arg
min
y
∈
Y
∑
k
=
1
K
L
(
c
k
,
y
)
P
(
c
k
∣
X
=
x
)
=
arg
min
y
∈
Y
∑
k
=
1
K
P
(
y
≠
c
k
∣
X
=
x
)
=
arg
min
y
∈
Y
(
1
−
P
(
y
=
c
k
∣
X
=
x
)
)
=
arg
max
y
∈
Y
P
(
y
=
c
k
∣
X
=
x
)
\begin{aligned} f(x) &=\arg \min _{y \in \mathcal{Y}} \sum_{k=1}^{K} L\left(c_{k}, y\right) P\left(c_{k} \mid X=x\right) \\ &=\arg \min _{y \in \mathcal{Y}} \sum_{k=1}^{K} P\left(y \neq c_{k} \mid X=x\right) \\ &=\arg \min _{y \in \mathcal{Y}}\left(1-P\left(y=c_{k} \mid X=x\right)\right) \\ &=\arg \max _{y \in \mathcal{Y}} P\left(y=c_{k} \mid X=x\right) \end{aligned}
f(x)=argy∈Ymink=1∑KL(ck,y)P(ck∣X=x)=argy∈Ymink=1∑KP(y=ck∣X=x)=argy∈Ymin(1−P(y=ck∣X=x))=argy∈YmaxP(y=ck∣X=x)
所以风险最小化等价于后验概率最大化
2. 朴素贝叶斯法的参数估计
2.1 极大似然估计
先验概率
P
(
Y
=
c
k
)
P(Y=c_k)
P(Y=ck)的极大似然估计:
P
(
Y
=
c
k
)
=
∑
i
=
1
N
I
(
y
i
=
c
k
)
N
,
k
=
1
,
2
,
⋯
,
K
P(Y=c_k)=\frac {\sum_{i=1}^NI(y_i=c_k)} {N},k=1,2,\cdots,K
P(Y=ck)=N∑i=1NI(yi=ck),k=1,2,⋯,K
条件概率
P
(
X
(
j
)
=
a
j
l
∣
Y
=
c
k
)
P(X^{(j)}=a_{jl}|Y=c_k)
P(X(j)=ajl∣Y=ck)的极大似然估计:
P
(
X
(
j
)
=
a
j
l
∣
Y
=
c
k
)
=
∑
i
=
1
N
I
(
x
i
(
j
)
=
a
j
l
,
y
i
=
c
k
)
∑
i
=
1
N
I
(
y
i
=
c
k
)
,
j
=
1
,
2
,
⋯
,
n
;
l
=
1
,
2
,
⋯
,
S
j
;
k
=
1
,
2
,
⋯
,
K
P(X^{(j)}=a_{jl}|Y=c_k)=\frac {\sum_{i=1}^NI(x_i^{(j)}=a_{jl},y_i=c_k)} {\sum_{i=1}^NI(y_i=c_k)},j=1,2,\cdots,n;l=1,2,\cdots,S_j;k=1,2,\cdots, K
P(X(j)=ajl∣Y=ck)=∑i=1NI(yi=ck)∑i=1NI(xi(j)=ajl,yi=ck),j=1,2,⋯,n;l=1,2,⋯,Sj;k=1,2,⋯,K
其中
- x i ( j ) : 第 i 个 样 本 的 第 j 个 特 征 x_i^{(j)} : 第i个样本的第j个特征 xi(j):第i个样本的第j个特征
- a j l : 第 j 个 特 征 可 能 取 的 第 l 个 值 a_{jl} : 第j个特征可能取的第l个值 ajl:第j个特征可能取的第l个值
- I : 指 示 函 数 I : 指示函数 I:指示函数
2.2 学习与分类算法
I n p u t : Input: Input:
- 训 练 数 据 T = { ( x 1 , y 1 ) , ⋯ , ( x N , y N } 训练数据T=\{(x_1,y_1),\cdots,(x_N,y_N\} 训练数据T={(x1,y1),⋯,(xN,yN}
- x i = ( x ( 1 ) , ⋯ , x ( n ) ) T , x i ( j ) 是 第 i 个 样 本 的 第 j 个 特 征 , x i ( j ) ∈ { a j 1 , ⋯ , a j S j } , a j l 是 第 j 个 特 例 可 能 取 的 第 l 个 值 x_i=(x^{(1)},\cdots,x^{(n)})^T,x_i^{(j)}是第i个样本的第j个特征,x_i^{(j)} \in \{a_{j1},\cdots,a_{jS_j}\},a_{jl}是第j个特例可能取的第l个值 xi=(x(1),⋯,x(n))T,xi(j)是第i个样本的第j个特征,xi(j)∈{aj1,⋯,ajSj},ajl是第j个特例可能取的第l个值
- y i ∈ { c 1 , c 2 , ⋯ , c K } y_i \in \{c_1,c_2,\cdots,c_K\} yi∈{c1,c2,⋯,cK}
O u t p u t : Output: Output:
- 实 例 x 的 类 别 实例x的类别 实例x的类别
S t e p : Step: Step:
-
计
算
先
验
概
率
及
条
件
概
率
计算先验概率及条件概率
计算先验概率及条件概率
P ( Y = c k ) = ∑ i = 1 N I ( y i = c k ) N , k = 1 , 2 , ⋯ , K P(Y=c_k)=\frac {\sum_{i=1}^NI(y_i=c_k)} {N},k=1,2,\cdots,K P(Y=ck)=N∑i=1NI(yi=ck),k=1,2,⋯,K
P ( X ( j ) = a j l ∣ Y = c k ) = ∑ i = 1 N I ( x i ( j ) = a j l , y i = c k ) ∑ i = 1 N I ( y i = c k ) , j = 1 , 2 , ⋯ , n ; l = 1 , 2 , ⋯ , S j ; k = 1 , 2 , ⋯ , K P(X^{(j)}=a_{jl}|Y=c_k)=\frac {\sum_{i=1}^NI(x_i^{(j)}=a_{jl},y_i=c_k)} {\sum_{i=1}^NI(y_i=c_k)},j=1,2,\cdots,n;l=1,2,\cdots,S_j;k=1,2,\cdots, K P(X(j)=ajl∣Y=ck)=∑i=1NI(yi=ck)∑i=1NI(xi(j)=ajl,yi=ck),j=1,2,⋯,n;l=1,2,⋯,Sj;k=1,2,⋯,K -
对
于
给
定
的
实
例
x
=
(
x
(
1
)
,
⋯
,
x
(
n
)
)
T
,
计
算
对于给定的实例x=(x^{(1)},\cdots,x^{(n)})^T,计算
对于给定的实例x=(x(1),⋯,x(n))T,计算
P ( Y = c k ) ∏ j = 1 n P ( X ( j ) = x ( j ) ∣ Y = c k ) , k = 1 , 2 , ⋯ , K P(Y=c_k)\prod_{j=1}^nP(X^{(j)}=x^{(j)}|Y=c_k),k=1,2,\cdots,K P(Y=ck)j=1∏nP(X(j)=x(j)∣Y=ck),k=1,2,⋯,K -
确
定
实
例
x
的
类
别
确定实例x的类别
确定实例x的类别
y = arg max c k P ( Y = c k ) ∏ j = 1 n P ( X ( j ) = x ( j ) ∣ Y = c k ) y=\argmax_{c_k} P(Y=c_k)\prod_{j=1}^nP(X^{(j)}=x^{(j)}|Y=c_k) y=ckargmaxP(Y=ck)j=1∏nP(X(j)=x(j)∣Y=ck)
2.3 贝叶斯估计
用极大似然估计可能会出现所要估计的概率值为0的情况 这时会影响到后验概率的计算结果,使分类产生偏差。解决这一问题的方法是采用贝叶斯估计
在随机变量各个取值的频数上赋予一个正数 λ > 0 \lambda>0 λ>0。
- λ = 0 \lambda=0 λ=0,是极大似然估计
- λ = 1 \lambda = 1 λ=1,是拉普拉斯平滑
先验概率的贝叶斯估计为
P
λ
(
Y
=
c
k
)
=
∑
i
=
1
N
I
(
y
i
=
c
k
)
+
λ
N
+
K
λ
P_{\lambda}\left(Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)+\lambda}{N+K \lambda}
Pλ(Y=ck)=N+Kλ∑i=1NI(yi=ck)+λ
条件概率的贝叶斯估计为
P
λ
(
X
(
j
)
=
a
j
l
∣
Y
=
c
k
)
=
∑
i
=
1
N
I
(
x
i
(
j
)
=
a
j
l
,
y
i
=
c
k
)
+
λ
∑
i
=
1
N
I
(
y
i
=
c
k
)
+
S
j
λ
P_{\lambda}\left(X^{(j)}=a_{j l} \mid Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(x_{i}^{(j)}=a_{j l}, y_{i}=c_{k}\right)+\lambda}{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)+S_{j} \lambda}
Pλ(X(j)=ajl∣Y=ck)=∑i=1NI(yi=ck)+Sjλ∑i=1NI(xi(j)=ajl,yi=ck)+λ
3. 算法实现
# 导入所需的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 加载数据
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
df
sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | label | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | 0 |
1 | 4.9 | 3.0 | 1.4 | 0.2 | 0 |
2 | 4.7 | 3.2 | 1.3 | 0.2 | 0 |
3 | 4.6 | 3.1 | 1.5 | 0.2 | 0 |
4 | 5.0 | 3.6 | 1.4 | 0.2 | 0 |
... | ... | ... | ... | ... | ... |
145 | 6.7 | 3.0 | 5.2 | 2.3 | 2 |
146 | 6.3 | 2.5 | 5.0 | 1.9 | 2 |
147 | 6.5 | 3.0 | 5.2 | 2.0 | 2 |
148 | 6.2 | 3.4 | 5.4 | 2.3 | 2 |
149 | 5.9 | 3.0 | 5.1 | 1.8 | 2 |
150 rows × 5 columns
# 展示数据
x_idx = iris.feature_names[0]
y_idx = iris.feature_names[1]
plt.scatter(df[:50][x_idx], df[:50][y_idx], label='0')
plt.scatter(df[50:100][x_idx], df[50:100][y_idx], label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()
# 准备数据
data = np.array(df.iloc[:100, [0, 1, -1]])
X, y = data[:,:-1], data[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
test_point = [[6, 3]]
plt.scatter(df[:50][x_idx], df[:50][y_idx], label='0')
plt.scatter(df[50:100][x_idx], df[50:100][y_idx], label='1')
plt.plot(test_point[0][0], test_point[0][1], 'bo', label='test_point')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()
from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()
clf.fit(X_train, y_train)
clf.predict(test_point)
array([1.])