認識高斯朴素貝葉斯
class sklearn.naive_bayes.GaussianNB (priors=None, var_smoothing=1e-09)
如果Xi是連續值,通常Xi的先驗概率為高斯分布(也就是正態分布),即在樣本類別Ck中,Xi的值符合正態分布。以此來估計每個特征下每個類別上的條件概率。對於每個特征下的取值,高斯朴素貝葉斯有如下公式:
prior
可輸入任何類數組結構,形狀為(n_classes,)
表示類的先驗概率。如果指定,則不根據數據調整先驗,如果不指定,則自行根據數據計算先驗概率P(Y)。
var_smoothing
浮點數,可不填(默認值= 1e-9)
在估計方差時,為了追求估計的穩定性,將所有特征的方差中最⼤大的方差以某個比例添加到估計的方差中。這個比例,由var_smoothing參數控制。
但在實例化的時候,不需要對高斯朴素貝葉斯類輸入任何參數,調用的接口也全部是sklearn中比較標准的一些搭配,可以說是一個非常輕量量級的類,操作非常容易。但過於簡單也意味着貝葉斯沒有太多的參數可以調整,因此貝葉斯算法的成長空間並不是太大,如果貝葉斯算法的效果不是太理想,一般都會考慮換模型。
無論如何,先來進行一次預測試吧:
#高斯朴素貝葉斯
'''手寫數字識別,數據是標記過的手寫數字的圖片,
即采集足夠多的手寫樣本,選擇合適模型,進行模型訓練,
最后驗證手寫識別程序的正確性'''
#導入需要的庫和數據
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.naive_bayes import GaussianNB
from sklearn.datasets import load_digits #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)
#把數據所代表的圖片顯示出來
images_and_labels = list(zip(digits.images,digits.target))
plt.figure(figsize=(4,3.5),dpi=100) #寬高,單位是inches, 分辨率
for index, (image,label) in enumerate(images_and_labels[:12]):
plt.subplot(3,4,index+1) #行數,列數(從1開始),第幾張圖(按行數)
plt.axis("off") #關閉坐標軸
plt.imshow(image,cmap=plt.cm.gray_r,interpolation="nearest")
# cmap設置色圖到灰色 interpolation 像素間顏色連接方法
plt.title("Digit: %i" % label, fontsize=6)
'''圖片數據一般使用像素點作為特征,
由於圖片的特殊性,相鄰像素點間的數值(RGB三通道色)往往是接近的,
故可以采用矩陣變換的方法壓縮矩陣,得到相對較少的特征數
數據總共包含1797張圖片,每張圖片的尺寸是8×8
像素大小,共有十個分類(0-9),每個分類約180個樣本.
所有的圖片數據保存在digits.image里,
數據分析的時候需要轉換成單一表格,即行為樣本列為特征(類似的還有文檔詞矩陣),
此案例中這個表格已經在digits.data里,可以通過digits.data.shape查看數據格式'''
print("shape of raw image data: {0}".format(digits.images.shape))
print("shape of data: {0}".format(digits.data.shape))
shape of raw image data: (1797, 8, 8)
shape of data: (1797, 64)
#建模,探索建模結果
gnb = GaussianNB().fit(Xtrain,Ytrain)
#查看分數
acc_score = gnb.score(Xtest,Ytest)
acc_score
0.8592592592592593
1
#查看預測結果
Y_pred = gnb.predict(Xtest)
Y_pred
array([6, 1, 3, 0, 4, 5, 0, 8, 3, 8, 6, 8, 7, 8, 8, 8, 5, 9, 5, 6, 5, 4,
7, 4, 8, 2, 7, 2, 8, 9, 2, 8, 3, 6, 0, 3, 8, 8, 1, 5, 2, 8, 8, 9,
2, 2, 0, 7, 3, 6, 7, 2, 8, 0, 5, 4, 1, 9, 4, 0, 5, 8, 9, 1, 7, 8,
7, 5, 8, 2, 4, 4, 8, 2, 6, 1, 2, 1, 7, 8, 8, 5, 9, 4, 3, 6, 9, 7,
4, 2, 4, 8, 0, 5, 7, 7, 7, 4, 7, 8, 8, 7, 0, 7, 2, 1, 9, 9, 8, 7,
1, 5, 1, 8, 0, 4, 8, 9, 5, 6, 4, 8, 3, 8, 0, 6, 8, 6, 7, 6, 1, 8,
5, 0, 8, 2, 1, 8, 8, 6, 6, 0, 2, 4, 7, 8, 9, 5, 9, 4, 7, 8, 8, 6,
7, 0, 8, 4, 7, 2, 2, 6, 4, 4, 1, 0, 3, 4, 3, 8, 7, 0, 6, 9, 7, 5,
5, 3, 6, 1, 6, 6, 2, 3, 8, 2, 7, 3, 1, 1, 6, 8, 8, 8, 7, 7, 2, 5,
0, 0, 8, 6, 6, 7, 6, 0, 7, 5, 5, 8, 4, 6, 5, 1, 5, 1, 9, 6, 8, 8,
8, 2, 4, 8, 6, 5, 9, 9, 3, 1, 9, 1, 3, 3, 5, 5, 7, 7, 4, 0, 9, 0,
9, 9, 6, 4, 3, 4, 8, 1, 0, 2, 9, 7, 6, 8, 8, 0, 6, 0, 1, 7, 1, 9,
5, 4, 6, 8, 1, 5, 7, 7, 5, 1, 0, 0, 9, 3, 9, 1, 6, 3, 7, 2, 7, 1,
9, 9, 8, 3, 3, 5, 7, 7, 7, 3, 9, 5, 0, 7, 5, 5, 1, 4, 9, 2, 0, 6,
3, 0, 8, 7, 2, 8, 1, 6, 4, 1, 2, 5, 7, 1, 4, 9, 5, 4, 2, 3, 5, 9,
8, 0, 0, 0, 0, 4, 2, 0, 6, 6, 8, 7, 1, 1, 8, 1, 1, 7, 8, 7, 8, 3,
1, 4, 6, 1, 8, 1, 6, 6, 7, 2, 8, 5, 3, 2, 1, 8, 7, 8, 5, 1, 7, 2,
1, 1, 7, 8, 9, 5, 0, 4, 7, 8, 8, 9, 5, 5, 8, 5, 5, 8, 1, 0, 4, 3,
8, 2, 8, 5, 7, 6, 9, 9, 5, 8, 9, 9, 1, 8, 6, 4, 3, 3, 3, 3, 0, 8,
0, 7, 7, 6, 0, 8, 9, 8, 3, 6, 6, 8, 7, 5, 8, 4, 5, 8, 6, 7, 6, 7,
7, 8, 0, 8, 2, 2, 0, 5, 7, 3, 0, 2, 8, 2, 0, 2, 3, 6, 8, 1, 7, 5,
7, 1, 7, 7, 2, 7, 5, 2, 6, 5, 8, 0, 0, 8, 1, 3, 7, 6, 1, 5, 6, 2,
0, 1, 5, 7, 8, 0, 3, 5, 0, 7, 5, 4, 4, 1, 5, 9, 5, 3, 7, 1, 7, 3,
5, 8, 5, 8, 5, 6, 1, 6, 7, 4, 3, 7, 0, 5, 4, 9, 3, 3, 6, 3, 5, 2,
9, 8, 9, 3, 9, 7, 3, 4, 9, 4, 3, 1])
#查看預測的概率結果
prob = gnb.predict_proba(Xtest) #每⼀列對應⼀個標簽下的概率
prob
array([[0.00000000e+000, 4.69391744e-052, 1.74871280e-098, ...,
0.00000000e+000, 4.19588993e-033, 1.51751459e-119],
[0.00000000e+000, 1.00000000e+000, 9.26742456e-013, ...,
0.00000000e+000, 0.00000000e+000, 0.00000000e+000],
[0.00000000e+000, 0.00000000e+000, 3.73608152e-026, ...,
0.00000000e+000, 1.29541754e-039, 5.54684869e-077],
...,
[0.00000000e+000, 2.43314963e-047, 4.82483668e-305, ...,
2.31612692e-008, 1.23891596e-126, 2.87896140e-257],
[0.00000000e+000, 8.26462929e-129, 4.99150558e-012, ...,
0.00000000e+000, 4.01802372e-003, 6.19000712e-013],
[0.00000000e+000, 9.99929965e-001, 1.45462767e-013, ...,
5.05856094e-005, 1.94498169e-005, 3.42317317e-042]])
prob.shape
(540, 10)
prob[1,:].sum() #每一行的和都是一
1.000000000000003
prob.sum(axis=1)
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
#使⽤混淆矩陣查看貝葉斯的分類結果
from sklearn.metrics import confusion_matrix as CM
CM(Ytest,Y_pred)
# 多分類狀況下最佳的模型評估指標是混淆矩陣和整體的准確度
array([[47, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[ 0, 46, 2, 0, 0, 0, 0, 3, 6, 2],
[ 0, 2, 35, 0, 0, 0, 1, 0, 16, 0],
[ 0, 0, 1, 40, 0, 1, 0, 3, 4, 0],
[ 0, 0, 1, 0, 39, 0, 1, 4, 0, 0],
[ 0, 0, 0, 2, 0, 58, 1, 1, 1, 0],
[ 0, 0, 1, 0, 0, 1, 49, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0],
[ 0, 3, 0, 1, 0, 0, 0, 2, 55, 0],
[ 1, 1, 0, 1, 2, 0, 0, 3, 7, 41]], dtype=int64)
探索貝葉斯:高斯朴素貝葉斯的擬合效果與運算速度
高斯朴素貝葉斯屬於分類效果不算頂尖的模型,這個算法在擬合的時候還有哪些特性呢?比如,決策樹是天生過擬合的模型,而支持向量機是不調參數的情況下就非常接近極限的模型。通過繪制高斯朴素貝葉斯的學習曲線與分類樹,隨機森林和支持向量機的學習曲線的對比,來探索高斯朴素貝葉斯算法在擬合上的性質。過去繪制學習曲線都是以算法類的某個參數的取值為橫坐標,今天來使用sklearn中自帶的繪制學習曲線的類learning_curve,在這個類
中執行交叉驗證並從中獲得不同樣本量下的訓練和測試的准確度。
#首先導入需要的模塊和庫
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
#定義繪制學習曲線的函數
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 ax
#這種學習曲線長什么樣?
estimator = GaussianNB()
plt.figure()
plot_learning_curve(estimator, "Naive Bayes", X, y,
ax=plt.gca(), ylim = [0.7, 1.05],n_jobs=4, cv=5);
#導⼊數據,定義循環
digits = load_digits()
X, y = digits.data, digits.target
X.shape
(1797, 64)
X #是一個稀疏矩陣
array([[ 0., 0., 5., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 10., 0., 0.],
[ 0., 0., 0., ..., 16., 9., 0.],
...,
[ 0., 0., 1., ..., 6., 0., 0.],
[ 0., 0., 2., ..., 12., 0., 0.],
[ 0., 0., 10., ..., 12., 1., 0.]])
title = ["Naive Bayes","DecisionTree","SVM, RBFkernel","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()
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).strftime("%M:%S:%f")))
plt.show()
Naive Bayes:00:03:134390
DecisionTree:00:01:208254
SVM, RBFkernel:00:09:041815
RandomForest:00:08:045525
Logistic:00:18:910432
幾個模型表現出的狀態非常有意思。
首先返回的結果是各個算法的運行時間。可以看到,決策樹和貝葉斯不相伯仲(如果你沒有發現這個結果,那么可以多運行幾次,你會發現貝葉斯和決策樹的運行時間逐漸變得差不多)。決策樹的運算效率隨着樣本量逐漸增大會越來越慢,但朴素貝葉斯卻可以在很少的樣本上獲得不錯的結果,因此,可以預料,隨着樣本量的逐漸增大,貝葉斯會逐漸變得比決策樹更快。朴素貝葉斯計算速度遠勝過SVM,隨機森林這樣復雜的模型,邏輯回歸的運行受到最大迭代次數的強烈影響和輸入數據的影響(邏輯回歸一般在線性數據上運行都比較快,但在這里應該是受到了稀疏矩陣的影響)。因此在運算時間上,朴素貝葉斯還是十分有優勢的。
緊接着,看一下每個算法在訓練集上的擬合。手寫數字數據集是一個較為簡單的數據集,決策樹,隨機森林,SVC和邏輯回歸都成功擬合了100%的准確率,但貝葉斯的最高訓練准確率都沒有超95%,
這也印證了朴素貝葉斯的分類效果其實不如其他分類器,貝葉斯天生學習能力比較弱。並且,隨着訓練樣本量的逐漸增大,其他模型的訓練擬合都保持在100%的水平,但貝葉斯的訓練准確率卻逐漸下降,這證明樣本量量越大,貝葉斯需要學習的東西越多,對訓練集的擬合程度也越差。反而比較少量的樣本可以讓貝葉斯有較高的訓練准確率。
再來看看過擬合問題。首先一眼看到,所有模型在樣本量量很少的時候都是出於過擬合狀態的(訓練集上表現好,測試集上表現糟糕),但隨着樣本的逐漸增多,過擬合問題都逐漸消失了,不過每個模型的處理手段不同。比較強大的分類器,比如SVM,隨機森林林和邏輯回歸,是依靠快速升高模型在測試集上的表現來減輕過擬合問題。相對的,決策樹雖然也是通過提高模型在測試集上的表現來減輕過擬合,但隨着訓練樣本的增加,模型在測試集上的表現改善卻非常緩慢。朴素貝葉斯獨樹一幟,是依賴訓練集上的准確率下降,測試集上的准確率上升來逐漸解決過擬合問題。
————————————————
版權聲明:本文為CSDN博主「Zen of Data Analysis」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/gracejpw/article/details/102335174