機器學習面試題集 - 詳解四種交叉驗證方法

本文結構:

  • 什麼是交叉驗證法?
  • 爲什麼用交叉驗證法?
  • 主要有哪些方法?優缺點?
  • 各方法應用舉例?

什麼是交叉驗證法?

它的基本思想就是將原始數據(dataset)進行分組,一部分做爲訓練集來訓練模型,另一部分做爲測試集來評價模型。


爲什麼用交叉驗證法?

  1. 交叉驗證用於評估模型的預測性能,尤其是訓練好的模型在新數據上的表,可以在一定程度上減小過擬合。
  2. 還可以從有限的數據中獲取儘可能多的有效信息。
  3. 可以選擇出合適的模型

主要有哪些方法?

  • Holdout Method
  • K-Fold CV
  • Leave One out CV
  • Bootstrap Methods

1. 留出法 (holdout cross validation)

這種方法是最簡單的交叉驗證:

在機器學習任務中,拿到數據後,我們首先會將原始數據集分爲三部分:訓練集、驗證集和測試集
訓練集用於訓練模型,驗證集用於模型的參數選擇配置,測試集對於模型來說是未知數據,用於評估模型的泛化能力。

這個方法操作簡單,只需隨機把原始數據分爲三組即可。

不過如果只做一次分割,它對訓練集、驗證集和測試集的樣本數比例,還有分割後數據的分佈是否和原始數據集的分佈相同等因素比較敏感,
不同的劃分會得到不同的最優模型,
而且分成三個集合後,用於訓練的數據更少了。


2. k 折交叉驗證(k-fold cross validation)

於是有了 k 折交叉驗證(k-fold cross validation) 加以改進:

k 折交叉驗證通過對 k 個不同分組訓練的結果進行平均來減少方差,
因此模型的性能對數據的劃分就不那麼敏感

  • 第一步,不重複抽樣將原始數據隨機分爲 k 份。
  • 第二步,每一次挑選其中 1 份作爲測試集,剩餘 k-1 份作爲訓練集用於模型訓練。
  • 第三步,重複第二步 k 次,這樣每個子集都有一次機會作爲測試集,其餘機會作爲訓練集。
  • 在每個訓練集上訓練後得到一個模型,
  • 用這個模型在相應的測試集上測試,計算並保存模型的評估指標,
  • 第四步,計算 k 組測試結果的平均值作爲模型精度的估計,並作爲當前 k 折交叉驗證下模型的性能指標。

k 一般取 10,
數據量小的時候,k 可以設大一點,這樣訓練集佔整體比例就比較大,不過同時訓練的模型個數也增多。
數據量大的時候,k 可以設小一點。


3. 留一法(Leave one out cross validation)

當 k=m 即樣本總數時,叫做 ** 留一法(Leave one out cross validation)**,
每次的測試集都只有一個樣本,要進行 m 次訓練和預測。

這個方法用於訓練的數據只比整體數據集少了一個樣本,因此最接近原始樣本的分佈。
但是訓練複雜度增加了,因爲模型的數量與原始數據樣本數量相同。
一般在數據缺乏時使用。
樣本數很多的話,這種方法開銷很大。

此外:

  1. 多次 k 折交叉驗證再求均值,例如:10 次 10 折交叉驗證,以求更精確一點。
  2. 劃分時有多種方法,例如對非平衡數據可以用分層採樣,就是在每一份子集中都保持和原始數據集相同的類別比例。
  3. 模型訓練過程的所有步驟,包括模型選擇,特徵選擇等都是在單個摺疊 fold 中獨立執行的。

4. Bootstrap

還有一種比較特殊的交叉驗證方式,Bootstrapping: 通過自助採樣法,
即在含有 m 個樣本的數據集中,進行 m 次有放回地隨機抽樣,組成的新數據集作爲訓練集。

這種方法,有的樣本會被多次採樣,也會有一次都沒有被選擇過的樣本,原數據集中大概有 36.8% 的樣本不會出現在新組數據集中,這些沒有被選擇過的數據作爲驗證集。

優點是訓練集的樣本總數和原數據集一樣都是 m,並且仍有約 1/3 的數據不被訓練而可以作爲測試集,對於樣本數少的數據集,就不用再由於拆分得更小而影響模型的效果。
缺點是這樣產生的訓練集的數據分佈和原數據集的不一樣了,會引入估計偏差。
此種方法不是很常用,除非數據量真的很少。

36.8% 是怎麼得到的?

各方法應用舉例?

1. 留出法 (holdout cross validation)

下面例子,一共有 150 條數據:

>>> import numpy as np
>>> from sklearn.model_selection import train_test_split
>>> from sklearn import datasets
>>> from sklearn import svm

>>> iris = datasets.load_iris()
>>> iris.data.shape, iris.target.shape
((150, 4), (150,))

用 train_test_split 來隨機劃分數據集,其中 40% 用於測試集,有 60 條數據,60% 爲訓練集,有 90 條數據:

>>> X_train, X_test, y_train, y_test = train_test_split(
...     iris.data, iris.target, test_size=0.4, random_state=0)

>>> X_train.shape, y_train.shape
((90, 4), (90,))
>>> X_test.shape, y_test.shape
((60, 4), (60,))

用 train 來訓練,用 test 來評價模型的分數。

>>> clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train)
>>> clf.score(X_test, y_test)                           
0.96...

2. k 折交叉驗證(k-fold cross validation)

最簡單的方法是直接調用 cross_val_score,這裏用了 5 折交叉驗證:

>>> from sklearn.model_selection import cross_val_score
>>> clf = svm.SVC(kernel='linear', C=1)
>>> scores = cross_val_score(clf, iris.data, iris.target, cv=5)
>>> scores                                              
array([ 0.96...,  1.  ...,  0.96...,  0.96...,  1.        ])

得到最後平均分爲 0.98,以及它的 95% 置信區間:

>>> print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
Accuracy: 0.98 (+/- 0.03)

我們可以直接看一下 K-fold 是怎樣劃分數據的:
X 有四個數據,把它分成 2 折,
結果中最後一個集合是測試集,前面的是訓練集,
每一行爲 1 折:

>>> 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))
[2 3] [0 1]
[0 1] [2 3]

同樣的數據 X,我們看 LeaveOneOut 後是什麼樣子,
那就是把它分成 4 折,
結果中最後一個集合是測試集,只有一個元素,前面的是訓練集,
每一行爲 1 折:

>>> from sklearn.model_selection import LeaveOneOut

>>> X = [1, 2, 3, 4]
>>> loo = LeaveOneOut()
>>> for train, test in loo.split(X):
...     print("%s %s" % (train, test))
[1 2 3] [0]
[0 2 3] [1]
[0 1 3] [2]
[0 1 2] [3]

推薦學習資料:
https://www.youtube.com/watch?v=vQBIi3Bvt2M&t=105s
http://scikit-learn.org/stable/modules/cross_validation.html
https://ljalphabeta.gitbooks.io/python-/content/kfold.html
http://www.csuldw.com/2015/07/28/2015-07-28%20crossvalidation/
《百面機器學習》
https://ww3.arb.ca.gov/research/weekendeffect/carb041300/sld012.htm


大家好!我是 Alice,歡迎進入 機器學習面試題集 系列!

這個系列會以《百面機器學習》的學習筆記爲主線,除了用導圖的形式提煉出精華,還會對涉及到的重要概念進行更深度的解釋,順便也梳理一下機器學習的知識體系。

歡迎關注我,一起交流學習!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章