机器学习的练功方式(五)——模型选择及调优
文章目錄
- 5 模型選擇及調優
- 5.1 數據增強
- 5.2 過擬合
- 5.3 交叉驗證
- 5.4 超參數搜索——網格搜索
5 模型選擇及調優
5.1 數據增強
有時候,你和你的老板說你數據不夠,它是不會理你的。老板會發問:為什么你是做機器學習的要那么多數據干嘛,讓機器去做不就行了。
對于這種問題有時候即使無語但你也不能正面拆穿,否則你的工作就不用干了。而為了解決數據集不足的問題,我們通常會采用數據增強。
這個名詞看似高大上,實際上就是把數據集經過某些變換,從而產生新的數據集。
這種方法多用于圖片識別上,將圖片結果左右對稱變換,或反轉,或偏移角度來達到擁有更多數據集的目的。
5.2 過擬合
統計學習的目的是使學到的模型不僅對已知數據而且對未知數據都能有很好的預測能力。不同的學習方法會給出不同的模型。當損失函數給定時,基于損失函數的模型的訓練誤差和模型的測試誤差就自然成為學習方法評估的標準。注意,統計學習方法具體采用的損失函數未必是評估時使用的損失函數。當然,讓兩者一致是比較理想的。
訓練誤差的大小,對判斷給定的問題是不是一個容易學習的問題是有意義的,但本質上不重要。測試誤差反映了學習方法對未知的測試數據集的預測能力,是學習中的重要概念。顯然,給定兩種學習方法,測試誤差小的方法具有更好的預測能力,是更有效的方法。
通常將學習方法對未知數據的預測能力稱為泛化能力。
當假設空間含有不同復雜度的模型時,就要面臨模型選擇的問題。我們希望選擇或學習一個合適的模型。如果在假設空間中存在真模型,那么所選擇的模型應該逼近真模型。具體地,所選擇的模型要與真模型的參數個數相同,所選擇的模型的參數向量與真模型的參數向量相近。
如果一味追求提高對訓練數據的預測能力,所選模型的復雜度則往往會比真模型更高。這種現象稱為過擬合。過擬合是指學習時選擇的模型所包含的參數過多,以至于出現這一模型對已知數據預測的很好,但對未知數據預測得很差的現象。可以說模型選擇旨在避免過擬合并提高模型的預測能力。
也就是說,上述的話翻譯成人話就是,我們不要那種能夠完全貼合訓練集的函數,那種函數訓練出來訓練集在上面跑挺牛逼,一到測試集就不行了。我們需要的是那種在訓練集跑的差不多,對于測試集跑出來效果也很好的那種函數。
現在我們有以上的數據集,我們要選擇一個模型去擬合真模型,也就是M=0時圖中畫的曲線,那條曲線即為真模型。當然了,根據我們上面所說,我們要的是做到“差不多”即可,我們不要精度完全一樣或者超過真模型。
當我們M=1,選擇的是一條直線,這種模型其實是罔顧事實的做法,我們完全不考慮擬合的效果,一上來就亂套模型,這樣會導致擬合數據的效果賊差。這種在古老的文獻中稱為“欠擬合”現象。
當M=3時,我們選擇的模型已經接近數據所對應的真模型了,已經幾乎擬合了,這時候的模型符合測試誤差最小的學習目的了。
當M=9時,這時候就是所謂的過擬合現象了,由于參數設置過多,導致這條曲線幾乎穿過了我們已知的所有的數據點。的確,他對已知數據預測很好(穿過了嘛),但是他對未知數據卻預測很差(說不定下一個點不在這條線上,這就導致前面預測很準,后面誤差越來越大)。
簡單來說,想解決過擬合,實際上無非就是選擇復雜度適當的模型,以達到使測試誤差最小的學習目的。我們常用的模型選擇方法:正則化和交叉驗證。關于正則化的學習我們在后面的學習中會接觸到,我們這里要提到的是關于交叉驗證。
5.3 交叉驗證
交叉驗證(cross validation)簡單來說就是將拿到的訓練數據,再次分為訓練集和驗證集。其中驗證集和測試集的功能一樣,都是對訓練集訓練出來的模型進行評估。而交叉驗證方法就是將訓練集劃分為訓練集+測試集,測試集通常占1份,而訓練集占k-1份,通過四次測試,每次更換不同的驗證集來達到在有限的數據集中得出不同精度,得出4組模型結果;得出結果后取平均值作為最終結果。我們把上述的做法稱為K折交叉驗證。
K折交叉驗證示意圖如下:
雖然K折交叉驗證能夠在k均值算法中起到優化K值的效果,那么如何來選取K值呢?什么時候才是最好呢?這就要進入我們的下一小節了。
5.4 超參數搜索——網格搜索
通常情況下,有很多參數時需要手動指定的(如K-近鄰算法中的K值),這種叫做超參數。但是手動指定不準且計算復雜,所以我們要對模型預設幾種超參數組合,每組超參數都采用交叉驗證來進行評估,最后選出最優參數組合建立模型。
知道原理了就是動手寫代碼的時刻,我們看一下sklearn中有哪些庫供我們調用。
sklearn.model_selection.GridSearchCV(estimator,param_grid = None,cv = None)
該API可以對估計器的指定參數值進行詳盡搜索
- estimator:估計器對象
- param——grid:估計器參數,對應到knn中可以傳入多個k值建立多個模型,以此評估哪個模型最好,傳入時要用字典形式,如{“n_neighbors”:[1,3,5]}
- cv:指定幾折交叉驗證,常用10折交叉驗證
fit():輸入訓練數據
score():準確率
通過調用以下屬性可以查看結果:
- 最佳參數:best_params_
- 最佳結果:best_score_
- 最佳估計器:best_estimator_
- 交叉驗證結果:cv_results_
知道上面的原理,讓我們對前一講的KNN分類鳶尾花代碼優化一下吧!
from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import GridSearchCVdef knn_iris():"""用KNN算法對鳶尾花進行分類"""# 1 導入數據集iris = load_iris()# 2 劃分數據集x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)# 3 特征工程:標準化transfer = StandardScaler()x_train = transfer.fit_transform(x_train)x_test = transfer.transform(x_test)# 4 實例化KNN算法預估器estimator = KNeighborsClassifier()# 選用合適的K值來選擇多個模型param_dict = {"n_neighbors": [1, 3, 5, 7, 9, 11]}# 加入超參數網格搜索和交叉驗證estimator = GridSearchCV(estimator, param_grid=param_dict, cv=10)estimator.fit(x_train, y_train)# 5 模型評估# 方法1 直接比對真實值和預測值y_predict = estimator.predict(x_test)print("y_predict:\n", y_predict)print("直接對比真實值和預測值:\n", y_test == y_predict)# 方法2 計算準確率score = estimator.score(x_test, y_test)print("準確率為:\n", score)# 查看最佳參數print("KNN模型最佳參數:\n", estimator.best_params_)print("最佳結果:\n", estimator.best_score_)print("最佳估計器:\n", estimator.best_estimator_)print("交叉驗證結果:\n", estimator.cv_results_)# 調用方法 knn_iris()總結
以上是生活随笔為你收集整理的机器学习的练功方式(五)——模型选择及调优的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在VS2019 C++ 中实现Socke
- 下一篇: Hello RoboCupRescue(