朴素贝叶斯
一种直接衡量标签和特征之间概率关系的有监督学习算法,专注分类的算法,基于概率论和数理统计的贝叶斯理论。在计算的过程中,假设特征之间条件独立,不进行建模,采用后验估计。

sklearn中的朴素贝叶斯

含义
naive_bayes.BernoulliNB 伯努利分布下的朴素贝叶斯
naive_bayes.GaussianNB 高斯分布下的朴素贝叶斯
naive_bayes.MultinomialNB 多项式分布下的朴素贝叶斯
naive_bayes.ComplementNB 补集朴素贝叶斯
linear_model.BayesianRidge 贝叶斯岭回归,在参数估计过程中使用贝叶斯回归技术来包括正则化参数

高斯朴素贝叶斯

参数 含义
prior 可输入任何类数组结构,形状为(n_classes,)表示类的先验概率。
如果指定,则不根据数据调整先验,如果不指定,则自行根据数据计算先验概率 P(Y)
var_smoothing 浮点数,可不填(默认值= 1e-9)
在估计方差时,为了追求估计的稳定性,将所有特征的方差中最大的方差以某个比例添加到估计的方差中

假设服从正态分布来估计每个特征下每个类别上的条件概率。公式如下:
对于任意一个Y的取值,贝叶斯都以求解最大化的 P ( x i ∣ Y ) P(x_i|Y) P(xi​∣Y)为目标,比较不同标签下样本靠近哪一个值。

简单测试

import numpy as np
import matplotlib.pyplot as plt
from sklearn.naive_bayes import GaussianNB
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split digits = load_digits()
X,y = digits.data,digits.target
Xtrain,Xtest,Ytrain,Ytest= train_test_split(X,y,test_size=0.3,random_state=420)gnb = GaussianNB().fit(Xtrain,Ytrain)
acc_score = gnb.score(Xtest,Ytest)
acc_score


混淆矩阵查看分类结果

from sklearn.metrics import confusion_matrix as CM
CM(Ytest,Y_pred)


探索朴素贝叶斯的拟合效果与运算速度
第一步:导入需要模块

import numpy as np
import matplotlib.pyplot as plt
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.tree import DecisionTreeClassifier as DTC
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_digits
from sklearn.model_selection import learning_curve
from sklearn.model_selection import ShuffleSplit
from time import time
import datetime
import pytz

第二步:定义学习曲线函数以及导入数据

def plot_learning_curve(estimator,title,X,y,ax,ylim=None,cv=None,n_jobs=None):train_sizes, train_scores, test_scores = learning_curve(estimator,X,y,cv=cv,n_jobs=n_jobs)ax.set_title(title)if ylim is not None:ax.set_ylim(*ylim)ax.set_xlabel("Training examples")ax.set_ylabel("Score")ax.grid()ax.plot(train_sizes,np.mean(train_scores,axis=1),'o-',color="r",label="Training score")ax.plot(train_sizes,np.mean(test_scores,axis=1),'o-',color="g",label="Test score")ax.legend(loc="best")return axdigits = load_digits()
X,y =digits.data, digits.target
title = ["Naive Bayes","DecisionTree","SVM, RBF kernel","RandomForest","Logistic"]
model = [GaussianNB(),DTC(),SVC(gamma=0.001),RFC(n_estimators=50),LR(C=.1,solver="lbfgs")]
cv = ShuffleSplit(n_splits=50, test_size=0.2, random_state=0)

第三步:循环绘制学习曲线

fig, axes = plt.subplots(1,5,figsize=(30,6))
for ind,title_,estimator in zip(range(len(title)),title,model):times = time()print(ind)plot_learning_curve(estimator,title_,X,y,ax=axes[ind],ylim=[0.7,1.05],n_jobs=4,cv=cv)print("{}:{}".format(title_,datetime.datetime.fromtimestamp(time()-times,pytz.timezone('UTC')).strftime("%M:%S:%f")))
plt.show()[*zip(range(len(title)),title,model)]




