朴素贝叶斯(naive Bayes)法是基于贝叶斯定理与特征条件独立假设的分类方法。
目录
设输入空间 X⊆Rn X ⊆ R n 为 n n 维向量的集合,输出空间为类标记集合 Y={c1,c2,...,cK} Y = { c 1 , c 2 , . . . , c K } ,输入特征向量 x∈X x ∈ X ,输出类标记为 y∈Y y ∈ Y , P(X,Y) P ( X , Y ) 是 X X 和 Y Y 的联合概率分布,数据集
由 P(X,Y) P ( X , Y ) 独立同分布产生。
朴素贝叶斯法就是通过训练集来学习联合概率分布 P(X,Y) P ( X , Y ) .具体就是从先验概率分布和条件概率分布入手,俩概率相乘即可得联合概率。
称之为朴素是因为将条件概率的估计简化了,对条件概率分布作了条件独立性假设,这也是朴素贝叶斯法的基石,假设如下
这个公式在之前的假设条件下等价于
对于给定的输入向量 x x ,通过学习到的模型计算后验概率分布 P(Y=Ck|X=x) P ( Y = C k | X = x ) ,后验分布中最大的类作为 x x 的输出结果,根据贝叶斯定理可知后验概率为
其中 ∑kP(X=x|Y=ck)P(Y=ck)⇔P(X=x) ∑ k P ( X = x | Y = c k ) P ( Y = c k ) ⇔ P ( X = x )
所有 ck c k 的 P(X=x) P ( X = x ) 都是相同的,这样我们可以把输出结果化简成
这样,就了解了朴素贝叶斯法的基本原理了,下面要介绍的是参数估计。
我们已经知道对于给定的输入向量 x x ,其输出结果可以表示为
可以使用极大似然估计法来估计相应的概率。先验概率 P(Y=ck) P ( Y = c k ) 的极大似然估计是
设第 j j 个特征 x(j) x ( j ) 可能的取值的集合为 {aj1,aj2,...,ajsj} { a j 1 , a j 2 , . . . , a j s j } ,条件概率 P(X(j)=ajl|Y=ck) P ( X ( j ) = a j l | Y = c k ) 的极大似然估计是
下面给出朴素贝叶斯法的学习与分类算法。
输入: 训练数据 T={(x1,y1),(x2,y2),...,(xn,yn)} T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) } , 其中 xi=(x(1)i,x(2)i,...,x(n)i)T x i = ( x i ( 1 ) , x i ( 2 ) , . . . , x i ( n ) ) T , x(j)i∈{aj1,aj2,...,ajsj} x i ( j ) ∈ { a j 1 , a j 2 , . . . , a j s j } , j=1,2,...,n j = 1 , 2 , . . . , n , l=1,2,...,Sj l = 1 , 2 , . . . , S j , yi∈{c1,c2,...,cK} y i ∈ { c 1 , c 2 , . . . , c K } ;实例 x x ;
输出: 实例 x x 的分类.
(1) 计算先验概率及条件概率
(2) 对于给定的实例 x=(x(1),x(2),...,x(n))T x = ( x ( 1 ) , x ( 2 ) , . . . , x ( n ) ) T ,计算
(3) 确定实例 x x 的类
例子:试由下表的训练数据学习一个朴素贝叶斯分类器并确定
python代码如下:
import numpy as np
#构造NB分类器
def Train(X_train, Y_train, feature):
global class_num,label
class_num = 2 #分类数目
label = [1, -1] #分类标签
feature_len = 3 #特征长度
#构造3×2的列表
feature = [[1, 'S'],
[2, 'M'],
[3, 'L']]
prior_prob = np.zeros(class_num) # 初始化先验概率
con_prob = np.zeros((class_num,feature_len,2)) # 初始化条件概率
positive_count = 0 #统计正类
negative_count = 0 #统计负类
for i in range(len(Y_train)):
if Y_train[i] == 1:
positive_count += 1
else:
negative_count += 1
prior_prob[0] = positive_count / len(Y_train) #求得正类的先验概率
prior_prob[1] = negative_count / len(Y_train) #求得负类的先验概率
'''
con_prob是一个2*3*2的三维列表,第一维是类别分类,第二维和第三维是一个3*2的特征分类
'''
#分为两个类别
for i in range(class_num):
#对特征按行遍历
for j in range(feature_len):
#遍历数据集,并依次做判断
for k in range(len(Y_train)):
if Y_train[k] == label[i]: #相同类别
if X_train[k][0] == feature[j][0]:
con_prob[i][j][0] += 1
if X_train[k][1] == feature[j][1]:
con_prob[i][j][1] += 1
class_label_num = [positive_count, negative_count] #存放各类型的数目
for i in range(class_num):
for j in range(feature_len):
con_prob[i][j][0] = con_prob[i][j][0] / class_label_num[i] #求得i类j行第一个特征的条件概率
con_prob[i][j][1] = con_prob[i][j][1] / class_label_num[i] #求得i类j行第二个特征的条件概率
return prior_prob,con_prob
#给定数据进行分类
def Predict(testset, prior_prob, con_prob, feature):
result = np.zeros(len(label))
for i in range(class_num):
for j in range(len(feature)):
if feature[j][0] == testset[0]:
conA = con_prob[i][j][0]
if feature[j][1] == testset[1]:
conB = con_prob[i][j][1]
result[i] = conA * conB * prior_prob[i]
result = np.vstack([result,label])
return result
def main():
X_train = [[1, 'S'], [1, 'M'], [1, 'M'], [1, 'S'], [1, 'S'],
[2, 'S'], [2, 'M'], [2, 'M'], [2, 'L'], [2, 'L'],
[3, 'L'], [3, 'M'], [3, 'M'], [3, 'L'], [3, 'L']]
Y_train = [-1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1]
#构造3×2的列表
feature = [[1, 'S'],
[2, 'M'],
[3, 'L']]
testset = [2, 'S']
prior_prob, con_prob= Train(X_train, Y_train, feature)
result = Predict(testset, prior_prob, con_prob, feature)
print('The result:',result)
main()
得到结果:
The result: [[ 0.02222222 0.06666667]
[ 1. -1. ]]
极大似然估计的一个可能是会出现所要估计的概率值为0的情况,这时会影响到后验概率的计算结果,解决这一问题的方法是采用贝叶斯估计,具体的只需要在极大似然估计的基础上加多一个参数即可。
当 λ=0 λ = 0 时就是最大似然估计。常取 λ=1 λ = 1 ,这时称为拉普拉斯平滑(Laplace smoothing)。
朴素贝叶斯法高效,且易于实现,但是其缺点就是分类的性能不一定很高。