k折交叉验证法python实现_Jason Brownlee专栏| 如何解决不平衡分类的k折交叉验证-不平衡分类系列教程(十)...
作者:Jason Brownlee
編譯:Florence Wong – AICUG
本文系AICUG翻譯原創,如需轉載請聯系(微信號:834436689)以獲得授權
在對不可見示例進行預測時,模型評估涉及使用可用的數據集來擬合模型,并評估其表現性能。
這是一個具有挑戰性的問題,因為用于擬合模型的訓練數據集和用于評估模型的測試集都必須足夠大,并對潛在問題具有代表性,從而可使對模型性能的最終估計不會過于樂觀或悲觀。
用于模型評估的兩種最常用的方法,是訓練/測試拆分和k折(k-fold)交叉驗證。盡管這兩種方法都可能導致誤導性結果,并且在對嚴重不平衡的分類問題上進行使用時,有可能會失敗,但是這兩種方法通常都非常有效。
在本教程中,您將發現如何評估不平衡數據集上的分類器模型。
完成本教程后,您將知道:
- 使用訓練/測試拆分和交叉驗證在數據集上評估分類器時的挑戰。
- 當評估不平衡數據集上的分類器時,一個k-折交叉驗證和訓練測試拆分的樸素應用,將如何失敗。
- 修改后的k折交叉驗證和訓練測試拆分, 如何用于保留數據集中的類分布。
教程概述
本教程分為三個部分:他們是:
- 評估分類器的挑戰
- k折疊交叉驗證的失敗
- 為不平衡分類,修正交叉驗證
評估分類器的挑戰
評估一個分類模型具有挑戰性,因為在使用模型之前,我們不知道模型有多好。
相反,我們必須使用已有目標或結果的可用數據,來估計模型的表現性能。
模型評估不僅僅涉及評估一個模型;還包括測試不同的數據準備方案,不同的學習算法以及針對性能良好的學習算法的不同超參數。
- 模型=數據準備+學習算法+超參數
理想情況下,可以選擇和使用得分最高(根據你選擇的測度)的模型構建過程(數據準備,學習算法和超參數)。
最簡單的模型評估過程是將數據集分為兩部分,其中一部分用于訓練模型,第二部分用于測試模型。這樣,數據集的各個部分,分別以其功能,訓練集和測試集命名。
如果您收集的數據集非常大且能代表問題,則此方法有效。所需的示例數量因問題而異,但可能是數千,數十萬或數百萬個示例才夠用。
訓練和測試的分割比例為50/50是理想的,盡管偏斜的分割比例比較普遍,例如訓練和測試組合的分割比例為67/33或80/20。
我們很少有足夠的數據,從而可以通過使用模型的訓練/測試拆分評估,來獲得對性能的無偏差估計。取而代之的是,我們的數據集通常比首選數據集小得多,并且必須在該數據集上使用重采樣策略。
分類器最常用的模型評估方案是10折(10-folds)交叉驗證。
k折交叉驗證過程涉及分割訓練數據集成?部分。前k-1個用于訓練模型,第k個保留的部分用作測試集。重復此過程,每個部分都有機會用作保留的測試集。總共對k個模型進行擬合和評估,取其平均值計算得到模型的性能。
與單次訓練/測試劃分相比,該方法可顯示出,在較小訓練數據集上模型的不足樂觀的性能估計。k = 10的值,顯示在多種不同大小的數據集和模型類型上有效。
k折疊交叉驗證失敗
可悲的是,k折交叉驗證不適用于評估不平衡的分類器。
“在分類不平衡的情況下,即使偏斜的極端程度以前考慮要小,十??倍交叉驗證(尤其是機器學習中最常用的錯誤估計方法)也很容易崩潰。”
—第188頁,不平衡的學習:基礎,算法和應用,2013年。
原因是數據被分成具有均勻概率分布的k部分。
這對于具有平衡類分布的數據可能會很好,但是當分布嚴重偏斜時,一部分或多部分折疊可能會出現極少數類的樣本很少甚至沒有。這意味著某些或許多模型評估會產生誤導,因為模型的需求僅是正確預測多數類。
我們可以用一個例子來具體說明。
首先,我們可以定義一個1:100的少數對比多數類分布的數據集。
這可以通過使用make_classification()函數來創建綜合數據集,指定示例數(1,000個),類數(2個)以及每個類的權重(99%和1%)來實現。
# generate 2 class dataset下面的示例生成綜合二進制分類數據集并總結類分布。
# create a binary classification dataset from numpy import unique from sklearn.datasets import make_classification # generate 2 class dataset X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.99, 0.01], flip_y=0, random_state=1) # summarize dataset classes = unique(y) total = len(y) for c in classes:n_examples = len(y[y==c])percent = n_examples / total * 100print('> Class=%d : %d/%d (%.1f%%)' % (c, n_examples, total, percent))運行示例將創建數據集并匯總每個類中的示例數量。
通過設置random_state參數,可以確保每次運行代碼時,我們得到的隨機生成的示例相同。
> Class=0 : 990/1000 (99.0%) > Class=1 : 10/1000 (1.0%)少數類中總共有10個例子并不多。如果我們使用10-folds,那么在理想情況下,每部分將得到一個示例,這不足以訓練模型。出于演示目的,我們將使用5-folds。
在理想情況下,每個部分中將有10/5或兩個示例,這意味著訓練數據集中的示例量為4 * 2(8),給定測試數據集中的示例量為1 * 2(2)。
首先,我們將使用KFold類將數據集隨機分為5部分,并檢查每個訓練和測試集的組成。下面列出了完整的示例。
# example of k-fold cross-validation with an imbalanced dataset from sklearn.datasets import make_classification from sklearn.model_selection import KFold # generate 2 class dataset X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.99, 0.01], flip_y=0, random_state=1) kfold = KFold(n_splits=5, shuffle=True, random_state=1) # enumerate the splits and summarize the distributions for train_ix, test_ix in kfold.split(X):# select rowstrain_X, test_X = X[train_ix], X[test_ix]train_y, test_y = y[train_ix], y[test_ix]# summarize train and test compositiontrain_0, train_1 = len(train_y[train_y==0]), len(train_y[train_y==1])test_0, test_1 = len(test_y[test_y==0]), len(test_y[test_y==1])print('>Train: 0=%d, 1=%d, Test: 0=%d, 1=%d' % (train_0, train_1, test_0, test_1))運行示例將創建相同的數據集,并枚舉數據的每個拆分,從而顯示訓練集和測試集的類分布。
我們可以看到,在這種情況下,某些拆分有期望的8/2的訓練集和測試集的比例,而另一些拆分很差,例如6/4(樂觀)和10/0(悲觀)。
在這些數據拆分上評估模型不會給出可靠的對性能的評估。
>Train: 0=791, 1=9, Test: 0=199, 1=1 >Train: 0=793, 1=7, Test: 0=197, 1=3 >Train: 0=794, 1=6, Test: 0=196, 1=4 >Train: 0=790, 1=10, Test: 0=200, 1=0 >Train: 0=792, 1=8, Test: 0=198, 1=2如果我們使用數據集的簡單訓練/測試拆分,則可以證明類似問題的存在,盡管該問題不太嚴重。
我們可以使用train_test_split()函數創建數據集的50/50拆分,并且平均而言,如果我們多次執行該拆分操作,我們則希望每個數據集中會出現來自少數類的五個示例。
下面列出了完整的示例。
# example of train/test split with an imbalanced dataset from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split # generate 2 class dataset X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.99, 0.01], flip_y=0, random_state=1) # split into train/test sets with same class ratio trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.5, random_state=2) # summarize train_0, train_1 = len(trainy[trainy==0]), len(trainy[trainy==1]) test_0, test_1 = len(testy[testy==0]), len(testy[testy==1]) print('>Train: 0=%d, 1=%d, Test: 0=%d, 1=%d' % (train_0, train_1, test_0, test_1))運行示例將創建與之前相同的數據集,并將其拆分為隨機訓練和測試。
在這種情況下,我們可以看到訓練集中都少數類的僅有3個例子,而測試集中有7個。
在這種拆分情況下,評估模型將無法提供足夠的示例以供機器學習,示例太多而無法被評估,并且可能會導致性能下降。您可以想象,如果使用更嚴格意義的隨機拆分,情況會變得更糟。
>Train: 0=497, 1=3, Test: 0=493, 1=7針對不平衡分類的交叉驗證的修正
解決方案是在使用k折交叉驗證或一個測試拆分時,不要隨機拆分數據。
具體來說,盡管我們可以在每個子集中保持相同的類分布,但是我們可以隨機拆分數據集。這稱為分層或分層抽樣,目標變量(y)類用于控制抽樣過程。
例如,我們可以使用k折交叉驗證的一個版本,該版本保留每個部分中不平衡的類分布。這稱為分層k折交叉驗證,它將在數據集的每個拆分中強制進行類分布以匹配完整訓練數據集中的分布。
“…特別是在類別不平衡的情況下,通常使用分層10折交叉驗證,以確保原始數據分布中正例與負例的比例在所有拆分部分中均得到體現。”
—第205頁,不平衡的學習:基礎,算法和應用,2013年。
我們可以用一個例子來具體說明。
顧名思義,我們可以使用支持分層k折交叉驗證的StratifiedKFold類對拆分進行分層。
以下的分層的交叉驗證版本,基于相同數據集和相同示例。
# example of stratified k-fold cross-validation with an imbalanced dataset from sklearn.datasets import make_classification from sklearn.model_selection import StratifiedKFold # generate 2 class dataset X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.99, 0.01], flip_y=0, random_state=1) kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=1) # enumerate the splits and summarize the distributions for train_ix, test_ix in kfold.split(X, y):# select rowstrain_X, test_X = X[train_ix], X[test_ix]train_y, test_y = y[train_ix], y[test_ix]# summarize train and test compositiontrain_0, train_1 = len(train_y[train_y==0]), len(train_y[train_y==1])test_0, test_1 = len(test_y[test_y==0]), len(test_y[test_y==1])print('>Train: 0=%d, 1=%d, Test: 0=%d, 1=%d' % (train_0, train_1, test_0, test_1))運行示例將像以前一樣生成數據集,并匯總每個拆分的訓練和測試集的類分布。
在這種情況下,我們可以看到每個拆分均與理想情況下的預期匹配。
少數類中的每個示例都有一個機會在測試集中使用,并且在每個數據集在拆分后的訓練和測試集具有相同的類分布。
>Train: 0=792, 1=8, Test: 0=198, 1=2 >Train: 0=792, 1=8, Test: 0=198, 1=2 >Train: 0=792, 1=8, Test: 0=198, 1=2 >Train: 0=792, 1=8, Test: 0=198, 1=2 >Train: 0=792, 1=8, Test: 0=198, 1=2本示例強調,需要首先為k折交叉驗證選擇k值,以確保訓練和測試集中有足夠數量的示例來擬合并評估一個模型(模型中兩個來自少數類的示例,對于測試集來說可能太少了)。
它還強調了對不平衡數據集使用分層k折交叉驗證的必要性:對一個給定模型的每次評估時,在訓練和測試集中,保留了模型的類分布。
我們還可以使用一個訓練/測試拆分的分層版本。
這可以通過在應用train_test_split()函數時設置“Stratify“參數,,并將其設置為“ y”-包含數據集中的目標變量的變量。由此,該方程將確定所需的類分布,并確保訓練和測試集都具有此分布。
我們可以通過下面列出的示例來證明這一點。
# example of stratified train/test split with an imbalanced dataset from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split # generate 2 class dataset X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.99, 0.01], flip_y=0, random_state=1) # split into train/test sets with same class ratio trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.5, random_state=2, stratify=y) # summarize train_0, train_1 = len(trainy[trainy==0]), len(trainy[trainy==1]) test_0, test_1 = len(testy[testy==0]), len(testy[testy==1]) print('>Train: 0=%d, 1=%d, Test: 0=%d, 1=%d' % (train_0, train_1, test_0, test_1))運行示例將對數據集創建一個隨機拆分的方法,旨在將數據拆分為訓練集和測試集時,保留類分布,在這種情況下,每個數據集中保留五個示例。
>Train: 0=495, 1=5, Test: 0=495, 1=5進一步閱讀
如果您想更深入,這里提供了有關該主題的更多資源。
教程:
A Gentle Introduction to k-fold Cross-Validation:
A Gentle Introduction to k-fold Cross-Validation - Machine Learning Mastery?machinelearningmastery.com書籍:
Imbalanced Learning: Foundations, Algorithms, and Applications, 2013:
https://amzn.to/32K9K6d?amzn.toAPI
sklearn.model_selection.KFold - scikit-learn 0.22.2 documentation?scikit-learn.orgsklearn.model_selection.StratifiedKFold - scikit-learn 0.22.2 documentation?scikit-learn.orgsklearn.model_selection.train_test_split - scikit-learn 0.22.2 documentation?scikit-learn.org總結
以上是生活随笔為你收集整理的k折交叉验证法python实现_Jason Brownlee专栏| 如何解决不平衡分类的k折交叉验证-不平衡分类系列教程(十)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ip网络基础知识及原理_关于网络测试的5
- 下一篇: vue function (i)第一次点