几个得出的结论:

  • 决策树和贝叶斯运行都很快。决策树运行快速是因为sklearn中分类树在特征选择时没有计算全部特征只是随机选择一部分特征来进行计算,当样本量增大后会变慢
  • 除了贝叶斯,其他算法准确率都达到了100%,即它天生学习能力就比较弱,不仅如此,随着样本量增大,贝叶斯对训练集的拟合程度也越来越差
  • 各个模型都存在过拟合问题。强大的分类器通过快速提高测试集上的表现来减轻过拟合问题,决策树提升相对缓慢。贝叶斯还依赖训练集上的准确率下降
  • 贝叶斯相对没有提升潜力,但计算很快。如果数据十分复杂或者是稀疏矩阵,那么可以优先尝试贝叶斯模型

概率类模型的评估指标
评测给出预测的可信度
布里尔分数Brier Score
概率预测相对与测试样本的均方误差:
B r i e r S c o r e = 1 N ( p i − o i ) 2 Brier Score =\frac{1}{N}(p_i-o_i)^2 BrierScore=N1​(pi​−oi​)2
其中p为预测出的概率,o为样本真实结果,只能取0或。结果分数范围0到1,越接近0效果越好。可以用于任何使用predict_proba接口调用概率的模型
探索手写数据集上逻辑回归,SVC和高斯朴素贝叶斯的效果:
第一步:库导入以及初步准备

import pandas as pd
from sklearn.metrics import brier_score_loss
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression as LRprob.shape
Ytest_1=Ytest.copy()
Ytest_1=pd.get_dummies(Ytest_1)
brier_score_loss(Ytest_1[1], prob[:,1], pos_label=1)

第二步:调用逻辑回归和svc模型,同时将svc置信度距离归一化

logi = LR(C=1., solver='lbfgs',max_iter=3000,multi_class="auto").fit(Xtrain,Ytrain)
svc = SVC(kernel = "linear",gamma=1).fit(Xtrain,Ytrain)
svc_prob = (svc.decision_function(Xtest) -
svc.decision_function(Xtest).min())/(svc.decision_function(Xtest).max() -
svc.decision_function(Xtest).min())
name = ["Bayes","Logistic","SVC"]
color = ["red","black","orange"]
df = pd.DataFrame(index=range(10),columns=name)
df


第三步:将每个标签类别下分数可视化

for i in range(10):df.loc[i,name[0]] = brier_score_loss(Ytest_1[i],prob[:,i],pos_label=1) df.loc[i,name[1]] = brier_score_loss(Ytest_1[i],logi.predict_proba(Xtest)[:,i],pos_label=1) df.loc[i,name[2]] = brier_score_loss(Ytest_1[i],svc_prob[:,i],pos_label=1)
for i in range(df.shape[1]):plt.plot(range(10),df.iloc[:,i],c=color[i])
plt.legend()
plt.show()
df


可以看到SVC效果明显弱于贝叶斯和逻辑回归(因为它通过sigmoid函数来强行压缩概率)

