前言

朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。对于给定的训练数据集,首先基于特征条件独立假设学习输入/输出的联合概率分布;然后基于此模型,对于给定的输入x,利用贝叶斯定理求出后验概率最大的输出y。朴素贝叶斯法实现简单,学习与预测的效率都很高,是一种常用的方法。

朴素贝叶斯法的学习与分类

基本方法

设输入空间$\mathcal{X}\subseteq R_n$为n维向量的集合,输出空间为类标记集合$\mathcal{Y}=\{c_1,c_2,…,c_k\}$.输入为特征向量$x\in \mathcal{X}$,输出为类标记$y\in \mathcal{Y}$.X是定义在输入空间$\mathcal{X}$上的随机向量,Y是定义在输出空间$\mathcal{Y}$上的随机变量。$P(X,Y)$是X和Y的联合概率分布。训练数据集$$T=\{(x_1,y_1),(x_2,y_2),…,(x_N,y_N)\}$$由$P(X,Y)$独立同分布产生。

朴素贝叶斯法通过训练数据集学习联合概率分布$P(X,Y)$。具体地,学习以下先验概率分布条件概率分布。先验概率分布$$P(Y=c_k),k=1,2,…,K$$条件概率分布(后验概率分布)$$P(X=x|Y=c_k)=P(X^{(1)}=x^{(1)},…,X^{(n)}=x^{(n)}|Y=c_k)$$于是学习到联合概率分布$P(X,Y)$.

条件概率分布$P(X=x|Y=c_k)$有指数级数量的参数,其估计实际是不可行的。事实上,假设$x^{(j)}$可取值有$S_j$个,$j=1,2,…,n$,Y可取值有K个,那么参数个数为$$K\prod_{j=1}^{n}S_j$$

朴素贝叶斯法对条件概率分布作了条件独立性的假设。由于这是一个较强的假设,朴素贝叶斯法也由此得名。朴素贝叶斯法实际上学习到生成数据的机制,所以属于生成模型。条件独立假设等于是说用于分类的特征在类确定的条件下都是条件独立的。这一假设使朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率。

朴素贝叶斯法分类的基本公式:$$P(Y=c_k|X=x)=\frac{P(Y=c_k)\prod_j P(X^{(j)}=x^{(j)}|Y=c_k)}{\sum_k P(Y=c_k) \prod_j (X^{(j)}=x^{(j)}|Y=c_k)}$$

朴素贝叶斯法分类器可表示为$$y=f(x)=arg \max_{c_k} P(Y=c_k) \prod_j P(X^{(j)}=x^{(j)}|Y=c_k)$$

朴素贝叶斯法的参数估计

极大似然估计

在朴素贝叶斯法中,学习意味着估计$P(Y=c_k)$和$P(X^{(j)}=x^{(j)}|Y=c_k)$.可以应用极大似然估计法估计相应的概率。先验概率$P(Y=c_k)$的极大似然估计是$$P(Y=c_k)=\frac {\sum_{i=1}^{N} I(y_i=c_k)} {N},k=1,2,…,K$$设第$j$个特征$x^{(j)}$可能取值的集合为$\{a_{j1},a_{j2},…,a_{jS_j}\}$,条件概率$P(X^{j}=a_{jl}||Y=c_k)$的极大似然估计是$$P(x^{(j)}=a_{jl}|Y=c_k)=\frac{\sum_{i=1}^{N} I(x_i^{(j)}=a_{jl},y_i=c_k)}{\sum_{i=1}^{N}I(y_i=c_k)}\\j=1,2,…,n;l=1,2,…,S_j;k=1,2,…,K$$式中,$x_i^{(j)}$是第$i$个样本的第$j$个特征;$a_{jl}$是第$j$个特征可能取的第$l$个值:$I$为指示函数。

学习与分类算法

(朴素贝叶斯算法)
输入:训练数据$T=\{(x_1,y_1),(x_2,y_2),…,(x_N,y_N)\}$,其中$x_i=(x_i^{(1)},x_i^{(2)},…,x_i^{(n)})$,$x_i^{(j)}$是第$i$个样本的第$j$个特征,$x_i^{(j)}\in \{a_{j1},a_{j2},…,a_{jS_j}\}$,$a_{jl}$是第$j$个特征可能取的第$l$个值,$j=1,2,…,n$,$l=1,2,…,S_j$,$y_i\in \{c1,c2,…,c_k\}$;实例$x$;
输出:实例$x$的分类

  1. 计算先验概率及条件概率$$P(Y=c_k)=\frac {\sum_{i=1}^{N} I(y_i=c_k)}{N},k=1,2,…,K\\P(X^{(j)}=a_{jl}|Y=c_k)=\frac {\sum_{i=1}^{(j)}I(x_i^{(j)}=a_{jl},y_i=c_k)}{\sum_{i=1}^{N}I(y_i=c_k)}\\j=1,2,…,n;l=1,2,…,S_j;k=1,2,…,K$$
  2. 对于给定的实例$x=(x^{(1)},x^{(2)},…,x^{(n)})^T$,计算$$P(Y=c_k)\prod_{j=1}^{n}P(X^{(j)}=X^{(j)}|Y=c_k),k=1,2,…,K$$
  3. 确定实例$x$的类$$y=arg \max_{c_k} P(Y=c_k)\prod_{j=1}^{n}P(X^{(j)}=x^{(j)}|Y=c_k)$$

朴素贝叶斯算法在digits数据集上的实现

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
import numpy as np

def get_digits():
digits = load_digits()
data = np.zeros([len(digits.data), len(digits.data[0])])
for i in range(len(digits.data)):
for t in range(len(digits.data[0])):
if digits.data[i][t] > 0:
data[i][t] = 1
else:
data[i][t] = 0
X_train, X_test, y_train, y_test = train_test_split(data,np.array(digits.target) , test_size=0.25,random_state=33)
return X_train, X_test, y_train, y_test

class Naive_Bayes:
def train(self,X,Y):
self.P_Yc=np.zeros(10)#保存P(Y=c_k)
self.I_Yc=np.zeros(10)#保存I(Y_i=c_k)
self.I_XaYc=np.zeros((len(X[0]),len([0,1]),10))
for i in range(len(Y)):
self.I_Yc[Y[i]]+=1
for t in range(len(X[0])):
self.I_XaYc[t][ int(X[i][t]) ][Y[i]]+=1
self.P_Yc=[i/sum(self.I_Yc) for i in self.I_Yc]
# 第一项特征的数量,特征值的种类数量,分类的种类
self.P_XaYc=np.zeros((len(X[0]),len([0,1]),10))

for i in range(len(X[0])):
for t in range(len([0,1])):
for j in range(10):
self.P_XaYc[i][t][j]=self.I_XaYc[i][t][j]/self.I_Yc[j]

def predict(self,x):
score=np.zeros(10)
for i in range(10):
a=self.P_Yc[i]
for t in range(len(x)):
a*=self.P_XaYc[t][int(x[t])][i]
score[i]=a
return score.argmax()

if __name__ == '__main__':
# print(get_digits())
X_train, X_test, Y_train, y_test= get_digits()
nb=Naive_Bayes()
nb.train(X_train,Y_train)
t_num=0
print("*"*10,"预测过程","*"*10)
for i in range(len(y_test)):
if nb.predict(X_test[i])==y_test[i]:
t_num+=1
print("case",i,",预测值:",nb.predict(X_test[i]),",真实值:",y_test[i],"预测结果:",nb.predict(X_test[i])==y_test[i])
print("*"*10,"预测结果","*"*10)
print("准确率:",t_num/len(y_test))

结果

朴素贝叶斯法预测结果