数据集划分问题
留出法(hold-out)
使用 n:m and n + m =1 的形式對(duì)原數(shù)據(jù)進(jìn)行分割,例如 train : test = 7 : 3 or train : test = 6.5 : 3.5 但是這種相對(duì)原始的處理方式效果并不好,缺點(diǎn)如下:
- 缺點(diǎn)一:浪費(fèi)數(shù)據(jù)
- 缺點(diǎn)二:容易過(guò)擬合,且矯正方式不方便
這時(shí),我們需要使用另外一種分割方式-交叉驗(yàn)證 或者 留P法(leave P out)
LOO 留一法 or LPO 留P法
LOO : 對(duì)于整個(gè)數(shù)據(jù)集而言,每次選取一個(gè)樣本作為驗(yàn)證集,其余樣本作為訓(xùn)練集
LPO : 對(duì)于整個(gè)數(shù)據(jù)集而言,每次選取P個(gè)樣本作為驗(yàn)證集,其余樣本作為訓(xùn)練集
LOO的好處在于,避免的數(shù)據(jù)的浪費(fèi),但是同時(shí)也擁有了,更高的性能開(kāi)銷
一般LOO相對(duì)于 K-Fold 而言,擁有更高的方差,但是對(duì)于方差占主導(dǎo)的情況時(shí),LOO可能擁有比交叉驗(yàn)證更強(qiáng)的能力.
K-Fold
KFold 將所有的樣例劃分為 k 個(gè)組,稱為折疊 (fold) (如果 k = n, 這等價(jià)于 Leave One Out(留一) 策略),都具有相同的大小(如果可能)。預(yù)測(cè)函數(shù)學(xué)習(xí)時(shí)使用 k - 1 個(gè)折疊中的數(shù)據(jù),最后一個(gè)剩下的折疊會(huì)用于測(cè)試。在集成算法Stacking中就使用了這種方式(Bagging則為子采樣,也是很有趣的方式,之前有介紹)
注意
而 i.i.d 數(shù)據(jù)是機(jī)器學(xué)習(xí)理論中的一個(gè)常見(jiàn)假設(shè),在實(shí)踐中很少成立。如果知道樣本是使用時(shí)間相關(guān)的過(guò)程生成的,則使用 time-series aware cross-validation scheme 更安全。 同樣,如果我們知道生成過(guò)程具有 group structure (群體結(jié)構(gòu))(從不同 subjects(主體) , experiments(實(shí)驗(yàn)), measurement devices (測(cè)量設(shè)備)收集的樣本),則使用 group-wise cross-validation 更安全。
是否重復(fù)試驗(yàn)與分層的問(wèn)題
分層: 對(duì)于K-Fold而言,保持每個(gè)分組中的train : test 的比例大致相等
重復(fù): 即樣本的放回采樣,比如Bagging,訓(xùn)練集中部分樣本會(huì)重復(fù),部分樣本永遠(yuǎn)不會(huì)出現(xiàn)
重復(fù)分層: 對(duì)于Sklearn中的K-Fold而言,指實(shí)現(xiàn)了采樣中各個(gè)類別的比例與原數(shù)據(jù)集的各類別比例大致相等.
交叉驗(yàn)證
LOO 與 LPO 的交叉驗(yàn)證就是每個(gè)(或者每P個(gè)樣本)都作為驗(yàn)證集一次,然后計(jì)算平均值,得出Score,K-Fold類似,不過(guò)不同的地方是分成了K折.
Sklearn中實(shí)現(xiàn)了便捷方法CV
快捷簡(jiǎn)便的使用
加載數(shù)據(jù)
from sklearn.model_selection import train_test_split,LeaveOneOut,LeavePOut from sklearn import datasets from sklearn import svm from sklearn.metrics import accuracy_score import numpy as npiris = datasets.load_iris() clf_svc = svm.SVC(kernel='linear') iris.data.shape,iris.target.shape ((150, 4), (150,))hold out
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.4, random_state=0) clf_svc.fit(X_train,y_train) accuracy_score(clf_svc.predict(X_test),y_test) 0.9666666666666667Leave One Out
loo = LeaveOneOut() loo.get_n_splits(iris.data) mean_accuracy_score_list = [] for train_index, test_index in loo.split(iris.data):clf_svc.fit(iris.data[train_index], iris.target[train_index])prediction = clf_svc.predict(iris.data[test_index])mean_accuracy_score_list.append(accuracy_score(iris.target[test_index], prediction)) print(np.average(mean_accuracy_score_list)) 0.98Leave P Out
LeavePOut 與 LeaveOneOut 非常相似,因?yàn)樗ㄟ^(guò)從整個(gè)集合中刪除 p 個(gè)樣本來(lái)創(chuàng)建所有可能的 訓(xùn)練/測(cè)試集。對(duì)于 n 個(gè)樣本,這產(chǎn)生了 m 個(gè) 訓(xùn)練-測(cè)試 對(duì), m 等于 n個(gè)樣本中 任意選取 p 個(gè)樣本不計(jì)順序自由組合的個(gè)數(shù) 。值得注意的是這種方式會(huì)導(dǎo)致計(jì)算開(kāi)銷大幅增加,下面的例子要比上面的例子,多花費(fèi) m-n 的時(shí)間
loo = LeavePOut(p=3) mean_accuracy_score_list = [] for train_index, test_index in loo.split(iris.data):clf_svc.fit(iris.data[train_index], iris.target[train_index])prediction = clf_svc.predict(iris.data[test_index])mean_accuracy_score_list.append(accuracy_score(iris.target[test_index], prediction)) print(np.average(mean_accuracy_score_list)) 0.9793627184231215下面的例子更好地展示了,其效果:
X = np.ones(4) lpo = LeavePOut(p=2) for train, test in lpo.split(X):print("%s %s" % (train, test)) [2 3] [0 1] [1 3] [0 2] [1 2] [0 3] [0 3] [1 2] [0 2] [1 3] [0 1] [2 3]K-Fold
普通的K-Fold僅僅是折疊,除此之外,還有分層K-Fold則,則進(jìn)行的分層K-Fold.
from sklearn.model_selection import KFold,StratifiedKFold X = ["a", "b", "c", "d"] kf = KFold(n_splits=4) for train, test in kf.split(X):print("%s %s" % (train, test)) [1 2 3] [0] [0 2 3] [1] [0 1 3] [2] [0 1 2] [3] X = np.array([[1, 2, 3, 4],[11, 12, 13, 14],[21, 22, 23, 24],[31, 32, 33, 34],[41, 42, 43, 44],[51, 52, 53, 54],[61, 62, 63, 64],[71, 72, 73, 74]])y = np.array([1, 1, 0, 0, 1, 1, 0, 0])stratified_folder = StratifiedKFold(n_splits=4, random_state=0, shuffle=False) for train_index, test_index in stratified_folder.split(X, y):print("Stratified Train Index:", train_index)print("Stratified Test Index:", test_index)print("Stratified y_train:", y[train_index])print("Stratified y_test:", y[test_index],'\n') Stratified Train Index: [1 3 4 5 6 7] Stratified Test Index: [0 2] Stratified y_train: [1 0 1 1 0 0] Stratified y_test: [1 0] Stratified Train Index: [0 2 4 5 6 7] Stratified Test Index: [1 3] Stratified y_train: [1 0 1 1 0 0] Stratified y_test: [1 0] Stratified Train Index: [0 1 2 3 5 7] Stratified Test Index: [4 6] Stratified y_train: [1 1 0 0 1 0] Stratified y_test: [1 0] Stratified Train Index: [0 1 2 3 4 6] Stratified Test Index: [5 7] Stratified y_train: [1 1 0 0 1 0] Stratified y_test: [1 0]不過(guò)在實(shí)際的使用中我們更常用的是cross_val_score,一個(gè)封裝好的交叉驗(yàn)證方法,來(lái)進(jìn)行模型選擇,其中默認(rèn)的方法即為K-Fold,除此之外,我們還可以使用cross_val_predict來(lái)獲取預(yù)測(cè)結(jié)果,不過(guò)效果不一定是最好偶.
from sklearn.model_selection import cross_val_score scores_clf_svc_cv = cross_val_score(clf_svc,iris.data,iris.target,cv=5) print(scores_clf_svc_cv) print("Accuracy: %0.2f (+/- %0.2f)" % (scores_clf_svc_cv.mean(), scores_clf_svc_cv.std() * 2)) [0.96666667 1. 0.96666667 0.96666667 1. ] Accuracy: 0.98 (+/- 0.03) from sklearn.model_selection import cross_val_predict predicted = cross_val_predict(clf_svc, iris.data, iris.target, cv=10) accuracy_score(iris.target, predicted) 0.9733333333333334參考
- Sklearn中文文檔:交叉驗(yàn)證
- Sklearn官方文檔:數(shù)據(jù)分割器
更多內(nèi)容請(qǐng)參考我的博客,我會(huì)持續(xù)更新相關(guān)內(nèi)容
轉(zhuǎn)載于:https://www.cnblogs.com/fonttian/p/9162724.html
總結(jié)
- 上一篇: angularjs -- 路由监听
- 下一篇: 【Spark篇】---Spark初始