一、交叉驗證的定義
交叉驗證即把得到的樣本數據進行切分,組合為不同的訓練集和測試集,用訓練集來訓練模型,用測試集來評估模型預測的好壞。交叉驗證通過重復使用數據,多次切分可得到多組不同的訓練集和測試集,某次訓練集中的某樣本在下次可能成為測試集中的樣本,即所謂“交叉”。
通常在數據量不大,或者想要減少過擬合的時候用到。
二、幾種常用的交叉驗證對比
1.sklearn.train_split_test
通常不進行交叉驗證的時候,用sklearn.train_split_test來對數據進行切分。train_split_test只把原數據集按test_size隨機不重復地划分成訓練集和測試集,用訓練集來驗證模型,用測試集來評估模型的得分高低。由於只划分一次,所以沒有交叉驗證。
from sklearn.model_selection import train_test_split x_train,x_test,y_train,y_test=train_test_split(train_data,train_lable,test_size=0.3,random_state=o,stratify=train_lable)
參數說明:
train_data:樣本特征集
train_target:樣本的標簽集
test_size:樣本占比,測試集占數據集的比重,如果是整數的話就是樣本的數量
random_state:是隨機數的種子。在同一份數據集上,相同的種子產生相同的結果,不同的種子產生不同的划分結果
stratify:有時候遇見非平衡數據,讓該參數等於標簽列,可以讓數據划分的時候按標簽來划分,避免划分后的訓練集和測試集在標簽分布上不均。
2.sklearn.cross_val_score,cross_validate
最簡單的交叉驗證可以在訓練模型后用cross_val_score,cross_validate 來進行,下面用svm來解釋
from sklearn.model_selection import cross_val_score,cross_validate
from sklearn import svm
clf = svm.SVC(kernel='linear', C=1) scores = cross_val_score(clf, iris.data, iris.target, cv=5) #交叉驗證cv為迭代次數。 print('迭代5次的scores',scores) # 打印輸出每次迭代的度量值(准確度) # [0.96666667 1. 0.96666667 0.96666667 1. ] print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2)) # 獲取置信區間。(也就是均值和方差),std()計算標准偏差Accuracy: 0.98 (+/- 0.03) # =======================多種度量結果=================== scoring = ['precision_macro', 'recall_macro'] # precision_macro為精度,recall_macro為召回率 # sklearn.metrics.SCORERS.keys() scores = cross_validate(clf, iris.data, iris.target, scoring=scoring,cv=5, return_train_score=True) sorted(scores.keys()) print('測試結果:',scores) # scores類型為字典。包含訓練得分,擬合次數, score-times (得分次數)
3.StratifiedKFold和KFold
K折交叉驗證會把樣本數據隨機的分成K份(一般是均分),每次隨機的選擇K-1份作為訓練集,剩下的1份做測試集。當這一輪完成后,重新隨機選擇K-1份來訓練數據。若干輪(小於K)之后,選擇損失函數評估最優的模型和參數。
將每個子集數據分別做一次測試集,其余的K-1組子集數據作為訓練集,所以一般分成K份就這樣會得到K組模型,用這K個模型最終的測試集的分類准確率的平均數作為此K-CV下分類器的性能指標。
優點是可以降低由一次隨機划分帶來的偶然性,提高其泛化能力。但K折還有個問題就是因為是隨機划分,很有可能划分的過程中剛好把類別都划分開了,比如第一折訓練集里全是0標簽,第二折測試集里全是1標簽,這樣對模型訓練就不太好,在其中的某個模型學習的時候就沒有學習到測試集的分類特征。在KFold中就是這樣的,對於不平衡數據集,特別是一些比賽數據正類非常少,那么直接用KFold就可能出現這種問題。
所以對非平衡數據可以用分層采樣StratifiedKFold,就是在每一份子集中都保持和原始數據集相同的類別比例。若數據集有4個類別,比例是2:3:3:2,則划分后的樣本比例約是2:3:3:2,StratifiedShuffleSplit() 划分中每個類的比例和完整數據集中的相同,若數據集有4個類別,比例是2:3:3:2,則划分后的樣本比例也是2:3:3:2
from sklearn.model_selection import KFold from sklearn.model_selection import StratifiedKFold kfolder = KFold(n_splits=4,random_state=1) for train, test in kfolder.split(X,y): print('Train: %s | test: %s' % (train, test),'\n') >>> Train: [2 3 4 5 6 7] | test: [0 1] Train: [0 1 4 5 6 7] | test: [2 3] Train: [0 1 2 3 6 7] | test: [4 5] Train: [0 1 2 3 4 5] | test: [6 7] folder = StratifiedKFold(n_splits=4,random_state=0) for train, test in sfolder.split(X,y): print('Train: %s | test: %s' % (train, test)) >>> Train: [1 3 4 5 6 7] | test: [0 2] Train: [0 2 4 5 6 7] | test: [1 3] Train: [0 1 2 3 5 7] | test: [4 6] Train: [0 1 2 3 4 6] | test: [5 7]
更多交叉驗證參考:https://blog.csdn.net/u010986753/article/details/98069124