对数似然函数Log Loss
对于一个真实标签在{0,1}中取值,并且这个类别在1的概率估计为 y p r e d y_{pred} ypred​,则对应损失函数类似于逻辑回归中损失函数为:
− l o g P ( y t r u e ∣ y p r e d ) = − ( y t r u e ∗ l o g ( y p r e d ) + ( 1 − y t r u e ∗ l o g ( 1 − y p r e d ) ) -logP(y_{true}|y_{pred})=-(y_{true}*log(y_{pred})+(1-y_{true}*log(1-y_{pred})) −logP(ytrue​∣ypred​)=−(ytrue​∗log(ypred​)+(1−ytrue​∗log(1−ypred​))

sklearn中通过对数似然函数查看

from sklearn.metrics import log_loss
log_loss(Ytest,prob)
log_loss(Ytest,logi.predict_proba(Xtest))
log_loss(Ytest,svc_prob)


可以看到,此时贝叶斯中效果不如SVC,这与之前使用布里尔分数得到的结论不同。这是因为,SVC和逻辑回归都是以最优化目的求解模型的,而在朴素贝叶斯中没有这个最优化的过程,所以没有优势。

不同情况下对数似然与布里尔的选择

需求 优先使用对数似然 优先使用布里尔分数
衡量模型 要对比多个模型,或者衡量模型的不同变化 衡量单一模型的表现
可解释性 机器学习和深度学习之间的行家交流,学术论文 商业报告,老板开会,业务模型的衡量
最优化指向 逻辑回归,SVC 朴素贝叶斯
数学问题 概率只能无限接近于0或1,无法取到0或1 概率可以取到0或1,比如树,随机森林

在使用贝叶斯模型的情况下追求概率预测上贴近真实概率,可以使用可靠性曲线来调节概率的校准程度

可靠性曲线 Reliability Curve
又称为概率校准曲线,可靠性图,是一条以预测概率为横坐标,真实标签为纵坐标的曲线。通常用于二分类,接下来进行绘制:

第一步:导入库和创建数据集

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification as mc
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression as LR
from sklearn.metrics import brier_score_loss
from sklearn.model_selection import train_test_splitX, y = mc(n_samples=100000,n_features=20,n_classes=2,n_informative=2,n_redundant=10,random_state=42)
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.99,random_state=42)
np.unique(Ytrain)


第二步:建立模型,尝试绘制图像

gnb = GaussianNB()
gnb.fit(Xtrain,Ytrain)
y_pred = gnb.predict(Xtest)
prob_pos = gnb.predict_proba(Xtest)[:,1]
clf_score = gnb.score(Xtest,Ytest)
df = pd.DataFrame({"ytrue":Ytest[:500],"probability":prob_pos[:500]})
df = df.sort_values(by="probability")
df.index=range(df.shape[0])
dffig = plt.figure()
ax1 = plt.subplot()
ax1.plot([0,1],[0,1],"k:",label="Perfectly calibrated")
ax1.plot(df["probability"],df["ytrue"],"s-",label="%s (%1.3f)"%("Bayes",clf_score))
ax1.set_ylabel("True label")
ax1.set_xlabel("predcited probaility")
ax1.set_ylim([-0.05,1.05])
ax1.legend()
plt.show()


很明显是有问题的,因为预测概率的值不断在0和1之前来回跳跃,所以导致如此混乱。希望的是一个范围在0到1的概率,由于真实概率无法获得,可以采用分箱的方式来获取类概率进行校准。具体做法如下:

可以看到,分享可以让曲线变的平滑。sklearn中可以使用calibration_curve来帮助绘制相关图像,其相关参数如下:

参数 含义
y_true 真实标签
y_prob 预测返回的,正类别下的概率值或置信度
normalize 布尔值,默认False
是否将y_prob中输入的内容归一化到[0,1]之间,比如说,当y_prob并不是真正的概率的时候可以使用。如果这是为True,则会将y_prob中最小的值归一化为0,最大值归一化为1
n_bins 整数值,表示分箱的个数。如果箱数很大,则需要更多的数据
返回 含义
trueproba 可靠性曲线的纵坐标,结构为(n_bins, ),是每个箱子中少数类(Y=1)的占比
predproba 可靠性曲线的横坐标,结构为(n_bins, ),是每个箱子中概率的均值

第三步:使用可靠性曲线的类绘制校准后的线

from sklearn.calibration import calibration_curvetrueproba, predproba = calibration_curve(Ytest,prob_pos,n_bins=10)
fig = plt.figure()
ax1 = plt.subplot()
ax1.plot([0,1],[0,1],"k:",label="Perfectly calibrated")
ax1.plot(trueproba,predproba,"s-",label="%s (%1.3f)"%("Bayes",clf_score))
ax1.set_ylabel("True label")
ax1.set_xlabel("predcited probaility")
ax1.set_ylim([-0.05,1.05])
ax1.legend()
plt.show()


第四步:不同bin取值下曲线的变化

fig, axes = plt.subplots(1,3,figsize=(18,4))
for ind,i in enumerate([3,10,100]):ax = axes[ind]ax.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated")trueproba, predproba = calibration_curve(Ytest, prob_pos,n_bins=i)ax.plot(predproba, trueproba,"s-",label="n_bins = {}".format(i))ax1.set_ylabel("True probability for class 1")ax1.set_xlabel("Mean predcited probability")ax1.set_ylim([-0.05, 1.05])ax.legend()
plt.show()



箱子数太多导致不够平滑,箱子数太少导致概率校准曲线过于粗糙,一般从10开始调整

第五步:多个模型校准曲线对比

fig, ax1 = plt.subplots(figsize=(8,6))
ax1.plot([0,1],[0,1],"k:",label="Perfectly calibrated")
for clf ,name_ in zip([gnb,logi,svc],name):clf.fit(Xtrain,Ytrain)y_pred = clf.predict(Xtest)if hasattr(clf,"predict_proba"):prob_pos = clf.predict_proba(Xtest)[:,1]else:prob_pos = clf.decision_function(Xtest)prob_pos = (prob_pos-prob_pos.min())/(prob_pos.max()-prob_pos.min())clf_score = brier_score_loss(Ytest,prob_pos,pos_label=y.max())trueproba,predproba = calibration_curve(Ytest,prob_pos,n_bins=10)ax1.plot(predproba,trueproba,"s-",label="%s (%1.3f)"%(name_,clf_score))
ax1.set_ylabel("True probability for class 1")
ax1.set_xlabel("Mean predcited probability")
ax1.set_ylim([-0.05, 1.05])
ax1.legend()
ax1.set_title('Calibration plots (reliability curve)')
plt.show()


逻辑回归依旧很完美。贝叶斯概率校准曲线呈现sigmoid镜像说明数据集中的数据不是相互条件独立(与此次设定相同),所以表现不好。SVC由于置信度本身就不足,大量样本集中在决策边界附近,所以准确度也有限

第六步:多个模型的概率分布直方图

直方图是以样本的预测概率分箱后的结果为横坐标,每个箱中的样本数量为纵坐标的一个图像,与之前可靠性曲线为了平滑的分箱是两码事

fig, ax2 = plt.subplots(figsize=(8,6))for clf, name_ in zip([gnb,logi,svc],name):clf.fit(Xtrain,Ytrain)y_pred = clf.predict(Xtest)if hasattr(clf, "predict_proba"):prob_pos = clf.predict_proba(Xtest)[:,1]else: prob_pos = clf.decision_function(Xtest)prob_pos = (prob_pos - prob_pos.min()) / (prob_pos.max() - prob_pos.min())ax2.hist(prob_pos ,bins=10,label=name_,histtype="step" ,lw=2 )ax2.set_ylabel("Distribution of probability")
ax2.set_xlabel("Mean predicted probability")
ax2.set_xlim([-0.05, 1.05])
ax2.set_xticks([0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])
ax2.legend(loc=9)
plt.show()


可以看到贝叶斯对于自己太过自信,SVC对于自己太过不自信。

校准可靠性曲线
使用sklearn中的CalibratedClassifierCV来对二分类情况下的数据集进行概率矫正

其中method选择概率校准的方法,可选“sigmoid”和“isotonic”

  • sigmoid:使用基于Platt的sigmoid模型进行校准
  • isotonic:使用等渗回归进行校准

当样本较少时,防止过拟合一般不建议使用isotionic

使用之前的数据进行校准:
第一步:包装函数

def plot_calib(models,name,Xtrain,Xtest,Ytrain,Ytest,n_bins=10):fig,(ax1,ax2) = plt.subplots(1,2,figsize=(20,6))ax1.plot([0,1],[0,1],"k:",label="Perfectly calibrated")for clf,name_ in zip(models,name):clf.fit(Xtrain,Ytrain)y_pred = clf.predict(Xtest)if hasattr(clf,"predict_proba"):prob_pos = clf.predict_proba(Xtest)[:,1]else:prob_pos=clf.decision_function(Xtest)prob_pos=(prob_pos - prob_pos.min())/(prob_pos.max()-prob_pos.min())clf_score = brier_score_loss(Ytest,prob_pos,pos_label=y.max())trueproba,predproba = calibration_curve(Ytest,prob_pos,n_bins=n_bins)ax1.plot(predproba,trueproba,"s-",label="%s (%1.3f)"%(name_,clf_score))ax2.hist(prob_pos,range=(0,1),bins=n_bins,label=name_,histtype="step",lw=2)ax2.set_ylabel("Distribution of probability")ax2.set_xlabel("Mean predicted probability")ax2.set_xlim([-0.05, 1.05])ax2.legend(loc=9)ax2.set_title("Distribution of probablity")ax1.set_ylabel("True probability for class 1")ax1.set_xlabel("Mean predcited probability")ax1.set_ylim([-0.05, 1.05])ax1.legend()ax1.set_title('Calibration plots(reliability curve)')plt.show()

第二步:实例化绘图

from sklearn.calibration import CalibratedClassifierCV
name = ["GaussianBayes","Logistic","Bayes+isotonic","Bayes+sigmoid"]
gnb = GaussianNB()
models = [gnb   ,LR(C=1., solver='lbfgs',max_iter=3000,multi_class="auto"),CalibratedClassifierCV(gnb, cv=2, method='isotonic'),CalibratedClassifierCV(gnb, cv=2, method='sigmoid')]
plot_calib(models,name,Xtrain,Xtest,Ytrain,Ytest)



Isotonic等渗校正大大改善了曲线的形状,几乎让贝叶斯的效果与逻辑回归持平,并且布里尔分数也下降到了0.098,比逻辑回归还低一个点。Sigmoid校准的方式也对曲线进行了稍稍的改善,不过效果不明显。从直方图来看,Isotonic校正让高斯朴素贝叶斯的效果接近逻辑回归,而Sigmoid校正后的结果依然和原本的高斯朴素贝叶斯更相近。可见,当数据的特征之间不是相互条件独立的时候,使用Isotonic方式来校准概率曲线,可以得到不错的结果,让模型在预测上更加谦虚

第三步:查看精确性的变化

gnb = GaussianNB().fit(Xtrain,Ytrain)
gnb.score(Xtest,Ytest)brier_score_loss(Ytest,gnb.predict_proba(Xtest)[:,1],pos_label=1)gnbisotonic = CalibratedClassifierCV(gnb, cv=2, method='isotonic').fit(Xtrain,Ytrain)
gnbisotonic.score(Xtest,Ytest)brier_score_loss(Ytest,gnbisotonic.predict_proba(Xtest)[:,1],pos_label = 1)


可以看到,校准后布里尔分数变小,但整体准确率缺下降了。对与不同模型出现这个现象的原因不同,对SVC和决策树这种模型来说,概率偏向于是一个“置信度”,校准可能使向更加错误的方向调整,因此出现布里尔分数与精确性相反的趋势。而对于朴素贝叶斯这样的模型,校准后准确性的变化取决测试集有多贴近估计的真实样本的面貌,这一系列有偏估计可能导致布里尔分数与准确度的趋势相反。当然,还有更多深层的原因,总之,如果两者相悖时,优先考虑准确率。

ccc-sklearn-13-朴素贝叶斯(1)相关推荐

  1. 基于sklearn的朴素贝叶斯_朴素贝叶斯分类实战:对文档进行分类

    朴素贝叶斯分类最适合的场景就是文本分类.情感分析和垃圾邮件识别.其中情感分析和垃圾邮件识别都是通过文本来进行判断.所以朴素贝叶斯也常用于自然语言处理 NLP 的工具. sklearn 机器学习包 sk ...

  2. 基于sklearn的朴素贝叶斯_Sklearn参数详解—贝叶斯

    在开始学习具体的贝叶斯参数前,你可以先看看:朴素贝叶斯详解​mp.weixin.qq.com 朴素贝叶斯一共有三种方法,分别是高斯朴素贝叶斯.多项式分布贝叶斯.伯努利朴素贝叶斯,在介绍不同方法的具体参 ...

  3. python调用sklearn中朴素贝叶斯踩坑

      调用结构: from sklearn.naive_bayes import MultinomialNB # 从sklean.naive_bayes里导入朴素贝叶斯模型 from sklearn.f ...

  4. Python+sklearn使用朴素贝叶斯算法识别中文垃圾邮件

    总体思路与步骤: 1.从电子邮箱中收集垃圾和非垃圾邮件训练集. 2.读取全部训练集,删除其中的干扰字符,例如[]*..,等等,然后分词,删除长度为1的单个字. 3.统计全部训练集中词语的出现次数,截取 ...

  5. [python机器学习及实践(2)]Sklearn实现朴素贝叶斯

    1.朴素贝叶斯简介 朴素贝叶斯(Naive Bayes)是一个基于贝叶斯理论的分类器.它会单独考量每一唯独特征被分类的条件概率,进而综合这些概率并对其所在的特征向量做出分类预测. 因此,朴素贝叶斯的基 ...

  6. sklearn学习-朴素贝叶斯(二)

    文章目录 一.概率类模型的评估指标 1.布里尔分数Brier Score 对数似然函数Log Loss 二. calibration_curve: 校准可靠性曲线 三.多项式朴素贝叶斯以及其变化 四. ...

  7. 使用Sklearn学习朴素贝叶斯算法

    目录 1,sklearn中的贝叶斯分类器 1.1,高斯朴素贝叶斯GaussianNB 1.1.1,认识高斯朴素贝叶斯 1.1.2,参数说明 1.1.3,高斯朴素贝叶斯建模案例 1.1.4,探索高斯朴素 ...

  8. sklearn学习-朴素贝叶斯

    文章目录 一.概述 1.真正的概率分类器 2.sklearn中的朴素贝叶斯 二.不同分布下的贝叶斯 1.高斯朴素贝叶斯GaussianNB 2.探索贝叶斯:高斯朴素贝叶斯擅长的数据集 3.探索贝叶斯: ...

  9. 基于sklearn的朴素贝叶斯_sklearn 朴素贝叶斯

    朴素贝叶斯是基于贝叶斯理论的一种监督学习算法,『朴素』意思是假设所有特征两两相互独立,给出类别y和一组依赖特征[x1..xn],根据贝叶斯理论,他们有如下的关系. P(y|x1,...xn)=P(y) ...

  10. 监督学习 | 朴素贝叶斯之Sklearn实现

    文章目录 1. Sklearn 实现朴素贝叶斯 1.1 数据导入 1.2 数据预处理 1.3 拆分训练集和测试集 1.4 Bag of Words 1.4.1 Sklearn 实现 Bag of Wo ...

最新文章

  1. 什么是CUDA编程 统一计算架构
  2. 白话JAVA守护线程
  3. java 环境变量的涵义
  4. python3 uuid模块
  5. C99 calloc、malloc和realloc区别
  6. 2021云上架构与运维峰会将于12月4日在上海举办,五大精彩看点不容错过
  7. wget使用tsocks
  8. mysql绿色版安装
  9. c语言for循环的省略写法,C语言两种for循环写法分析
  10. Dubbo详细介绍与安装使用过程
  11. python的sorted排序具体解释
  12. postgresql客户端代码上传中文数据到服务器
  13. M文件打包成jar包详解
  14. 使用MetaHuman Creator 塑造你心中的人物
  15. 微信注册验证成功之后不跳转_微信小号怎么申请(绑定了微信的手机号怎么注册新的微信)...
  16. 3dmax 2014加载panda3d插件失败
  17. jQery 日历 带农历显示
  18. C/C++实现学生成绩管理系统
  19. 农村小学计算机教育论文,浅谈小学信息技术教学
  20. 三星G9006W 6.0 root

热门文章

  1. 网络应用之JavaScript
  2. oracle数据库修改pga,18.1.2 修改PGA
  3. 语音识别开发---基于科大讯飞开放平台
  4. [导入]雨音唱片-《音乐诗画 4CD》四季系列 320k/mp3(亲传)
  5. Python-CSP 201903-1 小中大
  6. 安卓10 来电流程梳理
  7. html5绘制图形幸运大转盘,微信小程序利用canvas 绘制幸运大转盘功能
  8. DeepLearning | 图卷积神经网络(GCN)解析(论文、算法、代码)
  9. 【SIGN】函数使用技巧
  10. 怎么把录音变成文字?