机器学习中的数据集划分问题
留出法(hold-out)
使用 n:m and n + m =1 的形式對原數(shù)據(jù)進(jìn)行分割,例如 train : test = 7 : 3 or train : test = 6.5 : 3.5 但是這種相對原始的處理方式效果并不好,缺點如下:
- 缺點一:浪費數(shù)據(jù)
- 缺點二:容易過擬合,且矯正方式不方便
這時,我們需要使用另外一種分割方式-交叉驗證 或者 留P法(leave P out)
LOO 留一法 or LPO 留P法
LOO : 對于整個數(shù)據(jù)集而言,每次選取一個樣本作為驗證集,其余樣本作為訓(xùn)練集
LPO : 對于整個數(shù)據(jù)集而言,每次選取P個樣本作為驗證集,其余樣本作為訓(xùn)練集
LOO的好處在于,避免的數(shù)據(jù)的浪費,但是同時也擁有了,更高的性能開銷
一般LOO相對于 K-Fold 而言,擁有更高的方差,但是對于方差占主導(dǎo)的情況時,LOO可能擁有比交叉驗證更強的能力.
K-Fold
KFold 將所有的樣例劃分為 k 個組,稱為折疊 (fold) (如果 k = n, 這等價于 Leave One Out(留一) 策略),都具有相同的大小(如果可能)。預(yù)測函數(shù)學(xué)習(xí)時使用 k - 1 個折疊中的數(shù)據(jù),最后一個剩下的折疊會用于測試。在集成算法Stacking中就使用了這種方式(Bagging則為子采樣,也是很有趣的方式,之前有介紹)
注意
而 i.i.d 數(shù)據(jù)是機器學(xué)習(xí)理論中的一個常見假設(shè),在實踐中很少成立。如果知道樣本是使用時間相關(guān)的過程生成的,則使用 time-series aware cross-validation scheme 更安全。 同樣,如果我們知道生成過程具有 group structure (群體結(jié)構(gòu))(從不同 subjects(主體) , experiments(實驗), measurement devices (測量設(shè)備)收集的樣本),則使用 group-wise cross-validation 更安全。
是否重復(fù)試驗與分層的問題
分層: 對于K-Fold而言,保持每個分組中的train : test 的比例大致相等
重復(fù): 即樣本的放回采樣,比如Bagging,訓(xùn)練集中部分樣本會重復(fù),部分樣本永遠(yuǎn)不會出現(xiàn)
重復(fù)分層: 對于Sklearn中的K-Fold而言,指實現(xiàn)了采樣中各個類別的比例與原數(shù)據(jù)集的各類別比例大致相等.
交叉驗證
LOO 與 LPO 的交叉驗證就是每個(或者每P個樣本)都作為驗證集一次,然后計算平均值,得出Score,K-Fold類似,不過不同的地方是分成了K折.
Sklearn中實現(xiàn)了便捷方法CV
快捷簡便的使用
加載數(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 非常相似,因為它通過從整個集合中刪除 p 個樣本來創(chuàng)建所有可能的 訓(xùn)練/測試集。對于 n 個樣本,這產(chǎn)生了 m 個 訓(xùn)練-測試 對, m 等于 n個樣本中 任意選取 p 個樣本不計順序自由組合的個數(shù) 。值得注意的是這種方式會導(dǎo)致計算開銷大幅增加,下面的例子要比上面的例子,多花費 m-n 的時間.從時間復(fù)雜度上看,在數(shù)據(jù)量較大時,而P較小時,時間復(fù)雜度為:T(n) = O(n^p),所以請慎用.
loo = LeavePOut(p=2) 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]不過在實際的使用中我們更常用的是cross_val_score,一個封裝好的交叉驗證方法,來進(jìn)行模型選擇,其中默認(rèn)的方法即為K-Fold,除此之外,我們還可以使用cross_val_predict來獲取預(yù)測結(jié)果,不過效果不一定是最好偶.
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中文文檔:交叉驗證
- Sklearn官方文檔:數(shù)據(jù)分割器
更多內(nèi)容請參考我的博客,我會持續(xù)更新相關(guān)內(nèi)容
總結(jié)
以上是生活随笔為你收集整理的机器学习中的数据集划分问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Gradient Tree Boosti
- 下一篇: Sklearn中的CV与KFold详解