在哪給人做網(wǎng)站企業(yè)如何做網(wǎng)站
目錄
sklearn中的貝葉斯分類器
前言
1 分類器介紹
2?高斯樸素貝葉斯GaussianNB
2.1 認(rèn)識高斯樸素貝葉斯
2.2?高斯樸素貝葉斯建模案例
2.3?高斯樸素貝葉斯擅長的數(shù)據(jù)集
2.3.1 三種數(shù)據(jù)集介紹
2.3.2 構(gòu)建三種數(shù)據(jù)
2.3.3 數(shù)據(jù)標(biāo)準(zhǔn)化
2.3.4 樸素貝葉斯處理數(shù)據(jù)
2.4?高斯樸素貝葉斯的擬合效果與運算速度
2.4.1 交叉驗證的概念
2.4.2?ShuffleSplit和learning_curve
2.4.3 交叉驗證分析
3?概率模型的評估指標(biāo)
3.1 前言
3.2?布里爾分?jǐn)?shù)Brier Score
3.3?對數(shù)似然函數(shù)Log Loss
3.4?可靠性曲線 reliability curve?
3.4.1?基礎(chǔ)知識
3.4.2 模型評估
1 樸素貝葉斯評估
2 其它模型
3.5?預(yù)測概率的直方圖
3.6?校準(zhǔn)可靠性曲線
3.6.1 基礎(chǔ)知識
3.6.2 分析貝葉斯模型
3.6.3 SVC校準(zhǔn)效果
4?其它貝葉斯
4.1?多項式樸素貝葉斯MultinomialNB
1 如何判定數(shù)據(jù)符合多項式樸素貝葉斯
2?MultinomialNB語法格式
3 代碼實現(xiàn)
1 基礎(chǔ)知識
2 連續(xù)型數(shù)據(jù)處理
2 分類型數(shù)據(jù)
4.2 伯努利貝葉斯
1 BernoulliNB語法格式
2 代碼例子
4.3? 類別貝葉斯CategoricalNB
1?CategoricalNB語法格式
2 代碼例子
4.4?貝葉斯的樣本不平衡問題
4.5 補集貝葉斯
1?ComplementNB語法格式
2 代碼例子
sklearn中的貝葉斯分類器
前言
sklearn下各種樸素貝葉斯的分類器的原理可看sklearn之各類樸素貝葉斯原理
1 分類器介紹
Sklearn基于數(shù)據(jù)分布以及這些分布上的概率估計的改進,為我們提供了四個樸素貝葉斯的分類器。
類 | 含義 |
naive_bayes.BernoulliNB | 伯努利分布下的樸素貝葉斯 |
naive_bayes.GaussianNB | 高斯分布下的樸素貝葉斯 |
naive_bayes.MultinomialNB | 多項式分布下的樸素貝葉斯 |
naive_bayes.ComplementNB | 補集樸素貝葉斯 |
naive_bayes.CategoricalNB | 類別貝葉斯 |
linear_model.BayesianRidge | 貝葉斯嶺回歸,在參數(shù)估計過程中使用貝葉斯回歸技術(shù)來包括正則化參數(shù) |
貝葉斯有以下特點
- 貝葉斯是從概率角度進行估計,不需要太多的樣本量,極端情況下甚至我們可以使用1%的數(shù)據(jù)作為訓(xùn)練集,依然可以得到很好的擬合效果。當(dāng)然,如果樣本量少于特征數(shù)目,貝葉斯的效果就會被削弱。
- 與SVM和隨機森林相比,樸素貝葉斯運行速度更快,因為求解
本質(zhì)是在每個特征上單獨對概率進行計算,然后再求乘積,所以每個特征上的計算可以是獨立并且并行的
- 貝葉斯的運行效果不是那么好,貝葉斯模型預(yù)測結(jié)果也不是總指向真正的分類結(jié)果
2?高斯樸素貝葉斯GaussianNB
2.1 認(rèn)識高斯樸素貝葉斯
class sklearn.naive_bayes.GaussianNB(*, priors=None, var_smoothing=1e-09)
參數(shù)說明:
參數(shù) | 說明 |
---|---|
priors | array-like of shape (n_classes,) 類別的先驗概率。一經(jīng)指定,不會根據(jù)數(shù)據(jù)進行調(diào)整。 |
var_smoothing | float, default=1e-9 所有特征的最大方差部分,添加到方差中用于提高計算穩(wěn)定性。 |
屬性說明:
屬性 | 說明 |
---|---|
class_count_ | ndarray of shape (n_classes,) 每個類別中保留的訓(xùn)練樣本數(shù)量。 |
class_prior_ | ndarray of shape (n_classes,) 每個類別的概率。 |
classes_ | ndarray of shape (n_classes,) 分類器已知的類別標(biāo)簽 |
epsilon_ | float 方差的絕對相加值 |
sigma_ | ndarray of shape (n_classes, n_features) 每個類中每個特征的方差 |
theta_ | ndarray of shape (n_classes, n_features) 每個類中每個特征的均值 |
方法說明:
方法 | 說明 |
---|---|
fit (X, y[, sample_weight]) | 根據(jù)X,y擬合高斯樸素貝葉斯 |
get_params ([deep]) | 獲取這個估計器的參數(shù) |
partial_fit (X, y[, classes, sample_weight]) | 對一批樣本進行增量擬合 |
predict (X) | 對測試向量X進行分類。 |
predict_log_proba (X) | 返回針對測試向量X的對數(shù)概率估計 |
predict_proba (X) | 返回針對測試向量X的概率估計 |
score (X, y[, sample_weight]) | 返回給定測試數(shù)據(jù)和標(biāo)簽上的平均準(zhǔn)確率。 |
set_params (**params) | 為這個估計器設(shè)置參數(shù) |
對X矩陣和y矩陣的要求:
參數(shù) | 說明 |
---|---|
X | array-like of shape (n_samples, n_features) 用于訓(xùn)練的向量,其中n_samples是樣本數(shù)量,n_features是特征數(shù)量。 |
y | array-like of shape (n_samples,) 目標(biāo)值。 |
2.2?高斯樸素貝葉斯建模案例
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# 導(dǎo)入數(shù)據(jù)集
digits = load_digits()X = digits.data
y = digits.target# 劃分測試集和訓(xùn)練數(shù)據(jù)集,劃分后,訓(xùn)練數(shù)據(jù)1257個樣本,測試數(shù)據(jù)集540個樣本
xtrain, xtest, ytrain, ytest = train_test_split(X, y, test_size=0.3, random_state=0)# 查看標(biāo)簽種類
print(f'種類標(biāo)簽為:\n{np.unique(ytrain)}')# 實例化模型并且訓(xùn)練模型,其中fit()過程就是在計算概率的過程
gnb = GaussianNB().fit(xtrain, ytrain)# score()接口對于我們的分類型算法,返回預(yù)測的精確性,也就是accuracy,使用測試數(shù)據(jù)集測試
acc_score = gnb.score(xtest, ytest)
print(f'預(yù)測的精確性為:{acc_score}')# 返回所有樣本對應(yīng)的類別,這里的樣本標(biāo)簽是用我們下面得到的概率中,
# 選取每一個樣本中概率最大的作為此樣本的標(biāo)簽
y_pred = gnb.predict(xtest)
print(f'貝葉斯模型對所有樣本的預(yù)測類別為:\n{y_pred}')# 查看我們的概率結(jié)果
# 可以看到,返回的結(jié)果是540*10的二維矩陣,其中應(yīng)為分類有10個,所以一共返回10列概率
# 取其中概率最大的哪一個分類作為最后的分類結(jié)果,并且每一行的概率之和是1
yprob = gnb.predict_proba(xtest)
print(f'查看樣本計算的概率結(jié)果,結(jié)果為:\n{yprob}')# 注意,ROC曲線是不能用于多分類的。多分類狀況下最佳的模型評估指標(biāo)是混淆矩陣和整體的準(zhǔn)確度
# 主對角線上的點是全部分類正確的,而我們的主對角線的數(shù)值很大,因此準(zhǔn)確率很高
from sklearn.metrics import confusion_matrix as CM
print(f'混淆矩陣為:\n{CM(ytest, y_pred)}')
知識點補充
(1)train_test_split
語法格式如下
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=None, shuffle=True, stratify=None)
- X: 表示要劃分的特征數(shù)據(jù)集。
- y: 表示相應(yīng)的標(biāo)簽。
- test_size: 測試集的大小。可以是浮點數(shù)(表示比例)或整數(shù)(表示樣本數(shù)),默認(rèn)為 0.25。
- random_state: 隨機種子,用于控制隨機數(shù)生成過程。如果設(shè)置為某個整數(shù),則每次劃分?jǐn)?shù)據(jù)集時將使用相同的隨機種子,以確保結(jié)果的可重復(fù)性。如果不設(shè)置,則每次運行時都會生成不同的隨機種子。
- shuffle: 是否在劃分?jǐn)?shù)據(jù)集之前對數(shù)據(jù)進行洗牌。默認(rèn)為 True,即洗牌。
- stratify: 可選參數(shù),用于在劃分?jǐn)?shù)據(jù)集時根據(jù)標(biāo)簽的分布來進行分層抽樣。如果指定了該參數(shù),并且標(biāo)簽是分類問題的話,將會根據(jù)標(biāo)簽的類別進行分層抽樣,確保訓(xùn)練集和測試集中各類別的樣本比例與原始數(shù)據(jù)集中的比例相同。默認(rèn)為 None,表示不進行分層抽樣。
(2) load_digits
主要的參數(shù)如下:
- data: 包含手寫數(shù)字的特征數(shù)據(jù),每一行代表一個樣本,每一列代表一個特征(像素)。
- target: 包含每個樣本對應(yīng)的標(biāo)簽(即手寫數(shù)字的真實值)。
- target_names: 包含標(biāo)簽的名稱,即手寫數(shù)字的可能取值。
- images: 包含手寫數(shù)字的圖像數(shù)據(jù),是 8x8 像素的灰度圖像。 DESCR: 數(shù)據(jù)集的描述信息,包括數(shù)據(jù)集的來源、特征的含義等。
索引
data
images
其中每個元素是8×8的矩陣
target
每個數(shù)據(jù)對應(yīng)的標(biāo)簽
target_names
所有的類別標(biāo)簽
data[1]元素為例
64維的向量
8×8的矩陣,可以大致看出數(shù)字 ‘1’ 的輪廓
用plt.imshow()可以將images可視化
該數(shù)據(jù)的類別
2.3?高斯樸素貝葉斯擅長的數(shù)據(jù)集
2.3.1 三種數(shù)據(jù)集介紹
月亮型數(shù)據(jù)(Moon-shaped data)
月亮型數(shù)據(jù)是指具有類似月亮形狀的數(shù)據(jù)分布。一般使用sklearn.datasets的make_moons方法,調(diào)入方式為:
from sklearn.datasets import make_moons
其語法格式為:
make_moons(n_samples=100, *, shuffle=True, noise=None, random_state=None)
- n_samples: 生成的樣本數(shù)量,默認(rèn)為 100。
- shuffle: 是否對數(shù)據(jù)進行洗牌,默認(rèn)為 True。如果設(shè)置為 False,則生成的數(shù)據(jù)將按順序排列。
- noise: 添加到數(shù)據(jù)集中的高斯噪聲的標(biāo)準(zhǔn)差。如果為 None,則不添加噪聲。默認(rèn)為 None。
- random_state: 隨機種子,用于控制隨機數(shù)生成過程。如果設(shè)置為某個整數(shù),則每次生成數(shù)據(jù)集時將使用相同的隨機種子,以確保結(jié)果的可重復(fù)性。如果不設(shè)置,則每次運行時都會生成不同的隨機種子。
環(huán)形數(shù)據(jù)(Ring-shaped data)
環(huán)形數(shù)據(jù)是指具有環(huán)形或圓環(huán)形狀的數(shù)據(jù)分布。數(shù)據(jù)點圍繞著一個中心點呈環(huán)狀排列。一般使用sklearn.datasets的make_circles方法,調(diào)入方式為:
from sklearn.datasets import make_circles
其語法格式為:
make_circles(n_samples=100, *, shuffle=True, noise=None, random_state=None, factor=0.8)
- n_samples:生成的樣本數(shù),默認(rèn)為 100。
- shuffle:是否打亂樣本,默認(rèn)為 True。
- noise:添加到數(shù)據(jù)中的高斯噪聲的標(biāo)準(zhǔn)差,若為 None,則表示不添加噪聲,默認(rèn)為 None。
- random_state:隨機種子,默認(rèn)為 None。
- factor:外圈與內(nèi)圈半徑之比,默認(rèn)為 0.8,取值范圍為 0 到 1,越接近 1,內(nèi)外圈之間的距離越大。
二分型數(shù)據(jù)(Bimodal data)
二分型數(shù)據(jù)在機器學(xué)習(xí)中指的是具有兩類標(biāo)簽或類別的數(shù)據(jù)集。?一般使用sklearn.datasets的make_classification方法,調(diào)入方式為:
from sklearn.datasets import make_classification
其語法格式為:
make_classification(n_samples=100, n_features=20, *, n_informative=2, n_redundant=2, n_classes=2, n_clusters_per_class=2, weights=None, flip_y=0.01, class_sep=1.0, hypercube=True, shift=0.0, scale=1.0, shuffle=True, random_state=None)
- n_samples:生成的樣本數(shù),默認(rèn)為 100。
- n_features:特征數(shù),默認(rèn)為 20。
- n_informative:具有信息性的特征數(shù),默認(rèn)為 2。
- n_redundant:冗余特征數(shù),默認(rèn)為 2。
- n_classes:類別數(shù)量,默認(rèn)為 2。
- n_clusters_per_class:每個類別中的簇數(shù)量,默認(rèn)為 2。
- weights:每個類別的樣本權(quán)重,默認(rèn)為 None。
- flip_y:在生成標(biāo)簽時翻轉(zhuǎn)(翻譯)標(biāo)簽的比例,默認(rèn)為 0.01。
- class_sep:類之間的平均距離,默認(rèn)為 1.0。
- hypercube:如果為 True,則將樣本分布在一個多維超立方體中,默認(rèn)為 True。
- shift:數(shù)據(jù)集的平移量,默認(rèn)為 0.0。
- scale:數(shù)據(jù)集的縮放比例,默認(rèn)為 1.0。
- shuffle:是否打亂樣本,默認(rèn)為 True。
- random_state:隨機種子,默認(rèn)為 None。
2.3.2 構(gòu)建三種數(shù)據(jù)
構(gòu)建月亮型數(shù)據(jù)
構(gòu)建環(huán)形數(shù)據(jù)
構(gòu)建二分型數(shù)據(jù)
由上圖可知:生成的二分型數(shù)據(jù)的兩個簇離彼此很遠,這樣不利于我們測試分類器的效果,因為這樣的數(shù)據(jù)無論什么模型都是幾乎百分百正確率,因此我們使用np生成隨機數(shù)組,通過讓已經(jīng)生成的二分型數(shù)據(jù)點加減0~1之間的隨機數(shù),使數(shù)據(jù)分布變得更散更稀疏
2.3.3 數(shù)據(jù)標(biāo)準(zhǔn)化
使用sklearn.preprocessing的StandardScaler函數(shù)來將數(shù)據(jù)標(biāo)準(zhǔn)化
- 訓(xùn)練數(shù)據(jù),采用fit_transform()函數(shù)
- 測試數(shù)據(jù),采用tansform()函數(shù)
fit_transform()函數(shù)的計算過程:計算均值/標(biāo)準(zhǔn)差,使用均值/標(biāo)準(zhǔn)差數(shù)據(jù)轉(zhuǎn)換;tansform()函數(shù)則直接使用fit_transform()函數(shù)的均值和標(biāo)準(zhǔn)差來將數(shù)據(jù)轉(zhuǎn)換
StandardScaler原理
標(biāo)準(zhǔn)差標(biāo)準(zhǔn)化(standardScale)使得經(jīng)過處理的數(shù)據(jù)符合標(biāo)準(zhǔn)正態(tài)分布,即均值為0,標(biāo)準(zhǔn)差為1,其轉(zhuǎn)化函數(shù)為:
其中μ為所有樣本數(shù)據(jù)的均值,σ為所有樣本數(shù)據(jù)的標(biāo)準(zhǔn)差
數(shù)據(jù)標(biāo)準(zhǔn)化的好處是:在實際數(shù)據(jù)中,不同特征的取值范圍可能會相差較大,這會導(dǎo)致某些特征在模型訓(xùn)練過程中對結(jié)果產(chǎn)生更大的影響。通過標(biāo)準(zhǔn)化,可以消除這種量綱差異,使得各個特征在模型訓(xùn)練中對結(jié)果的影響更加平衡。
2.3.4 樸素貝葉斯處理數(shù)據(jù)
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
from sklearn.naive_bayes import GaussianNB, MultinomialNB, BernoulliNB, ComplementNBh = .02
# 模型的名字
names = ["Multinomial", "Gaussian", "Bernoulli", "Complement"]
# 創(chuàng)建我們的模型對象
classifiers = [MultinomialNB(), GaussianNB(), BernoulliNB(), ComplementNB()]# 構(gòu)造數(shù)據(jù)
# 創(chuàng)建二分型數(shù)據(jù)集
X, y = make_classification(n_features=2, n_redundant=0, n_informative=2,random_state=1, n_clusters_per_class=1)# 處理二分型數(shù)據(jù)集,使數(shù)據(jù)更加稀疏
rng = np.random.RandomState(2) #生成一種隨機模式
X += 2 * rng.uniform(size=X.shape) #加減0~1之間的隨機數(shù)
linearly_separable = (X, y) #生成了新的X,依然可以畫散點圖來觀察一下特征的分布# 準(zhǔn)備數(shù)據(jù)集合,包含了月亮型數(shù)據(jù),環(huán)型數(shù)據(jù),二分型數(shù)據(jù)
datasets = [make_moons(noise=0.3, random_state=0),make_circles(noise=0.2, factor=0.5, random_state=1),linearly_separable]# 創(chuàng)建畫布,寬高比為6*9
figure = plt.figure(figsize=(6, 9))
#設(shè)置用來安排圖像顯示位置的全局變量i
i = 1for ds_index, ds in enumerate(datasets):# ——————————————第一步:對測試集和訓(xùn)練集進行可視化——————————————X, y = ds# 對X中的數(shù)據(jù)進行標(biāo)準(zhǔn)化X = StandardScaler().fit_transform(X)# 區(qū)分測試集和訓(xùn)練集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.4, random_state=42)# 找出數(shù)據(jù)集中兩個特征的最大值和最小值,讓最大值+0.5,最小值-0.5,創(chuàng)造一個比兩個特征的區(qū)間本身更大一點的區(qū)間x1_min, x1_max = X[:, 0].min() - .5, X[:, 0].max() + .5x2_min, x2_max = X[:, 1].min() - .5, X[:, 1].max() + .5# 函數(shù)meshgrid用以生成網(wǎng)格數(shù)據(jù);函數(shù)np.arange在給定的兩個數(shù)之間返回均勻間隔的值,0.2為步長# 生成的網(wǎng)格數(shù)據(jù),是用來繪制決策邊界的,因為繪制決策邊界的函數(shù)contourf要求輸入的兩個特征都必須是二維的array1, array2 = np.meshgrid(np.arange(x1_min, x1_max, 0.2),np.arange(x2_min, x2_max, 0.2))# 創(chuàng)建一種顏色映射(colormap),值較大則顯示藍色,值較小則顯示紅色,中間值為白色cm = plt.cm.RdBu# 用ListedColormap為畫布創(chuàng)建顏色,#FF0000正紅,#0000FF正藍cm_bright = ListedColormap(['#FF0000', '#0000FF'])# 在畫布上加上一個子圖,數(shù)據(jù)為len(datasets)行,2列,放在位置i上ax = plt.subplot(len(datasets), 2, i)# 只需要在第一個坐標(biāo)系上有標(biāo)題,因此設(shè)定if ds_index==0這個條件if ds_index == 0:ax.set_title("Input data")# 將數(shù)據(jù)集的分布放到我們的坐標(biāo)系上# 使用cm_bright畫布,其中類別為0是正紅,類別為1是正藍# 放訓(xùn)練集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, alpha=0.6, edgecolors='k')# 為圖設(shè)置坐標(biāo)軸的最大值和最小值ax.set_xlim(array1.min(), array1.max())ax.set_ylim(array2.min(), array2.max())# 設(shè)置沒有坐標(biāo)軸ax.set_xticks(())ax.set_yticks(())# 每次循環(huán)之后,改變i的取值讓圖每次位列不同的位置i += 1# ——————————————第二步:從這里開始是貝葉斯模型,對貝葉斯模型處理的數(shù)據(jù)可視化——————————————# 在畫布上加上一個子圖,數(shù)據(jù)為len(datasets)行,2列,放在位置i上# 這里的i取值分別為2,4,6ax = plt.subplot(len(datasets), 2, i)# 高斯樸素貝葉斯的建模過程:fit訓(xùn)練 → score接口得到預(yù)測的準(zhǔn)確率clf = GaussianNB().fit(X_train, y_train)score = clf.score(X_test, y_test)# 繪制決策邊界,為此,我們將為網(wǎng)格中的每個點指定一種顏色[x1_min,x1_max] x [x2_min,x2_max]# ravel()能夠?qū)⒁粋€多維數(shù)組轉(zhuǎn)換成一維數(shù)組,np.c_是能夠?qū)蓚€數(shù)組組合起來的函數(shù)# 使用ravel()和np.c_為網(wǎng)格中每個點指定一種顏色# 使用高斯樸素貝葉斯的predict_proba,返回每一個輸入的數(shù)據(jù)點所對應(yīng)的標(biāo)簽類概率,[:, 1]代表只取標(biāo)簽類為1的概率Z = clf.predict_proba(np.c_[array1.ravel(), array2.ravel()])[:, 1]# 將返回的類概率作為數(shù)據(jù),放到contourf里面繪制去繪制輪廓# 由于取了類別1的類概率,當(dāng)類概率越高時,代表類1,則顯示正藍;類概率越低時,代表類0,則顯示正紅。與圖中的訓(xùn)練集和測試集的顏色相對應(yīng)Z = Z.reshape(array1.shape)ax.contourf(array1, array2, Z, cmap=cm, alpha=.8)# 同理,由于i+1,在新位置的圖上也要放置測試集和訓(xùn)練集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.6)# 為圖設(shè)置坐標(biāo)軸的最大值和最小值ax.set_xlim(array1.min(), array1.max())ax.set_ylim(array2.min(), array2.max())# 設(shè)置沒有坐標(biāo)軸ax.set_xticks(())ax.set_yticks(())# 只需要在第一個坐標(biāo)系上有標(biāo)題,因此設(shè)定if ds_index==0這個條件if ds_index == 0:ax.set_title("Gaussian Bayes")# (array1.max() - .3, array2.min() + .3)位置坐標(biāo)# ('{:.1f}%'.format(score * 100)將其轉(zhuǎn)換為百分比# horizontalalignment='right'右對齊方式ax.text(array1.max() - .3, array2.min() + .3, ('{:.1f}%'.format(score * 100)),size=15, horizontalalignment='right')i += 1
# 對當(dāng)前圖像進行調(diào)整,使得子圖參數(shù)自動適應(yīng)圖像區(qū)域,避免了子圖之間或子圖與標(biāo)簽之間的重疊。
plt.tight_layout()
# 顯示圖片
plt.show()
其代碼結(jié)果如下:
從圖上來看,高斯貝葉斯屬于比較特殊的一類分類器,其分類效果在二分?jǐn)?shù)據(jù)和月亮型數(shù)據(jù)上表現(xiàn)優(yōu)秀,有85%以上的準(zhǔn)確率,但是環(huán)形數(shù)據(jù)不太擅長。
2.4?高斯樸素貝葉斯的擬合效果與運算速度
2.4.1 交叉驗證的概念
交叉驗證(Cross-validation):一種將數(shù)據(jù)集分割成多個小部分,然后多次對模型進行訓(xùn)練和驗證的過程。通過多次進行這個過程,可以評估模型的泛化性能和穩(wěn)定性。
蒙特卡羅交叉驗證,也稱為Shuffle Split交叉驗證,是一種非常靈活的交叉驗證策略。在這種技術(shù)中,數(shù)據(jù)集被隨機劃分為訓(xùn)練集和驗證集。在這種交叉認(rèn)證方式中,自由決定要用做訓(xùn)練集和驗證集的百分比(訓(xùn)練集和驗證集的百分比加起來不一定是100%),自由決定訓(xùn)練次數(shù)。
2.4.2?ShuffleSplit和learning_curve
(1)ShuffleSplit
引入方式:
from sklearn.model_selection import ShuffleSplit
語法格式:
ShuffleSplit(n_splits=10, *, test_size=None, train_size=None, random_state=None)
- n_splits:劃分訓(xùn)練集、測試集的次數(shù),默認(rèn)為10。
- test_size:測試集的大小??梢允歉↑c數(shù)(表示測試集占總樣本的比例)或整數(shù)(表示測試集的絕對大小)。如果未提供,則默認(rèn)為 0.1。
- train_size:訓(xùn)練集的大小??梢允歉↑c數(shù)(表示訓(xùn)練集占總樣本的比例)或整數(shù)(表示訓(xùn)練集的絕對大小)。如果未提供,則默認(rèn)為 1 - test_size。
- random_state:隨機種子,用于控制隨機打亂的過程。
例子如下:
# 創(chuàng)建了一個ShuffleSplit對象
cv = ShuffleSplit(n_splits=50 # 劃分訓(xùn)練集、測試集的次數(shù),這里是50次, test_size=0.2 # 其中有20%數(shù)據(jù)作為測試集, random_state=0) # 在交叉驗證的時候進行的隨機抽樣的模式
這里例子中的蒙特卡羅交叉驗證有20%的數(shù)據(jù)作為測試集,80%作為訓(xùn)練集,并且重復(fù)的次數(shù)是50次
(2)learning_curve
2.1 語法格式
引入方式:
from sklearn.model_selection import learning_curve
語法格式:
learning_curve(estimator, X, y, *, train_sizes=None, cv=None, scoring=None, exploit_incremental_learning=False, n_jobs=None, pre_dispatch='all', verbose=0, shuffle=False, random_state=None, error_score='raise', return_times=False)
- estimator:用于擬合數(shù)據(jù)的模型對象。
- X:特征數(shù)據(jù)。
- y:目標(biāo)數(shù)據(jù)。
- train_sizes:用于生成學(xué)習(xí)曲線的訓(xùn)練集大小??梢允钦麛?shù)、浮點數(shù)或者序列。如果是整數(shù),表示用于學(xué)習(xí)曲線的每個點的訓(xùn)練集大小;如果是浮點數(shù),表示訓(xùn)練集大小相對于整個數(shù)據(jù)集的比例;如果是序列,表示具體的訓(xùn)練集大小列表。
- cv:用于交叉驗證的交叉驗證迭代器,默認(rèn)為 5 折交叉驗證。
- scoring:用于評估模型性能的指標(biāo)。默認(rèn)情況下,使用模型的 score 方法來計算。可以指定為字符串(例如 'accuracy'、'precision' 等),也可以傳入一個自定義的評估函數(shù)。
- n_jobs:并行運行的作業(yè)數(shù)量。如果設(shè)置為 -1,則使用所有可用的 CPU 核心。默認(rèn)為 None,表示不并行運行。
- shuffle:在每次迭代前對數(shù)據(jù)進行洗牌,以防止每次劃分的數(shù)據(jù)不同。默認(rèn)為 False。 random_state:隨機種子,用于控制洗牌過程的隨機性。
- error_score:當(dāng)模型在某些子集上無法擬合時,用于替代分?jǐn)?shù)的值。
- return_times:是否返回每次擬合模型的時間。默認(rèn)為 False。
- learning_curve 函數(shù)返回一個元組,其中包含訓(xùn)練樣本大小、訓(xùn)練集得分、驗證集得分等信息。
例子如下:
from sklearn.naive_bayes import GaussianNB
from sklearn.datasets import load_digits
from sklearn.model_selection import learning_curve
from sklearn.model_selection import ShuffleSplitdatas = load_digits()
X = datas.data
y = datas.target
clf = GaussianNB()
# 交叉驗證的模式
# 這里使用的訓(xùn)練集數(shù)據(jù)比例是默認(rèn)的,5次
cv = ShuffleSplit(n_splits=50 # 劃分訓(xùn)練集、測試集的次數(shù),這里是50次, test_size=0.2 # 其中有20%的數(shù)據(jù)會被作為測試集, random_state=0) # 交叉驗證所進行的隨機抽樣的模式# 默認(rèn)進行5次驗證,每次驗證會劃分50次訓(xùn)練集和測試集進行測試,其中20%作為測試集
# train_sizes 表示每次分訓(xùn)練集和測試集建模之后,訓(xùn)練集上的樣本數(shù)量
# train_scores 訓(xùn)練集上的分?jǐn)?shù) test_scores 測試集上的分?jǐn)?shù)
train_sizes, train_scores, test_scores = learning_curve(clf # 標(biāo)示分類器, X, y # 特征矩陣和標(biāo)簽, cv=cv # 設(shè)置交叉驗證的模式, n_jobs=4) # 每一次運行可以使用的線程數(shù)目,表示允許算法使用多少運算資源
learning_curve會進行5次建模,每次建模的訓(xùn)練集樣本如下:
train_scores和test_scores返回的結(jié)果是(5,50),這是因為ShuffleSplit是蒙特卡羅交叉驗證,將劃分測試集和訓(xùn)練集進行了50次,相當(dāng)于進行了50次訓(xùn)練
2,2 學(xué)習(xí)曲線常見三種情況
學(xué)習(xí)曲線能判定偏差(bias)和方差(validation)問題
第一種:當(dāng)訓(xùn)練集和測試集的誤差收斂但卻很高時,為高偏差-----欠擬合。
如左上圖所示,訓(xùn)練集準(zhǔn)確率與驗證集準(zhǔn)確率收斂,但是兩者收斂后的準(zhǔn)確率遠小于我們的期望準(zhǔn)確率(上面那條紅線),因此該模型屬于欠擬合(underfitting)問題。由于欠擬合,所以需要增加模型的復(fù)雜度,比如,增加特征、減小正則項等
第二種:當(dāng)訓(xùn)練集和測試集的誤差之間有大的差距時,為高方差----過擬合。
如右上圖所示,訓(xùn)練集準(zhǔn)確率高于期望值,驗證集則低于期望值,兩者之間有很大的間距,誤差很大,對于新的數(shù)據(jù)集模型適應(yīng)性較差,因此該模型屬于過擬合(overfitting)問題。由于過擬合,所以需要降低模型的復(fù)雜度,比如增大樣本數(shù)、減少特征數(shù)等等。
第三種:一個比較理想的學(xué)習(xí)曲線圖應(yīng)當(dāng)是:低偏差、低方差,即收斂且誤差小。
如左下圖所示,訓(xùn)練集準(zhǔn)確率與驗證集準(zhǔn)確率收斂于期望值,則為低偏差、低方差,這是比較理想的學(xué)習(xí)曲線圖
2.4.3 交叉驗證分析
# ————第一步:導(dǎo)入所需要的庫————
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# ————第二步:定義繪制學(xué)習(xí)曲線的函數(shù)————
def plot_learning_curve(estimator, title, X, y, # estimator標(biāo)示使用的分類器ax, # 選擇子圖ylim=None, # 設(shè)置縱坐標(biāo)的取值范圍cv=None, # 交叉驗證n_jobs=None # 設(shè)定索要使用的線程):# 使用learning_curve返回必要參數(shù)train_sizes, train_scores, test_scores = learning_curve(estimator, X, y, cv=cv, n_jobs=n_jobs)# 設(shè)置標(biāo)題ax.set_title(title)# 設(shè)置y坐標(biāo)的量綱形式一樣,即把多個子圖的y坐標(biāo)設(shè)置為一樣# 使用*號解包if ylim is not None:ax.set_ylim(*ylim)# 設(shè)置橫縱坐標(biāo)名字ax.set_xlabel("Training examples")ax.set_ylabel("Score")# 顯示網(wǎng)格作為背景,不是必須ax.grid()# 分別畫訓(xùn)練集和測試集的學(xué)習(xí)曲線# 橫坐標(biāo)是train_sizes,縱坐標(biāo)分別是訓(xùn)練分?jǐn)?shù)的均值和測試分?jǐn)?shù)的均值ax.plot(train_sizes, np.mean(train_scores, axis=1), 'o-', color="r", label="Training score") # 畫訓(xùn)練數(shù)據(jù)集的圖像ax.plot(train_sizes, np.mean(test_scores, axis=1), 'o-', color="g", label="Test score") # 畫出測試集圖像# 在圖上標(biāo)明一個圖例,用于說明每條曲線的文字顯示ax.legend(loc="best")# 返回子圖return ax# ————第三步:導(dǎo)入數(shù)據(jù),定義循環(huán)————
# 導(dǎo)入數(shù)據(jù)
digits = load_digits()
X, y = digits.data, digits.target
# 定義標(biāo)題
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)# ————第四步: 進入循環(huán),繪制學(xué)習(xí)曲線————
# 設(shè)置畫布一行五列,尺寸是30×6
# fig是畫布,axex是子圖對象
fig, axes = plt.subplots(1,5,figsize=(30,6))
# ind代表每次循環(huán)的索引,title代表每次循環(huán)的標(biāo)題,estimator代表每次循環(huán)的算法模型
for ind,title_,estimator in zip(range(len(title)),title,model):# 記錄當(dāng)前時間times = time()# 調(diào)用學(xué)習(xí)曲線函數(shù)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()
查看zip(range(len(title)),title,model
代碼結(jié)果如下:
對結(jié)果進行如下分析:
- 各個代碼運行時間。決策樹和貝葉斯不相伯仲(如果你沒有發(fā)現(xiàn)這個結(jié)果,可以多運行幾次,最終發(fā)現(xiàn)貝葉斯和決策樹的運行時間逐漸變得差不多)。決策樹之所以能夠運行非常快速是因為sklearn中的分類樹在選擇特征時有所“偷懶”,沒有計算全部特征的信息熵而是隨機選擇了一部分特征來進行計算,因此速度快,但決策樹的運算效率隨著樣本量逐漸增大會越來越慢;樸素貝葉斯可以在很少的樣本上獲得不錯的結(jié)果,可以預(yù)料,隨著樣本量的逐漸增大貝葉斯會逐漸變得比決策樹更快;樸素貝葉斯計算速度遠遠勝過SVM,隨機森林這樣復(fù)雜的模型,邏輯回歸的運行受到最大迭代次數(shù)的強烈影響和輸入數(shù)據(jù)的影響(邏輯回歸一般在線性數(shù)據(jù)上運行都比較快,但在這里是受到了稀疏矩陣的影響)。綜上在運算時間上,樸素貝葉斯還是十分有優(yōu)勢的。
- 訓(xùn)練集上的擬合結(jié)果。手寫數(shù)字?jǐn)?shù)據(jù)集是一個較為簡單的數(shù)據(jù)集,決策樹,森林,SVC和邏輯回歸都成功擬合了100%的準(zhǔn)確率,但貝葉斯的最高訓(xùn)練準(zhǔn)確率都沒有超過95%,說明樸素貝葉斯的分類效果不如其他分類器,貝葉斯天生學(xué)習(xí)能力比較弱;隨著訓(xùn)練樣本量的逐漸增大,其他模型的訓(xùn)練擬合都保持在100%的水平,但貝葉斯的訓(xùn)練準(zhǔn)確率卻逐漸下降,這說明樣本量越大,貝葉斯需要學(xué)習(xí)的東西越多,對訓(xùn)練集的擬合程度也越來越差。
- 過擬合問題。所有模型在樣本量很少的時候都是出于過擬合狀態(tài)的(訓(xùn)練集上表現(xiàn)好,測試集上表現(xiàn)糟糕),但隨著樣本的逐漸增多,過擬合問題都逐漸消失了。SVM,隨機森林和邏輯歸,決策樹通過提高模型在測試集上的表現(xiàn)來減輕過擬合問題,而樸素貝葉斯是依賴訓(xùn)練集上的準(zhǔn)確率下降,測試集上的準(zhǔn)確率上升來逐漸解決過擬合問題。
- 測試集上的擬合結(jié)果,即泛化誤差的大小。貝葉斯和決策樹在測試集上的表現(xiàn)遠遠不如SVM,隨機森林和邏輯回歸,VM在訓(xùn)練數(shù)據(jù)量增大到1500個樣本左右的時候,測試集上的表現(xiàn)已經(jīng)非常接近100%,隨機森林和邏輯回歸的表現(xiàn)也在95%以上,而決策樹和樸素貝葉斯還徘徊在85%左右;決策樹雖然測試結(jié)果不高,但是依然具有潛力,因為它的過擬合現(xiàn)象非常嚴(yán)重,可以通過減枝來讓決策樹的測試結(jié)果逼近訓(xùn)練結(jié)果;貝葉斯的過擬合現(xiàn)象在訓(xùn)練樣本達到1500左右的時候已經(jīng)幾乎不存在了,訓(xùn)練集上的分?jǐn)?shù)和測試集上的分?jǐn)?shù)非常接近;綜上判斷,85%左右就是貝葉斯在這個數(shù)據(jù)集上的極限了,如果我們進行調(diào)參,決策樹最后應(yīng)該可以達到90%左右的預(yù)測準(zhǔn)確率。
綜上所述,可以得出結(jié)論:
- 貝葉斯速度很快,但分類效果一般
- 如果數(shù)據(jù)十分復(fù)雜,或者是稀疏矩陣,則使用貝葉斯
3?概率模型的評估指標(biāo)
3.1 前言
混淆矩陣和精確性可以幫助我們了解貝葉斯的分類結(jié)果。然而,選擇貝葉斯進行分類,大多數(shù)時候不是為了單單追求效果,而是希望看到預(yù)測的相關(guān)概率。這種概率給出預(yù)測的可信度,所以對于概率類模型,我們希望能夠由其他的模型評估指標(biāo)來幫助我們判斷,模型在“概率預(yù)測”這項工作上,完成得如何。
3.2?布里爾分?jǐn)?shù)Brier Score
(1)布里爾分?jǐn)?shù)的概念
概率預(yù)測的準(zhǔn)確程度被稱為“校準(zhǔn)程度”,是衡量算法預(yù)測出的概率和真實結(jié)果的差異的一種方式。一種比較常用的指標(biāo)叫做布里爾分?jǐn)?shù),它被計算為是概率預(yù)測相對于測試樣本的均方誤差,表示為:
其中N是樣本數(shù)量,是樸素貝葉斯預(yù)測出的概率,
是樣本所對應(yīng)的真實結(jié)果,只能取0或1,如果事件發(fā)生則為1,否則為0。這個指標(biāo)衡量了我們的概率距離真實標(biāo)簽結(jié)果的差異,看起來非常像是均方誤差。布里爾分?jǐn)?shù)的范圍是從0到1,分?jǐn)?shù)越高則預(yù)測結(jié)果越差勁,校準(zhǔn)程度越差,因此布里爾分?jǐn)?shù)越接近0越好。
注意:布里爾分?jǐn)?shù)可以用于任何可以使用predict_proba接口調(diào)用概率的模型
(2)brier_score_loss語法格式
brier_score_loss(y_true, y_prob, sample_weight=None, pos_label=None)
- y_true:實際的標(biāo)簽,通常是一個包含了真實標(biāo)簽的數(shù)組。
- y_prob:模型對每個樣本屬于正類的預(yù)測概率,通常是一個二維數(shù)組,每行對應(yīng)一個樣本,每列對應(yīng)一個類別的預(yù)測概率。
- sample_weight:可選參數(shù),樣本權(quán)重,用于加權(quán)計算 Brier 分?jǐn)?shù)。
- pos_label:可選參數(shù),正類的標(biāo)簽值。默認(rèn)情況下,pos_label 是1。
注意:新版sklearn的brier_score_loss不再支持多分類,只能用于二分類
(3)例子
由于brier_score_loss不能用于多分類,因此使用只有二分類的乳腺癌數(shù)據(jù)進行評估,后續(xù)再思考如何解決多分類的問題
import pandas as pd
from sklearn.metrics import brier_score_loss
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer# 第一步---載入數(shù)據(jù)集---
datas =load_breast_cancer()
X = datas.data
y = datas.target# 劃分測試集和訓(xùn)練數(shù)據(jù)集
xtrain, xtest, ytrain, ytest = train_test_split(X, y, test_size=0.3, random_state=0)# 第二步---訓(xùn)練模型---
# 訓(xùn)練高斯樸素貝葉斯模型
gnb = GaussianNB().fit(xtrain, ytrain)
# 訓(xùn)練svc模型
# 我們將SVM模型的probability參數(shù)設(shè)置為True。這樣做是為了在模型預(yù)測時可以輸出樣本的概率。
# 使用了probability參數(shù)后,就可以使用predict_proba接口,進而可以使用布里爾分?jǐn)?shù)評估
svc = SVC(probability=True)
svc.fit(xtrain, ytrain)
prob_svc = svc.predict_proba(xtest)
# 訓(xùn)練邏輯歸模型
logi = LR(C=1., solver='lbfgs',max_iter=3000,multi_class="auto").fit(xtrain,ytrain)# 第三步---每個分類器每個標(biāo)簽類別下的布里爾分?jǐn)?shù)可視化---# 定義三種模型以及顏色
name = ["Bayes","Logistic","SVC"]
color = ["red","black","orange"]# 由于數(shù)據(jù)集的類別有兩種,有三種模型,因此設(shè)定DataFrame為兩行三列
df = pd.DataFrame(index=range(2),columns=name)# 通過循環(huán)記錄每個類別的布里爾分?jǐn)?shù)
for i in range(2):df.loc[i, name[0]] = brier_score_loss(ytest, gnb.predict_proba(xtest)[:, i], pos_label=i)df.loc[i, name[1]] = brier_score_loss(ytest, logi.predict_proba(xtest)[:, i], pos_label=i)df.loc[i, name[2]] = brier_score_loss(ytest, svc.predict_proba(xtest)[:, i], pos_label=i)
# 輸出DataFrame
print(f'三種模型每個類別的布里爾分?jǐn)?shù)為:\n{df}')# 類別數(shù)為橫坐標(biāo),每種模型為縱坐標(biāo)
# 分別為三種模型都畫圖
for i in range(df.shape[1]):plt.plot(range(2), df.iloc[:, i], c=color[i],label=name[i])
# 添加圖標(biāo)標(biāo)題
plt.legend(loc='best')
# 展示結(jié)果
plt.show()
可以看到:邏輯回歸的布里爾分?jǐn)?shù)是最好的,但是邏輯回歸在迭代過程中沒有收斂(這里沒有放出警告,后續(xù)可能會思考解決這個收斂問題),貝葉斯效果比SVC和邏輯回歸都差,但總的來說效果也不錯
3.3?對數(shù)似然函數(shù)Log Loss
(1)對數(shù)似然函數(shù)的概念
一種常用的概率損失衡量是對數(shù)損失(log_loss),又叫做對數(shù)似然,邏輯損失或者交叉熵?fù)p失,它是多元邏輯回歸以及一些拓展算法(比如神經(jīng)網(wǎng)絡(luò)中)使用的損失函數(shù)。它被定義為,對于一個給定的概率分類器,在預(yù)測概率為條件的情況下,真實概率發(fā)生的可能性的負(fù)對數(shù)。由于是損失,因此對數(shù)似然函數(shù)的取值越小,則證明概率估計越準(zhǔn)確,模型越理想。值得注意得是,對數(shù)損失只能用于評估分類型模型
對于一個樣本,如果樣本的真實標(biāo)簽在{0,1}中取值,并且這個樣本在類別1下的概率估計為
,則這個樣本所對應(yīng)的對數(shù)損失是:
注意:這里的 表示以 為底的自然對數(shù)。
(2)log_loss語法格式
log_loss(y_true, y_pred, eps=1e-15, normalize=True, sample_weight=None, labels=None)
- y_true:實際的標(biāo)簽,通常是一個包含了真實標(biāo)簽的數(shù)組。
- y_pred:模型對每個樣本屬于每個類別的預(yù)測概率,通常是一個二維數(shù)組,每行對應(yīng)一個樣本,每列對應(yīng)一個類別的預(yù)測概率。
- eps:用于防止概率值為 0 或 1 時的數(shù)值穩(wěn)定性,避免取對數(shù)時出現(xiàn)無窮大。默認(rèn)值為 1e-15。
- normalize:可選參數(shù),指定是否將計算的損失值歸一化。如果設(shè)置為 True(默認(rèn)),則返回的是每個樣本的平均對數(shù)損失;如果設(shè)置為 False,則返回的是每個樣本的總對數(shù)損失。
- sample_weight:可選參數(shù),樣本權(quán)重,用于加權(quán)計算對數(shù)損失。
- labels:可選參數(shù),用于指定類別標(biāo)簽。如果不提供,則函數(shù)會自動識別標(biāo)簽。
(3)例子
Log Loss可以用于多分類情況,因此使用手寫數(shù)據(jù)集來測試,當(dāng)然也可以用乳腺癌數(shù)據(jù)
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_digits
from sklearn.metrics import log_loss
from sklearn.datasets import load_breast_cancer# 第一步---載入數(shù)據(jù)集---
datas = load_digits()
X = datas.data
y = datas.target# 劃分測試集和訓(xùn)練數(shù)據(jù)集
xtrain, xtest, ytrain, ytest = train_test_split(X, y, test_size=0.3, random_state=0)# 第二步---訓(xùn)練模型---
# 訓(xùn)練高斯樸素貝葉斯模型
gnb = GaussianNB().fit(xtrain, ytrain)
# 訓(xùn)練svc模型
# 我們將SVM模型的probability參數(shù)設(shè)置為True。這樣做是為了在模型預(yù)測時可以輸出樣本的概率。
# 使用了probability參數(shù)后,就可以使用predict_proba接口,進而可以使用布里爾分?jǐn)?shù)評估
svc = SVC(probability=True)
svc.fit(xtrain, ytrain)
prob_svc = svc.predict_proba(xtest)
# 訓(xùn)練邏輯歸模型
logi = LR(C=1., solver='lbfgs',max_iter=3000,multi_class="auto").fit(xtrain,ytrain)# 第三步---求log_loss分?jǐn)?shù)---# 定義三種模型以及顏色
name = ["Bayes","Logistic","SVC"]
color = ["red","black","orange"]# 創(chuàng)建DataFrame
df = pd.DataFrame(index=['log_loss'],columns=name)# 記錄每個模型的log_loss分?jǐn)?shù)
df.loc['log_loss', name[0]] = log_loss(ytest, gnb.predict_proba(xtest))
df.loc['log_loss', name[1]] = log_loss(ytest, logi.predict_proba(xtest))
df.loc['log_loss', name[2]] = log_loss(ytest, svc.predict_proba(xtest))
# 輸出DataFrame
print(f'三種模型的log_loss分?jǐn)?shù)為:\n{df}')
結(jié)果如下:
無論是乳腺癌數(shù)據(jù)集還是手寫數(shù)據(jù)集,樸素貝葉斯的效果都是最差的。因為邏輯回歸和SVC都是以最優(yōu)化為目的來求解模型,然后進行分類的算法。而樸素貝葉斯中,卻沒有最優(yōu)化的過程。對數(shù)似然函數(shù)直接指向模型最優(yōu)化的方向,甚至就是邏輯回歸的損失函數(shù)本身,因此在邏輯回歸和SVC上表現(xiàn)得更好。
(4)什么時候使用對數(shù)似然
對數(shù)似然函數(shù)是概率類模型評估的黃金指標(biāo),往往是我們評估概率類模型的優(yōu)先選擇。但是它也有缺點:
- 它沒有界,不像布里爾分?jǐn)?shù)有上限,可以作為模型效果的參考
- 它的解釋性不如布里爾分?jǐn)?shù),很難與非技術(shù)人員去交流對數(shù)似然存在的可靠性和必要性
- 它在以最優(yōu)化為目標(biāo)的模型上明顯表現(xiàn)更好。而且,它還有一些數(shù)學(xué)上的問題,比如不能接受為0或1的概率,否則的話對數(shù)似然就會取到極限值(考慮以e為底的自然對數(shù)在取到0或1的時候的情況)
?綜上所述,有如下規(guī)則:
需求 | 優(yōu)先使用對數(shù)似然 | 優(yōu)先使用布里爾分?jǐn)?shù) |
衡量模型 | 要對比多個模型,或者衡量模型的不同變化 | 衡量單一模型的表現(xiàn) |
可解釋性 | 機器學(xué)習(xí)和深度學(xué)習(xí)之間的行家交流,學(xué)術(shù)論文 | 商業(yè)報告,老板開會,業(yè)務(wù)模型的衡量 |
最優(yōu)化指向 | 邏輯回歸,SVC | 樸素貝葉斯 |
數(shù)學(xué)問題 | 概率只能無限接近于0或1,無法取到0或1 | 概率可以取到0或1,比如樹,隨機森林 |
貝葉斯的原理簡單,根本沒有什么可用的參數(shù)。但是產(chǎn)出概率的算法有自己的調(diào)節(jié)方式,就是調(diào)節(jié)概率的校準(zhǔn)程度。校準(zhǔn)程度越高,模型對概率的預(yù)測越準(zhǔn)確,算法在做判斷時就越有自信,模型就會更穩(wěn)定。如果我們追求模型在概率預(yù)測上必須盡量貼近真實概率,那就可以使用可靠性曲線來調(diào)節(jié)概率的校準(zhǔn)程度
3.4?可靠性曲線 reliability curve?
3.4.1?基礎(chǔ)知識
(1)概念
可靠性曲線(reliability curve),又叫做概率校準(zhǔn)曲線(probability calibration curve),可靠性圖(reliability diagrams),這是一條以預(yù)測概率為橫坐標(biāo),真實標(biāo)簽為縱坐標(biāo)的曲線。我們希望預(yù)測概率和真實值越接近越好,最好兩者相等,因此一個模型/算法的概率校準(zhǔn)曲線越靠近對角線越好。校準(zhǔn)曲線因此也是我們的模型評估指標(biāo)之一。和布里爾分?jǐn)?shù)相似,概率校準(zhǔn)曲線是對于標(biāo)簽的某一類來說的,因此一類標(biāo)簽就會有一條曲線,或者我們可以使用一個多類標(biāo)簽下的平均來表示一整個模型的概率校準(zhǔn)曲線。但通常來說,曲線用于二分類的情況最多
(2)make_classification語法格式
sklearn.datasets.make_classification(n_samples=100, n_features=20, *, n_informative=2, n_redundant=2, n_repeated=0, n_classes=2, n_clusters_per_class=2, weights=None, flip_y=0.01, class_sep=1.0, hypercube=True, shift=0.0, scale=1.0, shuffle=True, random_state=None)
- n_samples:生成的樣本數(shù)量,默認(rèn)值為100
- n_features:生成的特征數(shù)量,默認(rèn)值為20
- n_informative:指定分類問題中有多少個特征是有用的(即與目標(biāo)變量相關(guān)),默認(rèn)值為2
- n_redundant:指定分類問題中有多少個特征是冗余的(即與目標(biāo)變量無關(guān),但與其他特征相關(guān)),默認(rèn)值為2
- n_repeated:指定分類問題中有多少個特征是重復(fù)的(即完全相同的特征數(shù)),默認(rèn)值為0
- n_classes:指定分類問題中有多少個類別,默認(rèn)值為2
- n_clusters_per_class:指定每個類別中有多少個簇,默認(rèn)值為2
- weights:指定各個類別的權(quán)重,默認(rèn)為None,即類是平衡的
- flip_y:隨機將標(biāo)簽翻轉(zhuǎn)的概率,默認(rèn)為0.01
- class_sep:指定類別之間的距離,默認(rèn)為1.0
- hypercube:指定是否在超立方體中生成數(shù)據(jù),默認(rèn)為True
- shift:指定生成數(shù)據(jù)的移位量,默認(rèn)為0
- scale:指定生成數(shù)據(jù)的縮放比例,默認(rèn)為1
- shuffle:指定是否對數(shù)據(jù)進行隨機洗牌,默認(rèn)為True
- random_state:隨機種子,默認(rèn)為None
返回值為:
- X:生成的樣本,array of shape [n_samples, n_features]
- y:每個樣本的類成員的整數(shù)標(biāo)簽,array of shape [n_samples]
例子如下:
from sklearn.datasets import make_classification as mc# 創(chuàng)建數(shù)據(jù)集
X, y = mc(n_samples=100000,n_features=20 #總共20個特征,n_classes=2 #標(biāo)簽為2分類,n_informative=2 #其中兩個代表較多信息,即比較重要的特征,n_redundant=10 #10個都是冗余特征,random_state=42)print(X.shape)
print(y.shape)
代碼結(jié)果如下:
(3)calibration_curve
sklearn.calibration.calibration_curve(y_true, y_prob, normalize=False, n_bins=5, strategy='uniform')
- y_true:真實標(biāo)簽的數(shù)組或序列。
- y_prob:預(yù)測標(biāo)簽為正類的概率數(shù)組或序列。
- normalize:可選參數(shù),默認(rèn)為 False。如果為 True,則將每個箱中的樣本數(shù)除以總樣本數(shù),使每個箱的值在 [0, 1] 范圍內(nèi)。
- n_bins:可選參數(shù),默認(rèn)為 5。將概率分成的箱的數(shù)量。
- strategy:可選參數(shù),默認(rèn)為 "uniform"。指定分箱策略,可選值為 "uniform" 或 "quantile"。
返回值為:
- trueproba:可靠性曲線的縱坐標(biāo),結(jié)構(gòu)為(n_bins, ),是每個箱子中少數(shù)類(Y=1)的占比
- predproba :可靠性曲線的橫坐標(biāo),結(jié)構(gòu)為(n_bins, ),是每個箱子中概率的均值
3.4.2 模型評估
1 樸素貝葉斯評估
先對樸素貝葉斯進行評估,代碼如下:
# 可靠性曲線
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_split
import pandas as pd# 第一步---創(chuàng)建數(shù)據(jù)集---
X, y = mc(n_samples=100000,n_features=20 #總共20個特征,n_classes=2 #標(biāo)簽為2分類,n_informative=2 #其中兩個代表較多信息,即比較重要的特征,n_redundant=10 #10個都是冗余特征,random_state=42)# 樸素貝葉斯訓(xùn)練集很小,效果也很好,因此僅用1%的樣本作為訓(xùn)練集
xtrain,xtest,ytrain,ytest=train_test_split(X,y,test_size=0.99,random_state=0)# 第二步---建立模型---
gnb = GaussianNB()
gnb = gnb.fit(xtrain,ytrain)
# 導(dǎo)出分類的結(jié)果
y_pred = gnb.predict(xtest)
# 導(dǎo)出類別為1的預(yù)測概率
y_prob = gnb.predict_proba(xtest)[:,1]
# 導(dǎo)出精確性
acc_score = gnb.score(xtest, ytest)# 第三步---繪制圖像---# 利用字典創(chuàng)建DateFrame,({"列的名稱":[列的值]})
# 選取一部分測試集,創(chuàng)建DateFrame,一列是真實值ytrue,一列是預(yù)測概率probability
df = pd.DataFrame({"ytrue": ytest[:500], "probability": y_prob[:500]})# 在我們的橫縱表坐標(biāo)上,概率是由順序的(由小到大),所以對數(shù)據(jù)按照預(yù)測概率進行一個排序
# 對df中的數(shù)據(jù)進行排序,按照probability進行排序
df = df.sort_values(by="probability")
# 排序后,索引會亂,要恢復(fù)索引,讓索引按順序排序
df.index = range(df.shape[0])# 緊接著我們就可以畫圖了
fig = plt.figure() # 建立畫布
ax1 = plt.subplot() # 建立一個子圖
ax1.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated") # 得做一條對角線來對比呀# 以df["probability"]即預(yù)測概率為橫坐標(biāo),df["ytrue"]即真實類別為縱坐標(biāo)
ax1.plot(df["probability"], df["ytrue"], "s-", label="%s (%1.3f)" % ("Bayes", acc_score))
ax1.set_ylabel("True label")
ax1.set_xlabel("predcited probability")# 設(shè)置縱坐標(biāo)范圍
ax1.set_ylim([-0.05, 1.05])
ax1.legend()
plt.show()
代碼結(jié)果如下:
按照預(yù)測概率的順序進行排序的,而預(yù)測概率從0開始到1的過程中,真實取值不斷在0和1之間變化,而我們是繪制折線圖,因此無數(shù)個縱坐標(biāo)分布在0和1的被鏈接起來了,所以看起來如此混亂。
換成散點圖后,就可以看得很清晰了
所謂可靠性曲線的橫縱坐標(biāo):橫坐標(biāo)是預(yù)測概率,而縱坐標(biāo)是真實值,真實值應(yīng)該是概率,而不是標(biāo)簽,事實上,真實概率是不可能獲取的,因此,一個簡單的做法是,將數(shù)據(jù)進行分箱,然后規(guī)定每個箱子中真實的少數(shù)類所占的比例為這個箱上的真實概率trueproba,這個箱子中預(yù)測概率的均值為這個箱子的預(yù)測概率predproba,然后以trueproba為縱坐標(biāo),predproba為橫坐標(biāo),來繪制我們的可靠性曲線。分箱之后樣本點的特征被聚合到了一起,曲線可以變得單調(diào)且平滑
,可以通過繪制可靠性曲線的類calibration_curve來實現(xiàn)
# 可靠性曲線
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification as mc
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.calibration import calibration_curve# 第一步---創(chuàng)建數(shù)據(jù)集---
X, y = mc(n_samples=100000,n_features=20 #總共20個特征,n_classes=2 #標(biāo)簽為2分類,n_informative=2 #其中兩個代表較多信息,即比較重要的特征,n_redundant=10 #10個都是冗余特征,random_state=42)# 樸素貝葉斯訓(xùn)練集很小,效果也很好,因此僅用1%的樣本作為訓(xùn)練集
xtrain,xtest,ytrain,ytest=train_test_split(X,y,test_size=0.99,random_state=0)# 第二步---建立模型---
gnb = GaussianNB()
gnb = gnb.fit(xtrain,ytrain)
# 導(dǎo)出分類的結(jié)果
y_pred = gnb.predict(xtest)
# 導(dǎo)出類別為1的預(yù)測概率
y_prob = gnb.predict_proba(xtest)[:,1]
# 導(dǎo)出精確性
acc_score = gnb.score(xtest, ytest)# 分成10箱,ytest代表是真實標(biāo)簽,y_prob標(biāo)示返回的概率
trueproba, predproba = calibration_curve(ytest, y_prob, n_bins=10)# 第三步---繪制圖像---# 利用字典創(chuàng)建DateFrame,({"列的名稱":[列的值]})
# 選取一部分測試集,創(chuàng)建DateFrame,一列是真實值ytrue,一列是預(yù)測概率probability
df = pd.DataFrame({"ytrue": ytest[:500], "probability": y_prob[:500]})# 在我們的橫縱表坐標(biāo)上,概率是由順序的(由小到大),所以對數(shù)據(jù)按照預(yù)測概率進行一個排序
# 對df中的數(shù)據(jù)進行排序,按照probability進行排序
df = df.sort_values(by="probability")
# 排序后,索引會亂,要恢復(fù)索引,讓索引按順序排序
df.index = range(df.shape[0])# 緊接著我們就可以畫圖了
fig = plt.figure() # 建立畫布
ax1 = plt.subplot() # 建立一個子圖
ax1.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated") # 得做一條對角線來對比呀# 以df["probability"]即預(yù)測概率為橫坐標(biāo),df["ytrue"]即真實類別為縱坐標(biāo)
ax1.plot(predproba, trueproba, "s-", label="%s (%1.3f)" % ("Bayes", acc_score))
ax1.set_ylabel("True label")
ax1.set_xlabel("predcited probability")# 設(shè)置縱坐標(biāo)范圍
ax1.set_ylim([-0.05, 1.05])
ax1.legend()
plt.show()
結(jié)果如下:
那么在不同箱數(shù)的情況下會有什么變化呢,把箱數(shù)分別設(shè)置為3,10,100,查看結(jié)果,代碼如下:
# 可靠性曲線
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification as mc
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.calibration import calibration_curve# 第一步---創(chuàng)建數(shù)據(jù)集---
X, y = mc(n_samples=100000,n_features=20 #總共20個特征,n_classes=2 #標(biāo)簽為2分類,n_informative=2 #其中兩個代表較多信息,即比較重要的特征,n_redundant=10 #10個都是冗余特征,random_state=42)# 樸素貝葉斯訓(xùn)練集很小,效果也很好,因此僅用1%的樣本作為訓(xùn)練集
xtrain,xtest,ytrain,ytest=train_test_split(X,y,test_size=0.99,random_state=0)# 第二步---建立模型---
gnb = GaussianNB()
gnb = gnb.fit(xtrain,ytrain)
# 導(dǎo)出分類的結(jié)果
y_pred = gnb.predict(xtest)
# 導(dǎo)出類別為1的預(yù)測概率
y_prob = gnb.predict_proba(xtest)[:,1]
# 導(dǎo)出精確性
acc_score = gnb.score(xtest, ytest)# 第三步---繪制圖像---# 利用字典創(chuàng)建DateFrame,({"列的名稱":[列的值]})
# 選取一部分測試集,創(chuàng)建DateFrame,一列是真實值ytrue,一列是預(yù)測概率probability
df = pd.DataFrame({"ytrue": ytest[:500], "probability": y_prob[:500]})# 在我們的橫縱表坐標(biāo)上,概率是由順序的(由小到大),所以對數(shù)據(jù)按照預(yù)測概率進行一個排序
# 對df中的數(shù)據(jù)進行排序,按照probability進行排序
df = df.sort_values(by="probability")
# 排序后,索引會亂,要恢復(fù)索引,讓索引按順序排序
df.index = range(df.shape[0])# 緊接著我們就可以畫圖了
# 我們繪制出的圖像,越接近y=x這條直線,越好
fig, axes = plt.subplots(1,3,figsize=(18,4))
for ind,i in enumerate([3,10,100]):ax = axes[ind]# 畫y=x直線ax.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated")# 分箱后的真實值和預(yù)測值trueproba, predproba = calibration_curve(ytest, y_prob,n_bins=i)ax.plot(predproba, trueproba,"s-",label="n_bins = {}".format(i))ax.set_ylabel("True probability for class 1")ax.set_xlabel("Mean predcited probability")ax.set_ylim([-0.05, 1.05])ax.legend()
plt.show()
結(jié)果如下:
從上述圖可以得出以下結(jié)論:
- n_bins越大,箱子越多,概率校準(zhǔn)曲線就越精確,但是太過精確的曲線不夠平滑(即劇烈震蕩),無法和我們希望的完美概率密度曲線相比較。
- n_bins越小,箱子越少,概率校準(zhǔn)曲線就越粗糙(無法反應(yīng)真實情況),雖然靠近完美概率密度曲線,但是無法真實地展現(xiàn)模型概率預(yù)測的結(jié)果。
- 需要取適中的箱子個數(shù),讓概率校準(zhǔn)曲線是一條相對平滑,又可以反應(yīng)出模型對概率預(yù)測的趨勢的曲線。通常來說,建議先試試看箱子數(shù)等于10的情況。箱子的數(shù)目越大,所需要的樣本量也越多,否則曲線就會太過精確
?
2 其它模型
建立其它模型比較一下效果,分別為邏輯回歸,SVC,貝葉斯。代碼如下:
# 可靠性曲線
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification as mc
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.calibration import calibration_curve
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression as LR
from sklearn.metrics import brier_score_loss# 第一步---創(chuàng)建數(shù)據(jù)集---
X, y = mc(n_samples=100000,n_features=20 #總共20個特征,n_classes=2 #標(biāo)簽為2分類,n_informative=2 #其中兩個代表較多信息,即比較重要的特征,n_redundant=10 #10個都是冗余特征,random_state=42)# 樸素貝葉斯訓(xùn)練集很小,效果也很好,因此僅用1%的樣本作為訓(xùn)練集
xtrain,xtest,ytrain,ytest=train_test_split(X,y,test_size=0.99,random_state=0)# 第二步---建立模型---# 訓(xùn)練貝葉斯模型
gnb = GaussianNB()
# 訓(xùn)練svc模型
svc = SVC(probability=True)
# 訓(xùn)練邏輯歸模型
logi = LR(C=1., solver='lbfgs',max_iter=3000,multi_class="auto").fit(xtrain,ytrain)# 第三步---繪制圖像---name = ["GaussianBayes","Logistic","SVC"]
# 緊接著我們就可以畫圖了
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):# 訓(xùn)練模型clf.fit(xtrain,ytrain)# 預(yù)測標(biāo)簽y_pred = clf.predict(xtest)# 預(yù)測概率prob_pos = clf.predict_proba(xtest)[:,1]# 返回布里爾分?jǐn)?shù)clf_score = brier_score_loss(ytest, prob_pos, pos_label=y.max())# 分箱數(shù)為10trueproba, 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()
代碼結(jié)果如下:
從圖中可以看出:
- 相對來說,高斯樸素貝葉斯的結(jié)果比較糟糕
- 高斯樸素貝葉斯呈現(xiàn)和Sigmoid函數(shù)相反的形狀。對于貝葉斯,如果概率校準(zhǔn)曲線呈現(xiàn)sigmoid函數(shù)的鏡像的情況,則說明數(shù)據(jù)集中的特征不是相互條件獨立的。貝葉斯原理中的”樸素“原則:特征相互條件獨立原則被違反了(我們設(shè)定了10個冗余特征,這些特征就是噪音,他們之間不可能完全獨立),因此貝葉斯的表現(xiàn)不夠好。
3.5?預(yù)測概率的直方圖
(1)基礎(chǔ)知識
可以通過繪制直方圖來查看模型的預(yù)測概率的分布。直方圖是以樣本的預(yù)測概率分箱后的結(jié)果為橫坐標(biāo),每個箱中的樣本數(shù)量為縱坐標(biāo)的一個圖像。
- 注意:這里的分箱和在可靠性曲線中的分箱不同,這里的分箱是將預(yù)測概率均勻分為一個個的區(qū)間
?
(2)matplotlib.pyplot.hist參數(shù)詳解
ax.hist(x, bins=None, range=None, density=False, weights=None,cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None,label=None, stacked=False, *, data=None, **kwargs)
- x: 繪制直方圖所需的一維數(shù)組或序列。
- bins: 直方圖的條形數(shù)目,默認(rèn)值為 10。
- range: 直方圖的取值范圍,默認(rèn)值為 None,即 (min(x), max(x))。
- density: 布爾值,默認(rèn)為False。若為True,則繪制頻率分布直方圖,若為False,則繪制頻數(shù)分布直方圖。
- weights: 每個數(shù)據(jù)點的權(quán)重,默認(rèn)值為 None。
- cumulative: 布爾值,默認(rèn)為False。若為True,當(dāng)density為False時直方圖顯示累計頻數(shù),當(dāng)density為True時直方圖顯示累計頻率。
- bottom: 數(shù)值或數(shù)組序列,默認(rèn)為None。若為數(shù)值,則直方圖的柱子相對于y=0向上/向下偏移相同的量。若為數(shù)組序列,則根據(jù)數(shù)組元素取值每根柱子偏移相應(yīng)的量。
- histtype: 直方圖類型,可選值為 'bar', 'barstacked', 'step', 'stepfilled'。'bar'是傳統(tǒng)的條形直方圖,'barstacked'是堆疊的條形直方圖,'step'是未填充的階梯直方圖,只有外邊框,'stepfilled'是有填充的階梯直方圖。
- align: 直方圖條形的對齊方式,可選值為 'left', 'mid', 'right'。
- orientation: 直方圖的方向,可選值為 'horizontal', 'vertical'。'horizontal'表示柱子水平排列,?'vertical'表示柱子垂直排列。
- rwidth: 直方圖條形寬度,浮點數(shù)或 None,默認(rèn)為 None。
- log: 是否繪制對數(shù)刻度的直方圖,默認(rèn)值為 False。
- color: 直方圖顏色。
- label: 直方圖標(biāo)簽。
- stacked: 布爾值,默認(rèn)為False。當(dāng)圖中有多個數(shù)據(jù)集時使用該參數(shù),若取值為True,則輸出數(shù)據(jù)集累計堆疊的結(jié)果,若取值為False,則多個數(shù)據(jù)集柱子并排排列。
(3)例子
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification as mc
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.calibration import calibration_curve
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression as LR
from sklearn.metrics import brier_score_loss# 第一步---創(chuàng)建數(shù)據(jù)集---
X, y = mc(n_samples=100000,n_features=20 #總共20個特征,n_classes=2 #標(biāo)簽為2分類,n_informative=2 #其中兩個代表較多信息,即比較重要的特征,n_redundant=10 #10個都是冗余特征,random_state=42)# 樸素貝葉斯訓(xùn)練集很小,效果也很好,因此僅用1%的樣本作為訓(xùn)練集
xtrain,xtest,ytrain,ytest=train_test_split(X,y,test_size=0.99,random_state=0)# 第二步---建立模型---# 訓(xùn)練貝葉斯模型
gnb = GaussianNB()
# 訓(xùn)練svc模型
svc = SVC(probability=True)
# 訓(xùn)練邏輯歸模型
logi = LR(C=1., solver='lbfgs',max_iter=3000,multi_class="auto").fit(xtrain,ytrain)# 第三步---繪制圖像---name = ["GaussianBayes","Logistic","SVC"]
# 緊接著我們就可以畫圖了
fig, ax1 = plt.subplots(figsize=(8,6))for clf, name_ in zip([gnb,logi,svc],name):# 訓(xùn)練模型clf.fit(xtrain,ytrain)# 預(yù)測標(biāo)簽y_pred = clf.predict(xtest)# 預(yù)測概率prob_pos = clf.predict_proba(xtest)[:,1]ax1.hist(prob_pos, bins=10, label=name_, histtype="step" # 設(shè)置直方圖為透明, lw=2 # 設(shè)置直方圖每個柱子描邊的粗細)# 縱坐標(biāo)為樣本數(shù)
ax1.set_ylabel("Distribution of probability")
# 樣本預(yù)測概率的均值
ax1.set_xlabel("Mean predicted probability")
# 設(shè)定x取值
ax1.set_xlim([-0.05, 1.05])
# 限制x軸刻度
ax1.set_xticks([0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])
ax1.legend(loc=9)
plt.show()
結(jié)果如下:
根據(jù)結(jié)果分析如下:
- 邏輯回歸??闯壬€,0到0.1之間有很多的樣本數(shù),這可以說明很大可能這些樣本是類別0;0.9-1之間也有很多的樣本數(shù),這可以說明很大可能這些樣本是類別1。幾乎90%以上的樣本都在0和1的附近(這些樣本可以充分預(yù)測其類別),是置信度最高的算法
- 高斯貝葉斯??此{色線,同理,高斯貝葉斯的概率分布是兩邊非常高,中間非常低,幾乎90%以上的樣本都在0和1的附近,是置信度最高的算法。但實際上,高斯貝葉斯算法太多樣本數(shù)在0和1的附近,置信度太高了,可能有一些類別1的樣本在0附近,類別0的樣本在1附近,這也是它可靠性曲線表現(xiàn)不好的原因。
- 支持向量機,當(dāng)使用了predict_proba接口后,跟上述算法同理,是置信度最高的算法
- 綜上,當(dāng)聚集在0和1附近的樣本數(shù)過多,置信度過高,其效果也不一定好
- 如果有一個算法,處于中間的樣本數(shù)很多,即中間高兩邊低,則這些樣本的類別不確定性很大,算法需要改進
注意:使用的預(yù)測概率是類別為1情況下的預(yù)測概率
3.6?校準(zhǔn)可靠性曲線
3.6.1 基礎(chǔ)知識
(1)基本介紹
等近似回歸有兩種回歸可以使用,一種是基于Platt的Sigmoid模型的參數(shù)校準(zhǔn)方法,一種是基于等滲回歸(isotoniccalibration)的非參數(shù)的校準(zhǔn)方法。概率校準(zhǔn)應(yīng)該發(fā)生在測試集上,必須是模型未曾見過的數(shù)據(jù)。在數(shù)學(xué)上,使用這兩種方式來對概率進行校準(zhǔn)的原理十分復(fù)雜,而此過程我們在sklearn中無法進行干涉,大家不必過于去深究。
(2)CalibratedClassifierCV語法格式
class sklearn.calibration.CalibratedClassifierCV(base_estimator=None, method='sigmoid', cv=None)
- base_estimator: 使用的基本分類器,默認(rèn)為 None??梢允侨魏斡?predict_proba() 接口或decision_function接口的分類器。
- method: 校準(zhǔn)概率的方法。可選值為 'sigmoid' 和 'isotonic',默認(rèn)='sigmoid'。輸入'sigmoid',使用基于Platt的Sigmoid模型來進行校準(zhǔn);輸入'isotonic',使用等滲回歸來進行校準(zhǔn)。樣本數(shù)過少(小于等于1000)時建議使用sigmoids,如果使用等滲回歸會過擬合
- cv: 用于交叉驗證的折數(shù)。默認(rèn)為 None,表示使用默認(rèn)的 5 折交叉驗證??奢斎胝麛?shù),代表指定折數(shù);可輸入已經(jīng)使用其他類建好的交叉驗證模式或生成器cv;可輸入可迭代的,已經(jīng)分割完畢的測試集和訓(xùn)練集索引數(shù)組;輸入"prefit",則假設(shè)已經(jīng)在分類器上擬合完畢數(shù)據(jù)。在這種模式下,使用者必須手動確定用來擬合分類器的數(shù)據(jù)與即將被校準(zhǔn)的數(shù)據(jù)沒有交集
?
CalibratedClassifierCV 的主要方法包括:
- fit(X, y, sample_weight=None): 訓(xùn)練模型,并對概率估計進行校準(zhǔn)。其中,X?和?y?分別為訓(xùn)練集的特征和標(biāo)簽。
- predict(X): 對測試集進行預(yù)測,并返回預(yù)測結(jié)果的類別。
- predict_proba(X): 對測試集進行預(yù)測,并返回每個類別的概率估計。
- predict_log_proba(X): 對測試集進行預(yù)測,并返回每個類別的對數(shù)概率估計。
- get_params(deep=True): 獲取模型的超參數(shù)。
- set_params(**params): 設(shè)置模型的超參數(shù)。
3.6.2 分析貝葉斯模型
這里分別使用了兩種校準(zhǔn)方式,分別為:'sigmoid' 和 'isotonic'
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification as mc
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.calibration import calibration_curve
from sklearn.linear_model import LogisticRegression as LR
from sklearn.metrics import brier_score_loss
from sklearn.calibration import CalibratedClassifierCV# 第一步---創(chuàng)建數(shù)據(jù)集---
X, y = mc(n_samples=100000,n_features=20 #總共20個特征,n_classes=2 #標(biāo)簽為2分類,n_informative=2 #其中兩個代表較多信息,即比較重要的特征,n_redundant=10 #10個都是冗余特征,random_state=42)# 樸素貝葉斯訓(xùn)練集很小,效果也很好,因此僅用1%的樣本作為訓(xùn)練集
xtrain,xtest,ytrain,ytest = train_test_split(X,y,test_size=0.99,random_state=0)# 第二步---建立模型---# 定義貝葉斯模型
gnb = GaussianNB()
# 所有模型放在models列表中,定義了兩種校準(zhǔn)方式
models = [gnb, LR(C=1., solver='lbfgs', max_iter=3000, multi_class="auto")# 定義兩種校準(zhǔn)方式, CalibratedClassifierCV(gnb, cv=2, method='isotonic'), CalibratedClassifierCV(gnb, cv=2, method='sigmoid')]# 第三步---定義畫圖函數(shù)---def plot_calib(models, name, Xtrain, Xtest, Ytrain, Ytest, n_bins=10):ax1.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated") # 畫出y=x的直線for clf, name_ in zip(models, name):clf.fit(xtrain, ytrain)y_pred = clf.predict(Xtest)prob_pos = clf.predict_proba(Xtest)[:, 1]# 返回布里爾分?jǐn)?shù)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)# 第四步---繪制圖像---
name = ["GaussianBayes", "Logistic", "Bayes+isotonic", "Bayes+sigmoid"]# 建立畫布以及子圖
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 6))
# 調(diào)用畫圖函數(shù)
plot_calib(models, name, xtrain, xtest, ytrain, ytest)
# 子圖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")
# 子圖1的一些配置
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()# 第四步---輸出準(zhǔn)確率和布里爾分?jǐn)?shù)---
print(f'貝葉斯的準(zhǔn)確率為:{gnb.score(xtest,ytest)},'f'布里爾分?jǐn)?shù)為{brier_score_loss(ytest,gnb.predict_proba(xtest)[:,1],pos_label = 1)}')
gnbisotonic = CalibratedClassifierCV(gnb, cv=2, method='isotonic').fit(xtrain,ytrain)
print(f'使用isotonic后的貝葉斯的準(zhǔn)確率為:{gnbisotonic.score(xtest,ytest)},'f'布里爾分?jǐn)?shù)為{brier_score_loss(ytest,gnbisotonic.predict_proba(xtest)[:,1],pos_label = 1)}')
結(jié)果如下:
對于曲線圖和直方圖分析結(jié)果如下:
- 從曲線圖來看,Isotonic等滲校正大大改善了曲線的形狀,幾乎讓貝葉斯的效果與邏輯回歸持平,Sigmoid校準(zhǔn)的方式也對曲線進行了稍稍的改善,不過效果不明顯
- 從直方圖來看,Isotonic校正讓高斯樸素貝葉斯的效果接近邏輯回歸,而Sigmoid校正后的結(jié)果依然和原本的高斯樸素貝葉斯更相近
- 綜上所述,當(dāng)數(shù)據(jù)的特征之間不是相互條件獨立的時候,使用Isotonic方式來校準(zhǔn)概率曲線,可以得到不錯的結(jié)果,讓模型在預(yù)測上更加謙虛
?
對于貝葉斯模型和準(zhǔn)確率和布爾分?jǐn)?shù)的分析:
- 校準(zhǔn)概率后,布里爾分?jǐn)?shù)明顯變小了,但整體的準(zhǔn)確率卻略有下降,這證明算法在校準(zhǔn)之后,盡管對概率的預(yù)測更準(zhǔn)確了,但模型的判斷力略有降低
- 這是因為,在樸素貝葉斯中,有各種各樣的假設(shè),除了“樸素”假設(shè),還有我們對概率分布的假設(shè)(比如說高斯),在這些假設(shè)下,這種概率估計其實不是那么準(zhǔn)確和嚴(yán)肅。通過校準(zhǔn),讓模型的預(yù)測概率更貼近于真實概率,本質(zhì)是在統(tǒng)計學(xué)上讓算法更加貼近我們對整體樣本狀況的估計,這樣的一種校準(zhǔn)在一組數(shù)據(jù)集上可能表現(xiàn)出讓準(zhǔn)確率上升,也可能表現(xiàn)出讓準(zhǔn)確率下降,這取決于測試集有多貼近估計的真實樣本的面貌
- 深層的可能原因是:概率校準(zhǔn)過程中的數(shù)學(xué)細節(jié)如何影響了我們的校準(zhǔn),類calibration_curve中是如何分箱,如何通過真實標(biāo)簽和預(yù)測值來生成校準(zhǔn)曲線使用的橫縱坐標(biāo),這些過程中也可能有著讓布里爾分?jǐn)?shù)和準(zhǔn)確率向兩個方向移動的過程
? - 當(dāng)兩者相悖的時候,以準(zhǔn)確率為標(biāo)準(zhǔn),但概率類模型幾乎沒有參數(shù)可以調(diào)整,概率校準(zhǔn)曲線非常好的針對概率提升模型的方法,所以仍然可以考慮使用這些方法
3.6.3 SVC校準(zhǔn)效果
使用SVCpredict_proba接口來進行處理,代碼如下:
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification as mc
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.calibration import calibration_curve
from sklearn.linear_model import LogisticRegression as LR
from sklearn.svm import SVC
from sklearn.metrics import brier_score_loss
from sklearn.calibration import CalibratedClassifierCV# 第一步---創(chuàng)建數(shù)據(jù)集---
X, y = mc(n_samples=100000,n_features=20 #總共20個特征,n_classes=2 #標(biāo)簽為2分類,n_informative=2 #其中兩個代表較多信息,即比較重要的特征,n_redundant=10 #10個都是冗余特征,random_state=42)# 僅用45%的樣本作為訓(xùn)練集
xtrain,xtest,ytrain,ytest = train_test_split(X,y,test_size=0.55,random_state=0)# 第二步---建立模型---# 定義SVC
svc = SVC(kernel = "linear",gamma=1,probability=True)
# 所有模型放在models列表中,定義了兩種校準(zhǔn)方式
models = [svc,LR(C=1., solver='lbfgs',max_iter=3000,multi_class="auto")#依然定義兩種校準(zhǔn)方式,CalibratedClassifierCV(svc, cv=2, method='isotonic'),CalibratedClassifierCV(svc, cv=2, method='sigmoid')]# 第三步---定義畫圖函數(shù)---def plot_calib(models, name, Xtrain, Xtest, Ytrain, Ytest, n_bins=10):ax1.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated") # 畫出y=x的直線for clf, name_ in zip(models, name):clf.fit(xtrain, ytrain)y_pred = clf.predict(Xtest)prob_pos = clf.predict_proba(Xtest)[:, 1]# 返回布里爾分?jǐn)?shù)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)# 第四步---繪制圖像---
name = ["SVC","Logistic","SVC+isotonic","SVC+sigmoid"]# 建立畫布以及子圖
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 6))
# 調(diào)用畫圖函數(shù)
plot_calib(models, name, xtrain, xtest, ytrain, ytest)
# 子圖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")
# 子圖1的一些配置
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()
當(dāng)使用45%的樣本作為訓(xùn)練集時,效果如下:
4?其它貝葉斯
4.1?多項式樸素貝葉斯MultinomialNB
1 如何判定數(shù)據(jù)符合多項式樸素貝葉斯
根據(jù)多項分布的概念,以詞袋模型為例,在文本分類中有如下假設(shè):
- 不考慮文本中單詞之間的次序,即認(rèn)為這兩個文本‘?Love and Peace’和‘?Peace and Love’最后建模出來對應(yīng)于同一個特征向量。不考慮文本單詞之間的次序,會導(dǎo)致文本語義丟失。
- 在類別為Y=c的文本中,每個單詞的出現(xiàn)是相互獨立。即在類別為Y=c的文本中,每次隨機試驗為隨機從詞表中抽取一個單詞,進行n次獨立重復(fù)試驗。
第2個假設(shè)只有滿足了才保證了文本的特征隨機向量滿足多項式分布,即給定類別Y=c的文本,滿足:
即滿足了上述要求,可用多項式樸素貝葉斯推導(dǎo)過程里的方法求條件概率?(一般使用詞頻法和TF-IDF表示法,詳情見詞袋模型)
2?MultinomialNB語法格式
class sklearn.naive_bayes.MultinomialNB(*, alpha=1.0, fit_prior=True, class_prior=None)
參數(shù)說明:
參數(shù) | 說明 |
---|---|
alpha | float, default=1.0 附加的(Laplace/Lidstone)平滑參數(shù)(0表示不平滑) |
fit_prior | bool, default=True 是否學(xué)習(xí)類別先驗概率。如果為False,將使用統(tǒng)一的先驗。 |
class_prior | array-like of shape (n_classes,), default=None 類別的先驗概率。一經(jīng)指定先驗概率不能隨著數(shù)據(jù)而調(diào)整。 |
屬性說明:
屬性 | 說明 |
---|---|
class_count_ | ndarray of shape (n_classes,) 擬合期間每個類別遇到的樣本數(shù)。此值由提供的樣本權(quán)重加權(quán)。 |
class_log_prior_ | ndarray of shape (n_classes, ) 每個類別的經(jīng)驗對數(shù)概率(平滑)。 |
classes_ | ndarray of shape (n_classes,) 分類器已知的類別標(biāo)簽 |
coef_ | ndarray of shape (n_classes, n_features) 用于將MultinomialNB解釋為線性模型的鏡像 feature_log_prob_ 。 |
feature_count_ | ndarray of shape (n_classes, n_features) 擬合期間每個(類別,特征)遇到的樣本數(shù)。此值由提供的樣本權(quán)重加權(quán)。 |
feature_log_prob_ | ndarray of shape (n_classes, n_features) 給定一類特征的經(jīng)驗對數(shù)概率 P(xi|y) |
intercept_ | ndarray of shape (n_classes, ) 用于將MultinomialNB解釋為線性模型的鏡像 class_log_prior_ 。 |
n_features_ | int 每個樣本的特征數(shù)量。 |
方法說明:
方法 | 說明 |
---|---|
fit (X, y[, sample_weight]) | 根據(jù)X,y擬合樸素貝葉斯分類器 |
get_params ([deep]) | 獲取這個估計器的參數(shù) |
partial_fit (X, y[, classes, sample_weight]) | 對一批樣本進行增量擬合 |
predict (X) | 對測試向量X進行分類。 |
predict_log_proba (X) | 返回針對測試向量X的對數(shù)概率估計 |
predict_proba (X) | 返回針對測試向量X的概率估計 |
score (X, y[, sample_weight]) | 返回給定測試數(shù)據(jù)和標(biāo)簽上的平均準(zhǔn)確率。 |
set_params (**params) | 為這個估計器設(shè)置參數(shù) |
對X矩陣和y矩陣的要求如下:
參數(shù) | 說明 |
---|---|
X | {array-like, sparse matrix} of shape (n_samples, n_features) 用于訓(xùn)練的向量,其中n_samples是樣本數(shù)量,n_features是特征數(shù)量。 |
y | array-like of shape (n_samples,) 目標(biāo)值。 |
3 代碼實現(xiàn)
1 基礎(chǔ)知識
(1)make_blobs語法格式
sklearn.datasets.make_blobs(n_samples=100, n_features=2, centers=3, cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)
- n_samples:生成的樣本總數(shù),默認(rèn)為100。
- n_features:每個樣本的特征數(shù),默認(rèn)為2。
- centers:要生成的聚類中心數(shù)量或者中心坐標(biāo),默認(rèn)為3。
- cluster_std:每個聚類的標(biāo)準(zhǔn)差,默認(rèn)為1.0。
- center_box:生成的聚類中心的范圍,默認(rèn)為(-10.0, 10.0)。
- shuffle:是否打亂數(shù)據(jù)順序,默認(rèn)為True。
- random_state:隨機數(shù)種子,默認(rèn)為None。
(2)KBinsDiscretizer語法格式
sklearn.preprocessing.KBinsDiscretizer(n_bins=5, encode='onehot', strategy='uniform')
參數(shù) | 含義和輸入 |
---|---|
n_bins | 每個特征要分的箱子數(shù)量,默認(rèn)為5,可以是單個整數(shù)或者數(shù)組形式(對每個特征分別指定) |
encode | 編碼方式,默認(rèn)為'onehot'(獨熱編碼)。可選值包括: 'onehot':做啞變量,返回一個稀疏矩陣,每一列是一個特征的一個類別,含有該類別的樣本為1,否則為0 'ordinal':每個特征的每個箱都被編碼為一個整數(shù),返回每一列是一個特征,每個特征下有不同整數(shù)編碼的箱的矩陣 'onehot-dense':做啞變量,返回密集矩陣 |
strategy | 分箱策略,默認(rèn)為'quantile'??蛇x值包括: 'uniform':等寬分箱,即每個特征中每個箱子的最大值之間的差為(特征.max()-特征.min())/(n_bins) 'quantile':等位分箱,即每個特征中每個箱子的樣本數(shù)量相同 'kmeans':聚類分箱,每個箱子的值到最近的一維k均值聚類的簇心的距離都相同 |
(3)MinMaxScaler語法格式
MinMaxScaler(feature_range=(0, 1), copy=True)
- feature_range:要縮放特征的范圍,默認(rèn)為(0, 1)
- copy:是否在轉(zhuǎn)換時復(fù)制輸入數(shù)據(jù),默認(rèn)為True
常用方法有:
創(chuàng)建 MinMaxScaler 對象
scaler = MinMaxScaler(feature_range=(0, 1))
fit(X, y=None):計算訓(xùn)練數(shù)據(jù) X 的最小值和最大值,用于后續(xù)的數(shù)據(jù)縮放
scaler.fit(X)
transform(X):根據(jù)之前計算的最小值和最大值來縮放數(shù)據(jù) X
X_scaled = scaler.transform(X)
fit_transform(X, y=None):相當(dāng)于先調(diào)用 fit 方法然后再調(diào)用 transform 方法
X_scaled = scaler.fit_transform(X)
inverse_transform(X):執(zhí)行反向縮放,將縮放后的數(shù)據(jù)轉(zhuǎn)換回原始范圍
X_original = scaler.inverse_transform(X_scaled)
2 連續(xù)型數(shù)據(jù)處理
sklearn中的多項式分布也可以處理連續(xù)型變量,但實際上想要處理連續(xù)型 變量,應(yīng)當(dāng)使用高斯樸素貝葉斯
# 導(dǎo)入庫
from sklearn.preprocessing import MinMaxScaler
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
from sklearn.metrics import brier_score_loss
import numpy as np# **********第一步:建立數(shù)據(jù)集**********
class_1 = 500
class_2 = 500 # 兩個類分別設(shè)置500個樣本
centers = [[0, 0], [2, 2]] # 設(shè)置數(shù)據(jù)集的中心
clusters_std = [0.5, 0.5] # 設(shè)置兩個類別的均值和方差# 使用make_blobs生成樣本,y的類別只有0和1
X, y = make_blobs(n_samples=[class_1, class_2], centers=centers, cluster_std=clusters_std, random_state=0, shuffle=False)# 劃分?jǐn)?shù)據(jù)集測試集
xtrain, xtest, ytrain, ytest = train_test_split(X, y, random_state=0, test_size=0.3)# **********第二步:歸一化,確保矩陣不帶有負(fù)數(shù)**********
mms = MinMaxScaler().fit(xtrain)
xtrain_ = mms.transform(xtrain)
xtest_ = mms.transform(xtest)# **********第三步:建立多項式樸素貝葉斯分類器**********
# 訓(xùn)練的時候使用歸一化之后的特征矩陣
mnb = MultinomialNB().fit(xtrain_, ytrain)# 獲取每一個特征的先驗概率
# 返回每一個標(biāo)簽類對應(yīng)的先驗概率
print(f'對數(shù)先驗概率矩陣為:\n{mnb.class_log_prior_}')
# 使用np.exp求出真正的概率,因為對數(shù)是以e為底
print(f'先驗概率矩陣為:\n{np.exp(mnb.class_log_prior_)}\n')# 返回每一個固定類別標(biāo)簽下的每一個特征的對數(shù)概率log(p(xi|y))
# 矩陣形狀是2*2,因為有2個特征,2個類別
print(f'對數(shù)條件概率矩陣為:\n{mnb.feature_log_prob_}')
# 使用np.exp求出真正的概率,因為對數(shù)是以e為底
print(f'條件概率矩陣為:\n{np.exp(mnb.feature_log_prob_)}\n')# 在fit時每一個標(biāo)簽類別下包含的樣本數(shù)
# 當(dāng)fit時候接口中sample_weight被設(shè)置的時候,該接口返回的值也會受到加權(quán)的影響
print(f'0類和1類的樣本數(shù)分別為:\n{mnb.class_count_}\n')# 返回預(yù)測結(jié)果
print(f'預(yù)測結(jié)果為:\n{mnb.predict(xtest_)}\n')# 返回每一個樣本在每一個標(biāo)簽下面的取值概率
print(f'標(biāo)簽的取值概率矩陣為:\n{mnb.predict_proba(xtest_)}\n')# 返回我們的準(zhǔn)確度
print(f'準(zhǔn)確度為:{mnb.score(xtest_, ytest)}\n')# 返回我們的布里爾分?jǐn)?shù)
print(f'布里爾分?jǐn)?shù)為:{brier_score_loss(ytest, mnb.predict_proba(xtest_)[:, 1], pos_label=1)}')
結(jié)果如圖所示(有些矩陣過大,只截取一部分):
由準(zhǔn)確度和布里爾分?jǐn)?shù)可知,多項式樸素貝葉斯處理連續(xù)型數(shù)據(jù)準(zhǔn)確率不高,因此考慮使用分箱法來將連續(xù)型數(shù)據(jù)轉(zhuǎn)成分類型數(shù)據(jù)
2 分類型數(shù)據(jù)
使用KBinsDiscretizer進行onehot編碼方式分箱后,代碼如下
# 導(dǎo)入庫
from sklearn.preprocessing import KBinsDiscretizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
from sklearn.metrics import brier_score_loss
import numpy as np# **********第一步:建立數(shù)據(jù)集**********
class_1 = 500
class_2 = 500 # 兩個類分別設(shè)置500個樣本
centers = [[0, 0], [2, 2]] # 設(shè)置數(shù)據(jù)集的中心
clusters_std = [0.5, 0.5] # 設(shè)置兩個類別的均值和方差# 使用make_blobs生成樣本,y的類別只有0和1
X, y = make_blobs(n_samples=[class_1, class_2], centers=centers, cluster_std=clusters_std, random_state=0, shuffle=False)# 劃分?jǐn)?shù)據(jù)集測試集
xtrain, xtest, ytrain, ytest = train_test_split(X, y, random_state=0, test_size=0.3)# **********第二步:數(shù)據(jù)轉(zhuǎn)換**********
# 把Xtiain轉(zhuǎn)換成分類型數(shù)據(jù)
# 注意我們的Xtrain沒有經(jīng)過歸一化,因為做啞變量之后自然所有的數(shù)據(jù)就不會有負(fù)數(shù)了
# 在這里,2個特征中,每個特征分了十個箱,相當(dāng)于2個特征裂變成20個特征
kbs = KBinsDiscretizer(n_bins=10, encode='onehot').fit(xtrain)
xtrain_ = kbs.transform(xtrain)
xtest_ = kbs.transform(xtest)# **********第三步:建立多項式樸素貝葉斯分類器**********
# 訓(xùn)練的時候使用歸一化之后的特征矩陣
mnb = MultinomialNB().fit(xtrain_, ytrain)# 獲取每一個特征的先驗概率
# 返回每一個標(biāo)簽類對應(yīng)的先驗概率
print(f'對數(shù)先驗概率矩陣為:\n{mnb.class_log_prior_}')
# 使用np.exp求出真正的概率,因為對數(shù)是以e為底
print(f'先驗概率矩陣為:\n{np.exp(mnb.class_log_prior_)}\n')# 返回每一個固定類別標(biāo)簽下的每一個特征的對數(shù)概率log(p(xi|y))
# 矩陣形狀是2*2,因為有2個特征,2個類別
print(f'對數(shù)條件概率矩陣為:\n{mnb.feature_log_prob_}')
# 使用np.exp求出真正的概率,因為對數(shù)是以e為底
print(f'條件概率矩陣為:\n{np.exp(mnb.feature_log_prob_)}\n')# 在fit時每一個標(biāo)簽類別下包含的樣本數(shù)
# 當(dāng)fit時候接口中sample_weight被設(shè)置的時候,該接口返回的值也會受到加權(quán)的影響
print(f'0類和1類的樣本數(shù)分別為:\n{mnb.class_count_}\n')# 返回預(yù)測結(jié)果
print(f'預(yù)測結(jié)果為:\n{mnb.predict(xtest_)}\n')# 返回每一個樣本在每一個標(biāo)簽下面的取值概率
print(f'標(biāo)簽的取值概率矩陣為:\n{mnb.predict_proba(xtest_)}\n')# 返回我們的準(zhǔn)確度
print(f'準(zhǔn)確度為:{mnb.score(xtest_, ytest)}\n')# 返回我們的布里爾分?jǐn)?shù)
print(f'布里爾分?jǐn)?shù)為:{brier_score_loss(ytest, mnb.predict_proba(xtest_)[:, 1], pos_label=1)}')
結(jié)果如下:
可以看到,性能大大提升
4.2 伯努利貝葉斯
1 BernoulliNB語法格式
多元伯努利分布的特點是數(shù)據(jù)集中可以存在多個特征,但每個特征都是二分類的,可以以布爾變量表示,也可以表示為{0,1}或者{-1,1}等任意二分類組合。因此,這個類要求將樣本轉(zhuǎn)換為二分類特征向量,如果數(shù)據(jù)不是二分類的,可以使用類中專門用來二值化的參數(shù)binarize來改變數(shù)據(jù)。
class sklearn.naive_bayes.BernoulliNB(*, alpha=1.0, binarize=0.0, fit_prior=True, class_prior=None)
參數(shù)說明:
參數(shù) | 說明 |
---|---|
alpha | float, default=1.0 附加的平滑參數(shù)(Laplace/Lidstone),0是不平滑 |
binarize | float or None, default=0.0 用于將樣本特征二值化(映射為布爾值)的閾值(例如小于該閾值設(shè)為0,大于該閾值設(shè)為1)。如果為None,則假定輸入已經(jīng)由二分類向量組成。 |
fit_prior | bool, default=True 是否學(xué)習(xí)類別先驗概率。如果為False,將使用統(tǒng)一的先驗。 |
class_prior | array-like of shape (n_classes,), default=None 類別的先驗概率。一經(jīng)指定先驗概率不能隨著數(shù)據(jù)而調(diào)整。 |
屬性說明:
屬性 | 說明 |
---|---|
class_count_ | ndarray of shape (n_classes) 擬合期間每個類別遇到的樣本數(shù)。此值由提供的樣本權(quán)重加權(quán)。 |
class_log_prior_ | ndarray of shape (n_classes) 每個類別的對數(shù)概率(平滑)。 |
classes_ | ndarray of shape (n_classes,) 分類器已知的類別標(biāo)簽 |
feature_count_ | ndarray of shape (n_classes, n_features) 擬合期間每個(類別,特征)遇到的樣本數(shù)。此值由提供的樣品權(quán)重加權(quán)。 |
feature_log_prob_ | ndarray of shape (n_classes, n_features) 給定一類P(xi|y)的特征的經(jīng)驗對數(shù)概率。 |
n_features_ | int 每個樣本的特征數(shù)量。 |
常用方法如下:
方法 | 說明 |
---|---|
fit (X, y[, sample_weight]) | 根據(jù)X,y擬合樸素貝葉斯分類器 |
get_params ([deep]) | 獲取這個估計器的參數(shù) |
partial_fit (X, y[, classes, sample_weight]) | 對一批樣本進行增量擬合 |
predict (X) | 對測試向量X進行分類。 |
predict_log_proba (X) | 返回針對測試向量X的對數(shù)概率估計 |
predict_proba (X) | 返回針對測試向量X的概率估計 |
score (X, y[, sample_weight]) | 返回給定測試數(shù)據(jù)和標(biāo)簽上的平均準(zhǔn)確率。 |
set_params (**params) | 為這個估計器設(shè)置參數(shù) |
對X矩陣和y矩陣的要求如下:
參數(shù) | 說明 |
---|---|
X | {array-like, sparse matrix} of shape (n_samples, n_features) 用于訓(xùn)練的向量,其中n_samples是樣本數(shù)量,n_features是特征數(shù)量。 |
y | array-like of shape (n_samples,) 目標(biāo)值。 |
2 代碼例子
仍然使用多項式樸素貝葉斯的數(shù)據(jù)集
# 導(dǎo)入庫
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
from sklearn.metrics import brier_score_loss
from sklearn.preprocessing import MinMaxScaler
from sklearn.naive_bayes import BernoulliNB# **********第一步:建立數(shù)據(jù)集**********
class_1 = 500
class_2 = 500 # 兩個類分別設(shè)置500個樣本
centers = [[0, 0], [2, 2]] # 設(shè)置數(shù)據(jù)集的中心
clusters_std = [0.5, 0.5] # 設(shè)置兩個類別的均值和方差# 使用make_blobs生成樣本,y的類別只有0和1
X, y = make_blobs(n_samples=[class_1, class_2], centers=centers, cluster_std=clusters_std, random_state=0, shuffle=False)# 劃分?jǐn)?shù)據(jù)集測試集
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X, y, random_state=0, test_size=0.3)# **********第二步:數(shù)據(jù)轉(zhuǎn)換**********
# 普通來說我們應(yīng)該使用二值化的類sklearn.preprocessing.Binarizer來將特征一個個二值化
# 然而這樣效率過低,因此我們選擇歸一化之后直接設(shè)置一個閾值
mms = MinMaxScaler().fit(Xtrain)
Xtrain_ = mms.transform(Xtrain)
Xtest_ = mms.transform(Xtest)# **********第三步:建立伯努利樸素貝葉斯分類器**********
# 不設(shè)置二值化
bnl_ = BernoulliNB().fit(Xtrain_, Ytrain)
print(f'不設(shè)置二值化時,準(zhǔn)確度為:{bnl_.score(Xtest_,Ytest)}')
print(f'不設(shè)置二值化時,布里爾分?jǐn)?shù)為:{brier_score_loss(Ytest,bnl_.predict_proba(Xtest_)[:,1],pos_label=1)}')# 設(shè)置二值化閾值為0.5
bnl = BernoulliNB(binarize=0.5).fit(Xtrain_, Ytrain)
print(f'設(shè)置二值化時,準(zhǔn)確度為:{bnl.score(Xtest_,Ytest)}')
print(f'設(shè)置二值化時,布里爾分?jǐn)?shù)為:{brier_score_loss(Ytest,bnl.predict_proba(Xtest_)[:,1],pos_label=1)}')
代碼結(jié)果如下:
通過代碼結(jié)果可知,二值化時伯努利樸素貝葉斯擁有非常高的準(zhǔn)確度
4.3? 類別貝葉斯CategoricalNB
1?CategoricalNB語法格式
class sklearn.naive_bayes.CategoricalNB(*, alpha=1.0, fit_prior=True, class_prior=None)
參數(shù)說明:
參數(shù) | 說明 |
---|---|
alpha | float, default=1.0 附加的平滑參數(shù)(Laplace/Lidstone),0是不平滑 |
fit_prior | bool, default=True 是否學(xué)習(xí)類別先驗概率。若為False,將使用統(tǒng)一的先驗(概率相等) |
class_prior | array-like of shape (n_classes,), default=None 類別的先驗概率。一經(jīng)指定先驗概率不能隨著數(shù)據(jù)而調(diào)整。 |
屬性說明:
屬性 | 說明 |
---|---|
category_count_ | list of arrays of shape (n_features,) 為每個要素保存形狀的數(shù)組(n_classes,各個要素的n_categories)。每個數(shù)組為每個類別和分類的特定特征提供遇到的樣本數(shù)量。 |
class_count_ | ndarray of shape (n_classes,) 擬合期間每個類別遇到的樣本數(shù)。此值由提供的樣本權(quán)重加權(quán)。 |
class_log_prior_ | ndarray of shape (n_classes,) 每個類別的對數(shù)先驗概率(平滑)。 |
classes_ | ndarray of shape (n_classes,) 分類器已知的類別標(biāo)簽 |
feature_log_prob_ | list of arrays of shape (n_features,) 為每個特征保形狀的數(shù)組(n_classes,各個要素的n_categories)。每個數(shù)組提供了給定各自特征和類別的分類的經(jīng)驗對數(shù)概率log(p(xi|y)) |
n_features_ | int 每個樣本的特征數(shù)量。 |
方法說明:
方法 | 說明 |
---|---|
fit(X, y[, sample_weight]) | 根據(jù)X,y擬合樸素貝葉斯分類器。 |
get_params([deep]) | 獲取這個估計器的參數(shù) |
partial_fit(X, y[, classes, sample_weight]) | 對一批樣本進行增量擬合。 |
predict(X) | 對測試向量X進行分類 |
predict_log_proba(X) | 返回針對測試向量X的對數(shù)概率估計 |
predict_proba(X) | 返回針對測試向量X的概率估計 |
score(X, y[, sample_weight]) | 返回給定測試數(shù)據(jù)和標(biāo)簽上的平均準(zhǔn)確率 |
set_params(**params) | 為這個估計器設(shè)置參數(shù) |
對于X矩陣和y矩陣的要求如下:
參數(shù) | 說明 |
---|---|
X | {array-like, sparse matrix} of shape (n_samples, n_features) 樣本的特征矩陣,其中n_samples是樣本數(shù)量,n_features是特征數(shù)量。在此,假設(shè)X的每個特征都來自不同的分類分布。進一步假設(shè)每個特征的所有類別均由數(shù)字0,…,n-1表示,其中n表示給定特征的類別總數(shù)。例如,這可以在順序編碼(OrdinalEncoder)的幫助下實現(xiàn)。 |
y | array-like of shape (n_samples,) 每個樣本所屬的標(biāo)簽類別 |
2 代碼例子
以多項式樸素貝葉斯的連續(xù)型數(shù)據(jù)為例,對其進行Ordinal分箱,代碼如下:
# 導(dǎo)入庫
from sklearn.preprocessing import KBinsDiscretizer
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
from sklearn.metrics import brier_score_loss
from sklearn.naive_bayes import CategoricalNB
import numpy as np# **********第一步:建立數(shù)據(jù)集**********
class_1 = 500
class_2 = 500 # 兩個類分別設(shè)置500個樣本
centers = [[0, 0], [2, 2]] # 設(shè)置數(shù)據(jù)集的中心
clusters_std = [0.5, 0.5] # 設(shè)置兩個類別的均值和方差# 使用make_blobs生成樣本,y的類別只有0和1
X, y = make_blobs(n_samples=[class_1, class_2], centers=centers, cluster_std=clusters_std, random_state=0, shuffle=False)# 劃分?jǐn)?shù)據(jù)集測試集
xtrain, xtest, ytrain, ytest = train_test_split(X, y, random_state=0, test_size=0.3)# **********第二步:數(shù)據(jù)轉(zhuǎn)換**********
# 在這里,2個特征中,將每個特征定義為有五個類別,即分成五個箱
# 矩陣每一列是特征,每一列的值是箱的整數(shù)編號,該整數(shù)編號相當(dāng)于該特征的所屬類別
kbs = KBinsDiscretizer(n_bins=5, encode='ordinal').fit(xtrain)
xtrain_ = kbs.transform(xtrain)
xtest_ = kbs.transform(xtest)# **********第三步:建立類別樸素貝葉斯分類器**********
# 訓(xùn)練數(shù)據(jù)
mnb = CategoricalNB().fit(xtrain_, ytrain)# 獲取每一個特征的先驗概率
# 返回每一個標(biāo)簽類對應(yīng)的先驗概率
print(f'對數(shù)先驗概率矩陣為:\n{mnb.class_log_prior_}')
# 使用np.exp求出真正的概率,因為對數(shù)是以e為底
print(f'先驗概率矩陣為:\n{np.exp(mnb.class_log_prior_)}\n')# 返回每一個固定類別標(biāo)簽下的每一個特征的對數(shù)概率log(p(xi|y))
# 矩陣形狀是2*2,因為有2個特征,2個類別
print(f'對數(shù)條件概率矩陣為:\n{mnb.feature_log_prob_}')
# 使用np.exp求出真正的概率,因為對數(shù)是以e為底
print(f'條件概率矩陣為:\n{np.exp(mnb.feature_log_prob_)}\n')# 在fit時每一個標(biāo)簽類別下包含的樣本數(shù)
# 當(dāng)fit時候接口中sample_weight被設(shè)置的時候,該接口返回的值也會受到加權(quán)的影響
print(f'0類和1類的樣本數(shù)分別為:\n{mnb.class_count_}\n')# 返回預(yù)測結(jié)果
print(f'預(yù)測結(jié)果為:\n{mnb.predict(xtest_)}\n')# 返回每一個樣本在每一個標(biāo)簽下面的取值概率
print(f'標(biāo)簽的取值概率矩陣為:\n{mnb.predict_proba(xtest_)}\n')# 返回我們的準(zhǔn)確度
print(f'準(zhǔn)確度為:{mnb.score(xtest_, ytest)}\n')# 返回我們的布里爾分?jǐn)?shù)
print(f'布里爾分?jǐn)?shù)為:{brier_score_loss(ytest, mnb.predict_proba(xtest_)[:, 1], pos_label=1)}')
最終的準(zhǔn)確度和布里爾分?jǐn)?shù)為:
4.4?貝葉斯的樣本不平衡問題
探討一個分類算法永遠都逃不過的核心問題:樣本不平衡。貝葉斯由于分類效力不算太好,因此對樣本不平衡極為敏感
- 注意:對于召回率的概念可看混淆矩陣-ROC曲線、召回率、精確率、準(zhǔn)確率
?
接下來看一個例子,以少數(shù)類樣本為正類,代碼如下:
from sklearn.naive_bayes import MultinomialNB, GaussianNB, BernoulliNB,CategoricalNB
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
from sklearn.preprocessing import KBinsDiscretizer
from sklearn.metrics import brier_score_loss as BS,recall_score,roc_auc_score as AUC# 第一步:創(chuàng)建數(shù)據(jù)集
# 其中,少數(shù)類為正類即為類別1
class_1 = 50000 #多數(shù)類為50000個樣本
class_2 = 500 #少數(shù)類為500個樣本
centers = [[0.0, 0.0], [5.0, 5.0]] #設(shè)定兩個類別的中心
clusters_std = [3, 1] #設(shè)定兩個類別的方差
X, y = make_blobs(n_samples=[class_1, class_2],centers=centers,cluster_std=clusters_std,random_state=0, shuffle=False)
# 查看所有貝葉斯樣本不均衡的表現(xiàn)
name = ["Multinomial","Gaussian","Bernoulli","Categorical"]
models = [MultinomialNB(),GaussianNB(),BernoulliNB(),CategoricalNB()]
for name,clf in zip(name,models):Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3,random_state=420)if name == "Categorical":kbs = KBinsDiscretizer(n_bins=5, encode='ordinal').fit(Xtrain)Xtrain = kbs.transform(Xtrain)Xtest = kbs.transform(Xtest)if name != "Gaussian" and name !="Categorical":kbs = KBinsDiscretizer(n_bins=10, encode='onehot').fit(Xtrain)Xtrain = kbs.transform(Xtrain)Xtest = kbs.transform(Xtest)clf.fit(Xtrain,Ytrain)y_pred = clf.predict(Xtest)proba = clf.predict_proba(Xtest)[:,1]score = clf.score(Xtest,Ytest)print(name)print("\tBrier:{:.3f}".format(BS(Ytest,proba,pos_label=1)))print("\tAccuracy:{:.3f}".format(score))# 返回召回率print("\tRecall:{:.3f}".format(recall_score(Ytest,y_pred)))# 返回AUCprint("\tAUC:{:.3f}".format(AUC(Ytest,proba)))
代碼結(jié)果如下:
從結(jié)果得到如下結(jié)論:
- 多項式樸素貝葉斯判斷出了所有的多數(shù)類樣本,但放棄了全部的少數(shù)類樣本,受到樣本不均衡問題影響最嚴(yán)重
- 類別貝葉斯和多項式樸素貝葉斯一樣
- 高斯比多項式在少數(shù)類的判斷上更加成功一些,至少得到了43.8%的recall
- 伯努利貝葉斯雖然整體的準(zhǔn)確度和布里爾分?jǐn)?shù)不如多項式和高斯樸素貝葉斯和,但至少成功捕捉出了77.1%的少數(shù)類
?
從上述結(jié)果可知,這四類貝葉斯結(jié)果都不好,因此出現(xiàn)了新興貝葉斯算法:補集樸素貝葉斯
4.5 補集貝葉斯
1?ComplementNB語法格式
補集樸素貝葉斯(complement naive Bayes,CNB)算法是標(biāo)準(zhǔn)多項式樸素貝葉斯算法的改進。補集貝葉斯可以解決樣本不平衡問題,并且能夠一定程度上忽略樸素假設(shè)
class sklearn.naive_bayes.ComplementNB(*,alpha = 1.0,fit_prior = True,class_prior = None,norm = False )
參數(shù)說明
參數(shù) | 說明 |
---|---|
alpha | float, default=1.0 附加的(Laplace/Lidstone)平滑參數(shù)(0表示不平滑) |
fit_prior | bool, default=True 是否學(xué)習(xí)類別先驗概率。如果為False,將使用統(tǒng)一的先驗。 |
class_prior | array-like of shape (n_classes,), default=None 類別的先驗概率。一經(jīng)指定先驗概率不能隨著數(shù)據(jù)而調(diào)整。 |
norm | bool, default=False 在計算權(quán)重的時候是否適用L2范式來規(guī)范權(quán)重的大小。默認(rèn)不進行規(guī)范,即不跟從補集樸素貝葉斯算法的全部內(nèi)容,如果希望進行規(guī)范,請設(shè)置為True。 |
屬性說明:
屬性 | 說明 |
---|---|
class_count_ | ndarray of shape (n_classes,) 擬合期間每個類別遇到的樣本數(shù)。此值由提供的樣本權(quán)重加權(quán)。 |
class_log_prior_ | ndarray of shape (n_classes,) 每個類別的對數(shù)概率(平滑)。 |
classes_ | ndarray of shape (n_classes,) 分類器已知的類別標(biāo)簽 |
feature_all_ | ndarray of shape (n_features,) 擬合期間每個特征遇到的樣本數(shù)。此值由提供的樣本權(quán)重加權(quán)。 |
feature_count_ | ndarray of shape (n_classes, n_features) 擬合期間每個(類別,特征)遇到的樣本數(shù)。此值由提供的樣本權(quán)重加權(quán)。 |
feature_log_prob_ | ndarray of shape (n_classes, n_features) 類別補充的經(jīng)驗權(quán)重 |
n_features_ | int 每個樣本的特征數(shù)量。 |
常用方法如下:
方法 | 說明 |
---|---|
fit (X, y[, sample_weight]) | 根據(jù)X,y擬合樸素貝葉斯分類器 |
get_params ([deep]) | 獲取這個估計器的參數(shù) |
partial_fit (X, y[, classes, sample_weight]) | 對一批樣本進行增量擬合 |
predict (X) | 對測試向量X進行分類。 |
predict_log_proba (X) | 返回針對測試向量X的對數(shù)概率估計 |
predict_proba (X) | 返回針對測試向量X的概率估計 |
score (X, y[, sample_weight]) | 返回給定測試數(shù)據(jù)和標(biāo)簽上的平均準(zhǔn)確率。 |
set_params (**params) | 為這個估計器設(shè)置參數(shù) |
對X矩陣和y矩陣要求如下:
參數(shù) | 說明 |
---|---|
X | {array-like, sparse matrix} of shape (n_samples, n_features) 用于訓(xùn)練的向量,其中n_samples是樣本數(shù)量,n_features是特征數(shù)量。 |
y | array-like of shape (n_samples,) 目標(biāo)值 |
2 代碼例子
接下來看一個例子,以少數(shù)類樣本為正類,代碼如下:
from sklearn.naive_bayes import MultinomialNB, GaussianNB, BernoulliNB,CategoricalNB, ComplementNB
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
from sklearn.preprocessing import KBinsDiscretizer
from sklearn.metrics import brier_score_loss as BS,recall_score,roc_auc_score as AUC# 第一步:創(chuàng)建數(shù)據(jù)集
# 其中,少數(shù)類為正類即為類別1
class_1 = 50000 #多數(shù)類為50000個樣本
class_2 = 500 #少數(shù)類為500個樣本
centers = [[0.0, 0.0], [5.0, 5.0]] #設(shè)定兩個類別的中心
clusters_std = [3, 1] #設(shè)定兩個類別的方差
X, y = make_blobs(n_samples=[class_1, class_2],centers=centers,cluster_std=clusters_std,random_state=0, shuffle=False)
# 查看所有貝葉斯樣本不均衡的表現(xiàn)
name = ["Multinomial","Gaussian","Bernoulli","Categorical","Complement"]
models = [MultinomialNB(),GaussianNB(),BernoulliNB(),CategoricalNB(),ComplementNB()]
for name,clf in zip(name,models):Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3,random_state=420)if name == "Categorical":kbs = KBinsDiscretizer(n_bins=5, encode='ordinal').fit(Xtrain)Xtrain = kbs.transform(Xtrain)Xtest = kbs.transform(Xtest)if name != "Gaussian" and name !="Categorical":kbs = KBinsDiscretizer(n_bins=10, encode='onehot').fit(Xtrain)Xtrain = kbs.transform(Xtrain)Xtest = kbs.transform(Xtest)clf.fit(Xtrain,Ytrain)y_pred = clf.predict(Xtest)proba = clf.predict_proba(Xtest)[:,1]score = clf.score(Xtest,Ytest)print(name)print("\tBrier:{:.3f}".format(BS(Ytest,proba,pos_label=1)))print("\tAccuracy:{:.3f}".format(score))# 返回召回率print("\tRecall:{:.3f}".format(recall_score(Ytest,y_pred)))# 返回AUCprint("\tAUC:{:.3f}".format(AUC(Ytest,proba)))
代碼結(jié)果如下:
從代碼結(jié)果可以得出:
- 補集樸素貝葉斯?fàn)奚瞬糠终w的精確度和布里爾指數(shù),但是得到了十分高的召回率Recall,捕捉出了98.7%的少數(shù)類,并且在此基礎(chǔ)上維持了和原本的多項式樸素貝葉斯一致的AUC分?jǐn)?shù)。
- 和其他的貝葉斯算法比起來,補集樸素貝葉斯的運行速度也十分優(yōu)秀。如果目標(biāo)是捕捉少數(shù)類,則選擇補集樸素貝葉斯。