什么是交叉驗證?
它的基本思想就是將原始數據(dataset)進行分組,一部分做為訓練集來訓練模型,另一部分做為測試集來評價模型。
主要是用於小部分數據集中。通過圖片可以看出,划分出來的測試集(test set)是不可以動的,因為模型參數的優化是使用驗證集(validation set),這個結果是有偏差的,所以需要一個沒見過的新數據集進行泛化能力測試。
為什么用交叉驗證法?
- 交叉驗證用於評估模型的預測性能,尤其是訓練好的模型在新數據上的表現,可以在一定程度上減小過擬合。
- 還可以從有限的數據中獲取盡可能多的有效信息。
交叉驗證用途?
交叉驗證(Cross Validation)是用來驗證分類器的性能一種統計分析方法,基本思想是把在某種意義下將原始數據(dataset)進行分組,一部分做為訓練集 (training set),另一部分做為驗證集(validation set),當然還要留出測試集部分(test set),首先用訓練集對分類器進行訓練,在利用驗證集來優化模型的超參數(hyperparameter),最后來使用測試集來測試模型的泛化能力。
- 可以用來選擇模型
- 大致判斷當前模型狀態是否處於過擬合
- 交叉驗證是一種評估統計分析、機器學習算法對獨立於訓練數據的數據集的泛化能力(generalize)。(過擬合的泛化能力差)
交叉驗證的方法?
1. 留出法(holdout cross validation)
在機器學習任務中,拿到數據后,我們首先會將原始數據集分為三部分:訓練集、驗證集和測試集。
訓練集用於訓練模型,
驗證集用於模型的參數選擇配置,
測試集對於模型來說是未知數據,用於評估模型的泛化能力。
這個方法操作簡單,只需隨機把原始數據分為三組即可。
不過如果只做一次分割,它對訓練集、驗證集和測試集的樣本數比例,還有分割后數據的分布是否和原始數據集的分布相同等因素比較敏感,不同的划分會得到不同的最優模型,而且分成三個集合后,用於訓練的數據更少了。
2. k折交叉驗證(k-fold cross validation)
k折交叉驗證是對留出法的改進,
k 折交叉驗證通過對 k 個不同分組訓練的結果進行平均來減少方差,因此模型的性能對數據的划分就不那么敏感。
- 第一步,不重復抽樣將原始數據隨機分為 k 份。
- 第二步,每一次挑選其中 1 份作為測試集,剩余 k-1 份作為訓練集用於模型訓練。
- 第三步,重復第二步 k 次,這樣每個子集都有一次機會作為測試集,其余機會作為訓練集。
- 在每個訓練集上訓練后得到一個模型,
- 用這個模型在相應的測試集上測試,計算並保存模型的評估指標,
- 第四步,計算 k 組測試結果的平均值作為模型精度的估計,並作為當前 k 折交叉驗證下模型的性能指標。
k 一般取 10,
數據量小的時候,k 可以設大一點,這樣訓練集占整體比例就比較大,不過同時訓練的模型個數也增多。
數據量大的時候,k 可以設小一點。
3.留一法(leave one out cross validation)
這個方法用於訓練的數據只比整體數據集少了一個樣本,因此最接近原始樣本的分布。
但是訓練復雜度增加了,因為模型的數量與原始數據樣本數量相同。
一般在數據缺乏時使用。
此外:
- 多次 k 折交叉驗證再求均值,例如:10 次 10 折交叉驗證,以求更精確一點。
- 划分時有多種方法,例如對非平衡數據可以用分層采樣,就是在每一份子集中都保持和原始數據集相同的類別比例。
- 模型訓練過程的所有步驟,包括模型選擇,特征選擇等都是在單個折疊 fold 中獨立執行的。
4.自助采樣法(bootstrapping)
通過自助采樣法,即在含有 m 個樣本的數據集中,每次隨機挑選一個樣本,再放回到數據集中,再隨機挑選一個樣本,這樣有放回地進行抽樣 m 次,組成了新的數據集作為訓練集。
這里會有重復多次的樣本,也會有一次都沒有出現的樣本,原數據集中大概有 36.8% 的樣本不會出現在新組數據集中。
優點是訓練集的樣本總數和原數據集一樣都是 m,並且仍有約 1/3 的數據不被訓練而可以作為測試集。
缺點是這樣產生的訓練集的數據分布和原數據集的不一樣了,會引入估計偏差。
此種方法不是很常用,除非數據量真的很少。
具體實現
1. 留出法(holdout cross validation)
from sklearn import datasets from sklearn.model_selection import train_test_split iris = datasets.load_iris() X_trainval, X_test, y_trainval, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=0) X_train, X_val, y_train, y_val = train_test_split(X_trainval, y_trainval, test_size=0.2, random_state=0) # 數據集分布為:訓練集0.64, 驗證集0.16, 測試集0.2 print(X_train.shape, y_train.shape) print(X_val.shape, y_val.shape) print(X_test.shape, y_test.shape)
2. k折交叉驗證(k-fold cross validation)
import numpy as np from sklearn.model_selection import KFold X = ["a", "b", "c", "d"] kf = KFold(n_splits=2) for train, test in kf.split(X): print("%s %s" % (train, test))
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()))