幾種交叉驗證(cross validation)方式的比較


模型評價的目的:通過模型評價,我們知道當前訓練模型的好壞,泛化能力如何?從而知道是否可以應用在解決問題上,如果不行,那又是哪里出了問題?

train_test_split

在分類問題中,我們通常通過對訓練集進行train_test_split,划分成train 和test 兩部分,其中train用來訓練模型,test用來評估模型,模型通過fit方法從train數據集中學習,然后調用score方法在test集上進行評估,打分;從分數上我們可以知道 模型當前的訓練水平如何。

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

cancer = load_breast_cancer()
X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,random_state=0)

logreg = LogisticRegression().fit(X_train,y_train)
print("Test set score:{:.2f}".format(logreg.score(X_test,y_test)))

輸出:
output: Test set score:0.96
然而,這種方式存:只進行了一次划分,數據結果具有偶然性,如果在某次划分中,訓練集里全是容易學習的數據,測試集里全是復雜的數據,這樣就會導致最終的結果不盡如意;反之,亦是如此。

Standard Cross Validation

針對上面通過train_test_split划分,從而進行模型評估方式存在的弊端,提出Cross Validation 交叉驗證。
Cross Validation:簡言之,就是進行多次train_test_split划分;每次划分時,在不同的數據集上進行訓練、測試評估,從而得出一個評價結果;如果是5折交叉驗證,意思就是在原始數據集上,進行5次划分,每次划分進行一次訓練、評估,最后得到5次划分后的評估結果,一般在這幾次評估結果上取平均得到最后的 評分。k-fold cross-validation ,其中,k一般取5或10。
標准交叉驗證standard Cross validation

demo:

from sklearn.model_selection import cross_val_score

logreg = LogisticRegression()
scores = cross_val_score(logreg,cancer.data, cancer.target) #cv:默認是3折交叉驗證,可以修改cv=5,變成5折交叉驗證。
print("Cross validation scores:{}".format(scores))
print("Mean cross validation score:{:2f}".format(scores.mean()))

輸出:

Cross validation scores:[0.93684211 0.96842105 0.94179894]
Mean cross validation score:0.949021

交叉驗證的優點:

  • 原始采用的train_test_split方法,數據划分具有偶然性;交叉驗證通過多次划分,大大降低了這種由一次隨機划分帶來的偶然性,同時通過多次划分,多次訓練,模型也能遇到各種各樣的數據,從而提高其泛化能力;
  • 與原始的train_test_split相比,對數據的使用效率更高。train_test_split,默認訓練集、測試集比例為3:1,而對交叉驗證來說,如果是5折交叉驗證,訓練集比測試集為4:1;10折交叉驗證訓練集比測試集為9:1。數據量越大,模型准確率越高!

缺點:

  • 這種簡答的交叉驗證方式,從上面的圖片可以看出來,每次划分時對數據進行均分,設想一下,會不會存在一種情況:數據集有5類,抽取出來的也正好是按照類別划分的5類,也就是說第一折全是0類,第二折全是1類,等等;這樣的結果就會導致,模型訓練時,沒有學習到測試集中數據的特點,從而導致模型得分很低,甚至為0,!為了避免這種情況,又出現了其他的各種交叉驗證方式。

Stratified k-fold cross validation

分層交叉驗證(Stratified k-fold cross validation):首先它屬於交叉驗證類型,分層的意思是說在每一折中都保持着原始數據中各個類別的比例關系,比如說:原始數據有3類,比例為1:2:1,采用3折分層交叉驗證,那么划分的3折中,每一折中的數據類別保持着1:2:1的比例,這樣的驗證結果更加可信。
通常情況下,可以設置cv參數來控制幾折,但是我們希望對其划分等加以控制,所以出現了KFold,KFold控制划分折,可以控制划分折的數目,是否打亂順序等,可以賦值給cv,用來控制划分。
標准交叉驗證 vs 分層交叉驗證

demo:

from sklearn.datasets import load_iris
from sklearn.model_selection import StratifiedKFold,cross_val_score
from sklearn.linear_model import LogisticRegression

iris = load_iris()
print('Iris labels:\n{}'.format(iris.target))
logreg = LogisticRegression()
strKFold = StratifiedKFold(n_splits=3,shuffle=False,random_state=0)
scores = cross_val_score(logreg,iris.data,iris.target,cv=strKFold)
print("straitified cross validation scores:{}".format(scores))
print("Mean score of straitified cross validation:{:.2f}".format(scores.mean()))

輸出:

Iris labels:
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
straitified cross validation scores:[0.96078431 0.92156863 0.95833333]
Mean score of straitified cross validation:0.95

Leave-one-out Cross-validation 留一法

留一法Leave-one-out Cross-validation:是一種特殊的交叉驗證方式。顧名思義,如果樣本容量為n,則k=n,進行n折交叉驗證,每次留下一個樣本進行驗證。主要針對小樣本數據。

demo:

from sklearn.datasets import load_iris
from sklearn.model_selection import LeaveOneOut,cross_val_score
from sklearn.linear_model import LogisticRegression

iris = load_iris()
print('Iris labels:\n{}'.format(iris.target))
logreg = LogisticRegression()
loout = LeaveOneOut()
scores = cross_val_score(logreg,iris.data,iris.target,cv=loout)
print("leave-one-out cross validation scores:{}".format(scores))
print("Mean score of leave-one-out cross validation:{:.2f}".format(scores.mean()))

輸出:

Iris labels:
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
leave-one-out cross validation scores:[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 1. 1. 1. 0. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1.]
Mean score of leave-one-out cross validation:0.95

Shuffle-split cross-validation

控制更加靈活:可以控制划分迭代次數、每次划分時測試集和訓練集的比例(也就是說:可以存在既不在訓練集也不再測試集的情況);
shuffle split cross validation
demo:

from sklearn.datasets import load_iris
from sklearn.model_selection import ShuffleSplit,cross_val_score
from sklearn.linear_model import LogisticRegression

iris = load_iris()
shufspl = ShuffleSplit(train_size=.5,test_size=.4,n_splits=8) #迭代8次;
logreg = LogisticRegression()
scores = cross_val_score(logreg,iris.data,iris.target,cv=shufspl)

print("shuffle split cross validation scores:\n{}".format(scores))
print("Mean score of shuffle split cross validation:{:.2f}".format(scores.mean()))

輸出:

shuffle split cross validation scores:
[0.95      0.95      0.95      0.95      0.93333333 0.96666667
0.96666667 0.91666667]
Mean score of shuffle split cross validation:0.95

我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=2l6rvdr2fmcko


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM