朴素贝叶斯算法
- 算法概述
- 数理统计学处理的信息
- 古典学派和贝叶斯学派的争论
- 贝叶斯定理
- 朴素贝叶斯分类
- 训练朴素贝叶斯:朴素假设
- 案例:预测打网球
- 拉普拉斯平滑技术
- 小结
- 算法流程与步骤
- 算法应用
- sklearn中的朴素贝叶斯
- 朴素贝叶斯的使用
- 算法实例
算法概述
数理统计学处理的信息
- 总体信息:当前总体样本符合某种分布。比如抛硬币,二项分布。学生的某一科的成绩符合正态分布。
- 样本信息:通过抽样得到的部分样本的某种分布。
- 抽样信息=总体信息+样本信息
- 基于抽样信息进行统计推断的理论和方法称为经典统计学。
先验信息:抽样之前,有关推断问题中未知参数的一些信息,通常来自于经验或历史资料。
基于总体信息+样本信息+先验信息进行统计推断的方法和理论,称为贝叶斯统计学。
古典学派和贝叶斯学派的争论
- 古典学派:认为概率来源于统计,需要通过统计来得到概率。
- 贝叶斯学派:认为有些情况概率是来源于统计,有些情况概率是来源于先验知识。
- 矛盾点在于是否承认先验概率。
贝叶斯定理
- 贝叶斯定理告诉我们如何交换条件概率中的条件与结果,即如果已知P(X|H),要求P(H|X),那么可以使用下面的计算方法:
P ( H ∣ X ) = P ( X ∣ H ) P ( H ) P ( X ) P(H|X)=\frac{P(X|H)P(H)}{P(X)} P(H∣X)=P(X)P(X∣H)P(H)- 贝叶斯定理引入了先验概率,后验概率由先验概率和类条件概率表达式计算出。
- 先验概率:根据以往经验和分析得到的概率。
- 后验概率:后验概率就是基于新的信息,修正原来的先验概率后所获得的更接近实际情况的概率估计。
- 实际上先验概率就是没有任何结果出来的情况下估计的概率,而后验概率则是在有一定依据后的重新估计,直观意义上后验概率就是条件概率。
- 贝叶斯方法分析的特点是用概率表示不确定性,概率规则表示推理或学习,随机变量的概率分布 表示推理或学习的最终结果。
贝叶斯理论概述
- 假设事件A和事件B是随机试验E的两个随机事件,则似然概率 P ( B ∣ A ) = P ( A B ) P ( A ) P(B|A)=\frac{P(AB)}{P(A)} P(B∣A)=P(A)P(AB),表示已知事件A发生的前提下,事件B发生的概率。
- 随着随机事件A的出现,将样本空间缩小到A。接着,随机事件B的出现将样本空间进一步缩小到A∩B。由于集合的∩运算是可交换的,因此有: P ( A ∩ B ) = P ( B ∣ A ) P ( A ) = P ( A ∣ B ) P ( B ) = P ( B ∩ A ) P(A∩B)=P(B|A)P(A)=P(A|B)P(B)=P(B∩A) P(A∩B)=P(B∣A)P(A)=P(A∣B)P(B)=P(B∩A)
整理得到贝叶斯公式:
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)
上述公式即为贝叶斯公式,它提供了从先验概率P(A)计算后验概率P(A|B)的方法。
如果将A理解为假设,B理解为数据,那么贝叶斯定理告诉我们:在给定数据的条件下,如何计算假设成立的概率。
- 先验概率P(A):在观测到数据之前,人们对参数的理解。
- 似然概率P(B|A):如何在实验中引入观测数据,反映的是在给定参数下得到某组观测数据的可信度。
- 后验概率P(A|B):是贝叶斯分析的结果,反映的是在给定数据和模型的条件下,人们对问题的全部认知。需要注意的是,后验指模型中参数的概率分布而不是某个值,该分布正比于先验乘以似然。
- 证据P(B):也叫做边缘似然。证据是在模型的参数取遍所有可能值的条件下得到指定观测值的概率的平均。
朴素贝叶斯分类
- 贝叶斯理论在分类算法中的解释:把B看做样本,A看做类别,那么贝叶斯定理告诉我们:在给定样本的情况下,如何计算样本属于某个类别的概率。
- 朴素贝叶斯分类(Naive Bayes Classifier)是基于贝叶斯定理和特征条件独立假设的分类算法。
- 朴素贝叶斯模型的参数也不多,对缺失数据不太敏感,算法实现比较简单。
- 通俗地讲,朴素贝叶斯分类器可以看作:对于给定的待分类项,求解在该分类项出现的条件下,各个类别出现的概率。根据各个类别出现的概率,哪个最大,就将其回归为哪个类别。
P ( A ∣ B × C ) = P ( B ∣ A ) × P ( C ∣ A ) × P ( A ) P ( B ) × P ( C ) P(A|B×C)=\frac{P(B|A)×P(C|A)×P(A)}{P(B)×P(C)} P(A∣B×C)=P(B)×P(C)P(B∣A)×P(C∣A)×P(A)
训练朴素贝叶斯:朴素假设
给定特征向量X,计算其属于每个类别C的概率:
P ( C ∣ X ) = P ( X ∣ C ) ∗ P ( C ) P(C|X)=P(X|C)*P(C) P(C∣X)=P(X∣C)∗P(C)
解决方案:假设给定类别,所有特征相互独立。
P ( C ∣ X ) = P ( X 1 ∣ C ) ∗ P ( X 2 ∣ C ) ∗ . . . ∗ P ( X n ∣ C ) ∗ P ( C ) P(C|X)=P(X_1|C)*P(X_2|C)*...*P(X_n|C)*P(C) P(C∣X)=P(X1∣C)∗P(X2∣C)∗...∗P(Xn∣C)∗P(C)
这就是“朴素”的假设
P ( C ∣ X ) = P ( C ) ∏ i = 1 n P ( X i ∣ C ) P(C|X)=P(C)\prod_{i=1}^n P(X_i|C) P(C∣X)=P(C)i=1∏nP(Xi∣C)
按照最大后验概率规则,把X分入概率最大的类别
a r g m a x k ∈ 1 , . . , K P ( C k ) ∏ i = 1 n P ( X i ∣ C k ) \frac{argmax}{k∈{1,..,K}}P(C_k)\prod_{i=1}^nP(X_i|C_k) k∈1,..,KargmaxP(Ck)i=1∏nP(Xi∣Ck)
很多概率值连乘,容易造成浮点计算下界溢出,取对数把乘法转化成加法
l o g ( P ( C k ) ) ∑ i = 1 n l o g ( P ( X i ∣ C k ) ) log(P(C_k))\sum_{i=1}^{n}log(P(X_i|C_k)) log(P(Ck))i=1∑nlog(P(Xi∣Ck))
案例:预测打网球
P(Play=yes)=9/14,P(Play=no)=5/14
使用训练数据构建概率查找表:
预测下面情境下是否打网球:
x=(Outlook=Sunny,Temperature=Cool,Humidity=High,Wind=Strong)
P(yes|sunny,cool,high,strong)=P(sunny|yes)*P(cool|yes)*P(high|yes)*P(strong|yes)*P(yes)
P(no|sunny,cool,high,strong)=P(sunny|no)*P(cool|no)*P(high|no)*P(strong|no)*P(no)
拉普拉斯平滑技术
问题:有些类别里没有的特征将会导致这些条件概率值为“0”
解决方案:在这些条件概率的分子和分母上各加1
小结
- 对于给定的训练数据集,首先基于特征属性独立假设学习输入\输出的联合概率分布,然后基于模型,对给定的输入,利用贝叶斯定理估计后验概率最大的输出。
- 朴素贝叶斯有稳定的分类效率,在大量样本下会有较好的表现,对小规模的数据依然有效,能处理多分类任务。再有,朴素贝叶斯适合增量式训练,既可以实时对新增样本进行训练。
- 朴素贝叶斯对缺失数据不太敏感,常用于文本分类识别、欺诈检测、垃圾邮件过滤、拼写检查等领域。
算法流程与步骤
1.确定特征属性 x j x_j xj,获取训练样本集合 y i y_i yi
该步骤的主要工作是根据具体情况确定特征属性,并对每个特征属性进行适当划分,然后人工对一部分待分类项进行分类,形成训练样本集合。这一阶段的输入是所有待分类数据,输出是特征属性和训练样本。
2.对于所有待分类数据,确定其特征属性 x j x_j xj,获取训练样本集合 y i y_i yi
D = ( x 1 ( 1 ) , x 2 ( 1 ) , . . . , x n ( 1 ) , y 1 ) , ( x 1 ( 2 ) , x 2 ( 2 ) , . . . , x n ( 2 ) , y 2 ) , . . . , x 1 ( m ) , x 2 ( m ) , . . . , x n ( m ) , y m ) D={(x_1^{(1)},x_2^{(1)},...,x_n^{(1)},y_1),(x_1^{(2)},x_2^{(2)},...,x_n^{(2)},y_2),...,x_1^{(m)},x_2^{(m)},...,x_n^{(m)},y_m)} D=(x1(1),x2(1),...,xn(1),y1),(x1(2),x2(2),...,xn(2),y2),...,x1(m),x2(m),...,xn(m),ym)
其中,m表示有m个样本,n表示有n个特征。 y i y_i yi表示训练样本集合,取值为 C 1 , C 2 , . . . , C k {C_1,C_2,...,C_k} C1,C2,...,Ck
3.计算各类别的先验概率P(Y=C_k)
针对训练样本集,我们可以利用极大似然估计计算先验概率。但为了弥补极大似然估计中可能出现概率值为0的情况,也就是某个事件出现的次数为0,我们使用贝叶斯估计计算先验概率:
4.计算各类别下各特征属性x_j的条件概率
如果 x j x_j xj是离散值,我们可以假设 x j x_j xj符合多项式分布,这样得到的条件概率是在样本类别 C k C_k Ck中,特征 x j x_j xj出现的概率,即:
某些时候,可能某些类别在样本中没有出现,这可能导致条件概率为0,这样会影响后验概率的估计。为了解决这种情况,我们引入了拉普拉斯平滑,即此时有:
如果 x j x_j xj是稀疏二项离散值,即各个特征出现概率很低,我们可以假设 x j x_j xj符合伯努利分布,即特征 x j x_j xj出现记为1,不出现记为0。我们不关注 x j x_j xj出现的次数。这样得到的条件概率是在样本类别 C k C_k Ck中, x j x_j xj出现的概率。此时有:
如果是 x j x_j xj是连续值,我们通常取 x j x_j xj的先验概率为正态分布,即在样本类别 C k C_k Ck中, x j x_j xj的值符合正态分布。这样得到的条件概率分布是:
5.计算各类别的后验概率 P ( Y = C k ∣ X = x ) P(Y=C_k|X=x) P(Y=Ck∣X=x)
由于假设各特征属性是条件独立的,则根据贝叶斯定理,各类别的后验概率有如下推导:
6.以后验概率最大项作为样本所属类别
我们预测的样本所属类别 C r e s u l t C_result Cresult是使用后验概率 P ( Y = C k ∣ X = x ) P(Y=C_k|X=x) P(Y=Ck∣X=x)最大化的类别,推导如下:
7.由于对于所有的类别计算后验概率时,分母是一样的,因此我们的预测公式可以简化为:
8.我们利用朴素贝叶斯的独立性假设,就可以得到通常意义上的朴素贝叶斯推断公式:
总结
算法应用
sklearn中的朴素贝叶斯
在sklearn库中,实现了三个朴素贝叶斯分类器,如下表所示:
分类器 | 描述 |
---|---|
naive_bayes.GussianNB | 高斯朴素贝叶斯 |
naive_bayes.MultinomialNB | 针对多项式模型的朴素贝叶斯分类器 |
naive_bayes.BernoulliNB | 针对多元伯努利模型的朴素贝叶斯分类器 |
区别在于假设某一特征的所有属于某个类别的观测值符合特定分布,如,分类问题的特征包括人的身高,身高符合高斯分布,这类问题适合高斯朴素贝叶斯,即在高斯朴素贝叶斯分类器中,假设特征的条件概率分布满足高斯分布。
朴素贝叶斯的使用
1.导入numpy库,并构造训练数据X和y。
import numpy as np
X=np.array([[-1,-1],[-2,-1],[-3,-2],[1,1],[2,1],[3,2]])
Y=np.array([1,1,1,2,2,2])
2.使用import语句导入朴素贝叶斯分类器。
from sklearn.naive_bayes import GaussianNB
3.使用默认参数,创建一个高斯朴素贝叶斯分类器,并将该分类器赋给变量clf。
clf=GaussianNB(priors=None)
4.类似的,使用fit()函数进行训练,并使用predict()函数进行预测,得到的预测结果为1。
clf.fit(X,Y)
print(clf.predict([[-0.8,-1]]))
朴素贝叶斯是典型的生成学习方法,由训练数据学习联合概率分布,并求得后验概率分布。
朴素贝叶斯一般在小规模数据上的表现很好,适合进行多分类任务。
算法实例
以下是应用sklearn库中朴素贝叶斯(高斯)分类模型进行分析的示例代码。数据源是通过sklearn中的聚类生成器(make_blobs)生成的50000个随机样本,每个样本的特征数为2个,样本集的标准差是1.0,随机数种子为42
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.naive_bayes import GaussianNB
centers=[(-5,5),(0,0),(5,5)]
#生成50000个随机样本,每个样本的特征数是2个,样本集的标准差是1.0,随机数种子为42
X,y=make_blobs(n_samples=50000,n_features=2,cluster_std=1.0,centers=centers,shuffle=False,random_state=42)
n_samples=50000
y[:n_samples//2]=0
y[n_samples//2:]=1
#①生成数据集
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.9,random_state=42)
clf=GaussianNB()
#②训练模型
clf.fit(X_train,y_train)
#③预测
target_pred=clf.predict(X_test)
#④模型准确率
score=accuracy_score(y_test,target_pred,normalize=True)
print("accuracy score:",score)
分别使用3种朴素贝叶斯算法对iris()、breast_cancer()和wine()数据集进行分类,比较三种贝叶斯模型(GaussianNB,MultinomialNB,BernoulliNB)的分类结果(要求:分别打印出分类结果的准确率和混淆矩阵)
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB,MultinomialNB,BernoulliNB
from sklearn.metrics import accuracy_score,confusion_matrix
#①创建数据集
iris=datasets.load_iris()
breast_cancer=datasets.load_breast_cancer()
wine=datasets.load_wine()
#②划分训练集和测试集
#按照训练集是70%,测试集是30%的比例来划分,随机种子是42
iris_X_train,iris_X_test,iris_y_train,iris_y_test=train_test_split(iris.data,iris.target,test_size=0.3,random_state=42)
breast_cancer_X_train,breast_cancer_X_test,breast_cancer_y_train,breast_cancer_y_test=train_test_split(breast_cancer.data,breast_cancer.target,test_size=0.3,random_state=42)
wine_X_train,wine_X_test,wine_y_train,wine_y_test=train_test_split(wine.data,wine.target,test_size=0.3,random_state=42)
#③创建GaussianNB模型并进行分类
gnb=GaussianNB()
#训练模型
gnb.fit(iris_X_train,iris_y_train)
#预测
iris_gnb_y_pred=gnb.predict(iris_X_test)
#评估
print("GaussianNB模型在iris数据集上的准确率是:",accuracy_score(iris_y_test,iris_gnb_y_pred))
print("GaussianNB模型在iris数据集上的混淆矩阵是:\n",confusion_matrix(iris_y_test,iris_gnb_y_pred))
gnb.fit(breast_cancer_X_train,breast_cancer_y_train)
breast_cancer_gnb_y_pred=gnb.predict(breast_cancer_X_test)
print("GaussianNB模型在breast_cancer数据集上的准确率是:",accuracy_score(breast_cancer_y_test,breast_cancer_gnb_y_pred))
print("GaussianNB模型在breast_cancer数据集上的混淆矩阵是:\n",confusion_matrix(breast_cancer_y_test,breast_cancer_gnb_y_pred))
gnb.fit(wine_X_train,wine_y_train)
wine_gnb_y_pred=gnb.predict(wine_X_test)
print("GaussianNB模型在wine数据集上的准确率是:",accuracy_score(wine_y_test,wine_gnb_y_pred))
print("GaussianNB模型在wine数据集上的混淆矩阵是:\n",confusion_matrix(wine_y_test,wine_gnb_y_pred))
#④创建MutinomialNB模型并进行分类
mnb=MultinomialNB()
mnb.fit(iris_X_train,iris_y_train)
iris_mnb_y_pred=mnb.predict(iris_X_test)
print("MutinomialNB模型在iris数据集上的准确率是:",accuracy_score(iris_y_test,iris_mnb_y_pred))
print("MutinomialNB模型在iris数据集上的混淆矩阵是:\n",confusion_matrix(iris_y_test,iris_mnb_y_pred))
mnb.fit(breast_cancer_X_train,breast_cancer_y_train)
breast_cancer_mnb_y_pred=mnb.predict(breast_cancer_X_test)
print("MutinomialNB模型在breast_cancer数据集上的准确率是:",accuracy_score(breast_cancer_y_test,breast_cancer_mnb_y_pred))
print("MutinomialNB模型在breast_cancer数据集上的混淆矩阵是:\n",confusion_matrix(breast_cancer_y_test,breast_cancer_mnb_y_pred))
mnb.fit(wine_X_train,wine_y_train)
wine_mnb_y_pred=mnb.predict(wine_X_test)
print("MutinomialNB模型在wine数据集上的准确率是:",accuracy_score(wine_y_test,wine_mnb_y_pred))
print("MutinomialNB模型在wine数据集上的混淆矩阵是:\n",confusion_matrix(wine_y_test,wine_mnb_y_pred))
#⑤创建BernoulliNB模型并进行分类
bnb=BernoulliNB()
bnb.fit(iris_X_train,iris_y_train)
iris_bnb_y_pred=bnb.predict(iris_X_test)
print("BernoulliNB模型在iris数据集上的准确率是:",accuracy_score(iris_y_test,iris_bnb_y_pred))
print("BernoulliNB模型在iris数据集上的混淆矩阵是:\n",confusion_matrix(iris_y_test,iris_bnb_y_pred))
bnb.fit(breast_cancer_X_train,breast_cancer_y_train)
breast_cancer_bnb_y_pred=bnb.predict(breast_cancer_X_test)
print("BernoulliNB模型在breast_cancer数据集上的准确率是:",accuracy_score(breast_cancer_y_test,breast_cancer_bnb_y_pred))
print("BernoulliNB模型在breast_cancer数据集上的混淆矩阵是:\n",confusion_matrix(breast_cancer_y_test,breast_cancer_bnb_y_pred))
bnb.fit(wine_X_train,wine_y_train)
wine_bnb_y_pred=bnb.predict(wine_X_test)
print("BernoulliNB模型在wine数据集上的准确率是:",accuracy_score(wine_y_test,wine_bnb_y_pred))
print("BernoulliNB模型在wine数据集上的混淆矩阵是:\n",confusion_matrix(wine_y_test,wine_bnb_y_pred))