1.過擬合的問題
1.1 過擬合的定義
開篇首先談一下機器學習模型的過擬合問題。什么是過擬合?簡單來講,當 train set 誤差較小,而 test set 誤差較大時,我們即可認為模型過擬合。這句話表達的另一層意思是,模型評估指標的方差(variance)較大,即可認為模型過擬合。另外,無論監督學習還是非監督學習,均存在過擬合的問題。
1.2 如何判斷是否過擬合
一般來講,判斷模型是否過擬合可采用學習曲線(learning curve),通過畫學習曲線圖可以直觀的看出 train set 和 test set 的誤差隨着訓練樣本數量(number of training samples)的變化。在學習曲線中,如果訓練准確度(training accuracy)和測試准確度(或驗證准確度 validation accuracy)兩條曲線相距較遠,則說明模型的方差較大(一般情況下,訓練精度都會高於測試精度),模型過擬合。而我們期望的理想狀況是,訓練集和測試集的兩條精度曲線相距較近,並且隨着訓練樣本數量的增加,越來越近,逐漸收斂。
當然,還有最簡單的判斷模型是否過擬合的方法,就是通過training accuracy 和 test accuracy 數值大小,直觀的判斷模型是否過擬合。例如,訓練集的准確率為90%,而測試集的准確率為70%,那么我們可以認為模型過擬合。不過,這種方法沒有明確的判斷標准,完全靠個人的主觀判斷——“感覺訓練和測試的誤差相差有點大,有可能過擬合”。還是剛才的例子,如果測試集的誤差為80%,那么我們是否還能下結論模型過擬合呢?這個時候你可以說,訓練和測試准確率相差10個百分點,也挺大的,還是有很大可能過擬合的。但是,也有可能,模型的平均誤差率在85%左右,在95%的置信度下,模型預測准確率的置信區間恰為 [80%,90%],那么此時模型並沒有過擬合。當然,后一種情況出現的概率相對較小,我只是想表達一下,這種直觀的判斷方法是不一定准確的,不過方便的是,我們不用畫學習曲線圖啊,多省事。因此,總的來講,我們可以先通過訓練集和測試集准確率的大小,直觀的判斷模型是否過擬合;當沒有把握斷定模型是否過擬合時,再借助學習曲線。
1.3 過擬合的原因
不知道各位有沒有聽過這樣一種說法,就是沒有任何一種算法能夠完全避免過擬合。其實,我們討論模型的過擬合,實際上是針對模型的泛化性能進行研究。首先我覺得,模型的泛化能力如何,一方面與模型自身的特性有關,另一方面與所研究的數據也有關。如果我們的數據質量較高,並且呈現出某種特有的“規律”,那么對於新數據,模型具有非常好的泛化能力,那么我們可以說模型不存在任何過擬合問題。但是,理想是飽滿的,現實是骨感的。在實際生產環境中,絕對不可能出現質量很高的數據,而數據所蘊含的規律或特性也不是那么容易學習。因此,即便用再高大上的模型,再花多少時間優化模型的超參數和參數,依然很難再提高模型的泛化能力。生活中我們常說一句話:天賦決定上限,努力決定下限。我想套用這句話說:數據決定上限,模型決定下限。
接下來,我想談一下機器學習中的一個算法——隨機森林。為什么點名道姓要聊它?原因很簡單,我們在談到不同模型的優缺點時,給隨機森林貼的標簽之一,就是它能有效的避免過擬合。(我看過很多人說的更激進,直接說隨機森林不會出現過擬合。)隨機森林算法,出自於集成學習算法家族中的bagging,往往是我們解決決策樹過擬合問題的有效方案之一。貌似隨機森林算法的作者說過隨機森林算法不會出現過擬合,也有人說他本意表達的意思是,隨着樹的增加,測試集的誤差不會增大,而是趨於收斂;同時,看到有人說隨機森林在噪聲較大的數據集上依然會表現出過擬合(這就是我前面說的數據的影響,不能把數據的鍋甩給模型啊)。我自己在使用過程中發現,當隨機森林樹的棵樹較少時,例如sklearn中默認的10棵,這種情況,模型的方差依然會很大。所以用隨機森林時,可以將樹的數量設置多一些(R語言中隨機森林默認好像是100棵樹),不過樹太多的話,模型訓練時間長、對於計算資源的占用較大。
網上有很多關於隨機森林是否會產生過擬合的激烈討論,這里也分享我在知乎上看到的一個帖子:https://www.zhihu.com/question/23578594 。最后,對於隨機森林是否會產生過擬合的問題,總結一句:隨機森林能有效的避免過擬合,但如果數據質量較差(例如噪聲較大),那么模型的泛化能力也會受到很大影響。(貌似這樣說才不顯得那么武斷。。)
最后總結一下,導致過擬合的原因大概有以下幾點:
- 模型復雜度過高
- 訓練數據過少
- 數據噪聲較大
2.交叉驗證
通過對過擬合的討論之后,我們在運用機器學習算法模型時,要考慮兩個問題:(1) 如何驗證模型是否過擬合?(2) 如何避免過擬合?
關於如何驗證模型是否過擬合,上一節已經簡單討論。接下來想針對python機器學習算法模塊sklearn中交叉驗證相關函數的使用加以說明。
2.1 cross_validate 與 cross_val_score
這兩個函數的區別是,cross_validate允許指定多個指標進行評估,同時,它還可以顯示交叉驗證訓練集的評估score,而cross_val_score只能顯示測試集的score。當我們需要直觀判斷模型是否過擬合時,可以采用 cross_validate 觀察訓練和測試集評估score相差的大小。而cross_val_score可以用作對模型性能的綜合評估。
2.2 如何利用交叉驗證避免過擬合?
避免模型過擬合的方法,總結大概以下幾點:
- 重新清洗數據(刪除稀疏特征、對噪聲數據進行處理(刪除/替換))
- 重新采樣(改變采樣方法等)
- 增加訓練數據
- 采用交叉驗證訓練模型
- 重新篩選特征
- 降低模型復雜度(增加正則項:L1,L2)
- dropout(神經網絡中,讓神經元一定的概率不工作)
本文主要探討一下如何利用交叉驗證來避免模型過擬合。
首先,我們要明確一下交叉驗證的作用是什么,什么場景下會用到交叉驗證。
第一個作用就是對模型的性能進行評估。當我們通過一次划分樣本對模型進行訓練和測試時,由於樣本划分的偶然性,會導致我們對模型的評估不准確。因此,可以采用交叉驗證對模型進行評估(一般采用5折或10折,sklearn默認采用的是3折),以 n 折交叉驗證結果的均值,作為模型的性能評估。
第二個作用就是用來避免過擬合。例如當我們進行10折交叉驗證時,訓練了10次,得到了10個模型,每個模型的參數也是不同的,那么我們究竟用哪個模型作為我們最終的模型呢?答案是:一個都不用!我們要利用全量數據重新訓練出一個最終模型!
如果你覺得有點迷糊的話不用急,我們一起來梳理一下。我們訓練模型是為了什么?是為了確定模型中的參數,例如多元回歸模型的系數、神經網絡各神經元的權重等。但是,有些模型除了參數還有超參數,例如KNN和KMeans的k值,支持向量機的C值,這些超參數是需要人為設定,沒有辦法讓模型自己學習得到,我們只能通過經驗或者多次訓練比較,主觀設定一個我們認為相對最優的值。而交叉驗證的作用,就是讓我們進行多次的模型訓練比較。例如,我們期望從 [ 1, 10, 100, 1000 ] 這幾個值中選擇一個最優值,作為支持向量機的C值。那么我們就得分別用這4個值進行10折交叉驗證(該過程經歷了40次模型的訓練測試),把每一次交叉驗證結果的均值進行比較,從而選擇出一個最優值。最優值選出來了,那么模型的超參數確定了,接下來,利用全量的數據(不要划分訓練集測試集,而是用全部的數據)進行模型訓練,訓練出來的模型才是我們的最終模型。在此過程中可以看出,交叉驗證幫助我們確定模型的超參數。這樣訓練出來的模型,是經過多次綜合比較得出的相對最優模型,在一定程度上可以避免過擬合的問題,這就是為什么我們會說交叉驗證可以避免過擬合。
關於交叉驗證和過擬合的問題,我就先談這么多吧。(對於文章中表達的觀點,歡迎指正與補充,謝謝。)
