朴素贝叶斯
贝叶斯模型同样是流行的十大挖掘算法之一,属于有监督的学习算法,是专门用于解决分类问题的模型,该模型的数学理论并不复杂,只需要具备概率论和数理统计的部分知识,该分类器的实现思想非常简单,即通过已知类别的训练数据及计算样本先验概率,然后利用贝叶斯公式测算未知类别样本属于某个类别的后验概率,最终以最大的后验概率所对应的类别作为样本的预测值。
朴素贝叶斯模型,在对于未知类别的样本进行预测时,有几大优点:
- 首先算法在运算过程中简单而且高效
- 其次算法拥有古典概型的理论支撑分类效率稳定
- 最后算法对于缺失数据和异常数据不太敏感
同时缺点也是存在的:
- 模型的判断结果依赖于先验概率,所以分类结果存在一定的错误率
- 对于输入的自变量X要求具有相同的特征
- 模型的前提假设在实际应用中很难得满足。
由于该模型只用到数理统计中的朴素贝叶斯公式,所以在这里就不再赘述,相信大家也都有所了解朴素贝叶斯。
高斯朴素贝叶斯中的参数
GaussianNB(priors=None) # 没错,它的主要参数就这一个。
该参数用于指定因变量各类别的先验概率,默认以数据集中的类别频率作为先验概率
所以通常情况下,我们不对高斯普速被淹死,做任何参数的调整。
高斯朴素贝叶斯的使用
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix as CM
from sklearn.datasets import load_digits
digits=load_digits()
x,y=digits.data,digits.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3,random_state=10)
gnb=GaussianNB().fit(x_train,y_train)
gnb.score(x_train,y_train)
gnb.predict_proba(x_test).sum(axis=1).shape
y_pro=gnb.predict(x_test)
CM(y_test,y_pro)
模型评估指标
布里尔分数
from sklearn.metrics import brier_score_loss
brier_score_loss(y_true # 真实标签
, y_prob # 标签正概率
, pos_label=None # 填写正样本标签
)
需要注意的是布里尔分数只能用于二分类,不能用于多分类。
他返回的是一个浮点类型的数据,表示的是模型丢失数据的比例。所以越小越好。
对数似然
from sklearn.metrics import log_loss
log_loss(y_true# 真是标签结果
, y_prede # 预测结果,predict_proba返回的值,不是predict返回的值
)
返回的是损失值,因此对数自然函数的取值越小,证明概率估计越准确。
高斯朴素贝叶斯对不同数据集的效果
from sklearn.naive_bayes import GaussianNB
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_moons, make_circles, make_classification
######生成三种数据集######
# 二分类数据集
X, y = make_classification(n_samples=100, #生成100个样本
n_features=2,#有两个特征
n_redundant=0, #添加冗余特征0个
n_informative=2, #包含信息的特征是2个
random_state=1,#随机模式1
n_clusters_per_class=1 #每个簇内包含的标签类别有1个
)
rng = np.random.RandomState(2) #生成一种随机模式
X += 2 * rng.uniform(size=X.shape) #加减0~1之间的随机数
linearly_separable = (X, y) #生成了新的X,依然可以画散点图来观察一下特征的分布
#plt.scatter(X[:,0],X[:,1])
#用make_moons创建月亮型数据,make_circles创建环形数据,并将三组数据打包起来放在列表datasets中
moons=make_moons(noise=0.3, random_state=0)
circles=make_circles(noise=0.2, factor=0.5, random_state=1)
datasets = [moons,circles,linearly_separable]
figure = plt.figure(figsize=(6, 9))
i=1
#设置用来安排图像显示位置的全局变量i i = 1
#开始迭代数据,对datasets中的数据进行for循环
for ds_index, ds in enumerate(datasets):
X, y = ds
# 对数据进行标准化处理
X = StandardScaler().fit_transform(X)
#划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4,
random_state=42)
#定数据范围,以便后续进行画图背景的确定
#注意X[:,0]指横坐标,X[:,1]指纵坐标
x1_min, x1_max = X[:, 0].min() - .5, X[:, 0].max() + .5
x2_min, x2_max = X[:, 1].min() - .5, X[:, 1].max() + .5
#使画板上每个点组成坐标的形式(没间隔0.2取一个),array1表示横坐标,array2表示纵坐标
array1,array2 = np.meshgrid(np.arange(x1_min, x1_max, 0.2), np.arange(x2_min, x2_max, 0.2))
# 颜色列表
cm_bright = ListedColormap(['#FF0000', '#0000FF'])
########## 原始数据的现实 #########
# 用画板上六个图片位置(3,2)的第i个
ax = plt.subplot(len(datasets), 2, i)
# 便签添加
if ds_index == 0:
ax.set_title("Input data")
#画出训练数据集散点图
ax.scatter(X_train[:, 0],#横坐标
X_train[:, 1],#纵坐标
c=y_train,#意思是根据y_train标签从cm_bright颜色列表中取出对应的颜色,也就是说相同的标签有相同的颜色。
cmap = cm_bright, #颜色列表
edgecolors = 'k'#生成散点图,每一个点边缘的颜色
)
#画出测试数据集的散点图,其中比训练集多出alpha = 0.4参数,以分辨训练测试集
ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test,cmap = cm_bright, alpha = 0.4, edgecolors = 'k')
#显示的坐标范围
ax.set_xlim(array1.min(), array1.max())
ax.set_ylim(array2.min(), array2.max())
#不显示坐标值
ax.set_xticks(())
ax.set_yticks(())
#i+1显示在下一个子图版上画图
i += 1
####### 经过决策的数据显示 #######
ax = plt.subplot(len(datasets), 2, i)
#实例化训练模型
gnd = GaussianNB().fit(X_train, y_train)
score = gnd.score(X_test, y_test)
# np.c_是能够将两个数组组合起来的函数
# ravel()能够将一个多维数组转换成一维数组
#通过对画板上每一个点的预测值确定分类结果范围,并以此为依据通,通过不同的颜色展现出来范围
# 为了展示不同概率对应不同的颜色就不用这句代码作为contourf的z参数了Z = clf.predict(np.c_[array1.ravel(), array2.ravel()])
# 通过计算每一个结果对应的概率,并选出其中的最大值作为contourf参数
Z = gnd.predict_proba(np.c_[array1.ravel(), array2.ravel()])
Z = Z[:,0].reshape(array1.shape)
cm = plt.cm.RdBu # 自动选取颜色的实例化模型。
ax.contourf(array1#画板横坐标。
, array2#画板纵坐标
, Z# 画板每个点对应的预测值m,并据此来确定底底板的颜色。
, cmap=cm#颜颜色选取的模型,由于Z的值只有两个,也可以写出一个颜色列表,指定相应颜色,不让其自动生成
, alpha=0.8
)
#和原始数据集一样,画出每个训练集和测试集的散点图
ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright, edgecolors = 'k')
ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, edgecolors = 'k', alpha = 0.4)
ax.set_xlim(array1.min(), array1.max())
ax.set_ylim(array2.min(), array2.max())
ax.set_xticks(())
ax.set_yticks(())
if ds_index == 0:
ax.set_title("GaussianNB")
#在右下角添加模型的分数
ax.text(array1.max() - .3, array2.min() + .3, ('{:.1f}%'.format(score * 100)),
size = 15, horizontalalignment = 'right')
i += 1
#自动调整子画板与子画板之间的的距离
plt.tight_layout()
plt.show()
可以看出高斯朴素这些线性的数据有着非常好的效果,但是对于非线性的数据的结果并不是特别的理想
不同样本量对于高斯朴素贝叶斯的影响
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression as LR
from sklearn.model_selection import learning_curve
from sklearn.model_selection import ShuffleSplit
import time
def plot_learning_curve(estimator,title,x,y,ax,ylim=None,cv=None,n_jobs=None):
train_size,train_scores,test_scores=learning_curve(estimator # 分类器
,x,y# 数据
,cv=cv # 交叉验证的模式
,n_jobs=n_jobs)
# train_size 为每次训练和测试集划分后,在训练集上的样本数量,会自动选取
# train_scores为(5,50)5表示划分了5次数据,50代表每次划分训练集50次交叉验证对应的分数,所以要取均值
# test_scores为(5,50)5表示划分了5次数据,50代表每次划分测试集50次交叉验证对应的分数,所以要取均值
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_size,np.mean(train_scores,axis=1),"o-",label="Training scores",color="red")
ax.plot(train_size, np.mean(test_scores, axis=1), "o-", label="Training scores", color="green")
ax.legend(loc="lower right")
title_list=["GaussianNB","LR","RandomForestClassifier","SVC"]
model_list=[GaussianNB()
,LR(C=1,solver="lbfgs",max_iter=3000,multi_class="auto")
,RandomForestClassifier(n_estimators=20)
,SVC(kernel="rbf",gamma=0.001)]
cv=ShuffleSplit(n_splits=50 # 将数据分成50份,验证次数
,test_size=0.2 # 将20%作为测试集
,random_state=10
)
digits=load_digits()
x=pd.DataFrame(digits.data)
y=pd.Series(digits.target)
fig=plt.figure(figsize=(20,4))
for i in range(0,4):
start=time.time()
ax=fig.add_subplot(1,4,i+1)
plot_learning_curve(model_list[i],title_list[i],x,y,ax,[0.7,1.05],cv,1)
end=time.time()
print(title_list[i])
print(end-start)
plt.tight_layout()
plt.show()
GaussianNB
2.445056200027466
LR
19.8220853805542
RandomForestClassifier
12.856705665588379
SVC
26.9399311542511
通过这段代码也能够非常明显的看出,高斯朴素贝叶斯和其他算法之间的优劣,对于其他算法来说,在模型过拟合的时候,可以通过大量的数据对通过对于模型的提升,使测试集的分数不断上升而达到比较好的效果,但是对于高斯朴素贝叶斯来说,随着样本数据的增大,虽然过拟合的程度降低,但是测试训练及的分数也随之降低,模型的效果也相对没有其他模型那么好。但是对于它的优点来说,我们可以直观的发现,它使用的时间是非常短的效率是非常高的。