sklearn快速入门教程:(四)模型自动调参
上個教程中我們已經看到在sklearn中調用機器學習模型其實非常簡單。但要獲得較好的預測效果則需要選取合適的超參數。在實際的項目中其實也有不少參數是由工程師借助其經驗手動調整的,但在許多場景下這種方式仍然是很難行得通的。sklearn提供了十分簡單易用的調參方法,可以輕松地實現對各類模型的調參。但調參的機制中涉及的概念相對較多,因此本文需要羅列一些必要的原理。
一、 調參的基本思想–交叉驗證(Cross Validation)
根據上篇教程的內容我們容易想到,調參的根本目的實際上就是要找到一組合適的超參數,使得模型具有列好的效果,而更專業的說法則是希望讓模型得到更好的泛化性能(可以簡單理解為樣本外的預測效果)。目前使用最為廣泛的調參方法之一便是交叉驗證,它的思路非常簡單:
- 將樣本拆分為 kkk 個子集,用其中 k?1k-1k?1個子集的數據訓練模型,再在剩下的一個子集上驗證模型的性能。當所有子集都被作為測試集輪完一圈之后,計算模型在所有子集上的平均性能。
- 對每一組超參數對應模型執行上述操作,選出平均性能最好的一組參數作為最優參數。
sklearn官方文檔中給出了這樣一張圖很清楚地描述了這個過程(k-fold cross validation)。
至于為何要這樣做,其理論相對較深,建議初學時不要太過于糾結,先用會即可(因為涉及較深的統計學知識)。其根本目的即是尋找出一組最優超參數,使其在各種樣本組合下的平均性能都能達到最優,從而認為這組參數能夠使得模型具有最強的泛化性能。
二、 實現交叉驗證需要考慮哪些細節
上述描述其實已經給出了k?k-k?折交叉驗證的基本實現思路,但這里還有兩個細節的問題沒有討論:
- 子集應該如何劃分?
- 備選的參數組合應該如何生成?
- 評價模型性能的指標選什么?
實際上這兩個問題非常復雜,子集劃分可以有許多種方式:
- k-fold: 隨機將訓練集劃分為kkk個
- leave-one-out: 將子集劃分為nnn 個,即每個子集只有一個樣本
- hold-out: 將nnn個樣本中的mmm個隨機挑出作為測試集(當然也可以指定測試集)
備選參數的選擇也有多種方式:
- grid-search: 即給出每個超參數的備選范圍,對所有組合進行窮舉
- random search: 以某種方式生成多種超參數的組合,窮舉所有隨機生成的結果
至于模型的評價指標,也是層出不窮:
- 分類問題:分類精度、平衡精度、平均精度等
- 回歸問題:最大誤差、均方誤差、均方根誤差等
這些選擇,通常也只能根據具體問題結合經驗進行選擇。(這的確也是一件很麻煩的事情 )。
三、 sklearn中的實現方式(以GridSearchCV和SVR為例)
GridSearchCV即網格搜索的交叉驗證法,這是最為常用的方法之一。在sklearn的官方文檔中給出了該方法詳細的輸入參數和說明,而通常我們只需要考慮以下幾個參數即可:
| estimator | 被調參的模型,即上一教程中提到的各類模型的class,比如tree,RandomForestRegressor等具體模型,以對象實例的形式傳遞。 |
| param_grid | 被調參數的grid,以字典形式傳遞。 |
| scoring | 模型評價指標,給出具體指標的名稱字符串即可,如'accuracy','neg_mean_squared_error'等。 |
| cv | 這個變量比較復雜。一般來說我們直接取整數即可,也就是k-fold中的k即可。特別地當k等于樣本個數時,它就是留一法。 |
為方便起見我們先用官方給出的示例代碼做一些說明:
>>> from sklearn import svm, datasets >>> from sklearn.model_selection import GridSearchCV >>> iris = datasets.load_iris() >>> parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]} >>> svc = svm.SVC() >>> clf = GridSearchCV(svc, parameters) >>> clf.fit(iris.data, iris.target) GridSearchCV(estimator=SVC(),param_grid={'C': [1, 10], 'kernel': ('linear', 'rbf')}) >>> sorted(clf.cv_results_.keys()) ['mean_fit_time', 'mean_score_time', 'mean_test_score',...'param_C', 'param_kernel', 'params',...'rank_test_score', 'split0_test_score',...'split2_test_score', ...'std_fit_time', 'std_score_time', 'std_test_score']這里面需要特別說明有幾個問題:
(1)參數網格的設定(第4行)
變量parameters即是param_grid的值??梢钥吹剿且?#61;=字典(dict)==的形式給出的。一般在寫程序的時候如果參數較多,我們其實更喜歡看這樣的寫法:
parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}這里就需要回顧一下python的基本數據結構。字典類型的本質其實就是典型的key-value結構。在花括號中每一個逗號分隔的就是字典的一條記錄,這條記錄中冒號左邊是key的名稱,用單引號,冒號右邊則是value。注意這里非常非常舒服的一點是這個value可以是任意的合法類型。那么這樣一來,我們只需要考慮每個參數的取值范圍即可,非常方便。
在設好了這樣的GridSearchCV中我們只需要將這樣的一個字典傳入,函數將自動根據設定的范圍對每種組合進行窮舉。比如上面這段代碼實際上給出的是這樣的一種組合:
kernel = 'linear', C = 1 kernel = 'linear', C = 10 kernel = 'rbf', C = 1 kernel = 'rbf', C = 10試想如果我們有非常多的超參數需要調(比如隨機森林就有非常多的超參數),如果自己動手寫循環那么一個參數就是一個循環,非常麻煩。而sklearn則給我們提供了一種非常簡單的實現方式。
(2)返回類型
GridSearchCV從最后一行代碼中可以看到,返回值的類型其實很復雜,內容特別多。而這里我們首先關注的就是兩個東西:
- 最優參數 best_params_:它是以字典的形式存儲,比如上述代碼運行完成后,可以直接通過clf.best_params_來查看具體的最優參數,并且保留了原參數名。
- **最優模型 **best_estimator_ : best_estimator_就是在整個過程中表現最好的那一個模型(平均性能最優)。它的本質就是sklearn中的estimator,再說得直接一點,如果被調的模型是SVR,那么它就是SVR;如果被調的是tree那么它就是tree。根據我們前面所講,如果想要用它來進行預測,則直接對它進行操作即可,即調用clf.best_estimator.predict(X)。
上述兩個參數是與我們最直接關心的,當然還有更多的詳細參數,這些內容在具體問題中對應讀取查看就可以了。
另外,我們之前提到過除了GridSearchCV之外還有另外的隨機調參方法,它叫做RandomizedSearchCV,而這里隨了對隨機方法的指定以外,基本用法和其它參數的設定也幾乎一模一樣。
四、 其它問題
(1)并行計算
并行計算是sklearn中的另一個亮點,它對一些能夠并行的方法提前進行了封裝,在使用的時候只需要簡單一個參數即可。在GridSearchCV中,只需要在輸入參數中設定n_jobs大于等于2即可,這個參數即是代表需要用來并行的核心數量。比如:
# 使用兩個核心并行 clf = GridSearchCV(svc, parameters, n_jobs =2) # 使用全部的核心并行 clf = GridSearchCV(svc, parameters, n_jobs =-1)另外特別要注意的一點是,sklearn的并行沒有任何對硬件的保護機制。簡單地說就是它會盡一切可能壓榨CPU的效率,在能超頻的時候它一點也不會客氣。這在用大量級的數據集,網格較密和核心較多的時候要特別小心。因為超頻的代價就是CPU的溫度會瞬間飆升,至于會不會引起硬件的其它問題目前還沒遇到,但一定要慎用。
(2)自定義調參
從常理上講,sklearn本身是開源的,源碼實際上可以進行修改。不過sklearn本身也提供了一些方便的接口供用戶進行自定義。比如上面提到的評價指標,sklearn就提供了詳細的文檔供開發者參考。比如:
自定義指標:https://scikit-learn.org/stable/modules/model_evaluation.html#scoring
使用多指標:https://scikit-learn.org/stable/modules/grid_search.html#multimetric-grid-search
當然,集合的劃分等問題也可以自定義,可以參考:
CV Splitter: https://scikit-learn.org/stable/glossary.html#term-cv-splitter
五、小結
那么到這里,從如何調用sklearn的基本庫到如何進行自動調參就全部講解完畢。學到這一步相信許多同學已經可能在標準數據集和一些自己的數據集上調出較好的模型了。更多的內容待后續繼續講解。
- sklearn快速入門教程:(一)準備工作
- klearn快速入門教程:(二)線性回歸
- sklearn快速入門教程:(三)機器學習的通用模式及實現方法
- sklearn快速入門教程:(五)集成學習
總結
以上是生活随笔為你收集整理的sklearn快速入门教程:(四)模型自动调参的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sklearn快速入门教程:(三)机器学
- 下一篇: sklearn快速入门教程:(五)集成学