集成學習(4) - 超參數優化

1. 參數和超參數

在上一節模型優化部分,我們對模型的優化都是對模型算法本身的改進,比如:嶺回歸對線性回歸的優化在于在線性回歸的損失函數中加入L2正則化項從而犧牲無偏性降低方差。但是,大家是否想過這樣的問題:在L2正則化中參數\lambda應該選擇多少?是0.01、0.1、還是1?到目前為止,我們只能憑經驗或者瞎猜,能不能找到一種方法找到最優的參數\lambda?事實上,找到最佳參數的問題本質上屬于最優化的內容,因為從一個參數集合中找到最佳的值本身就是最優化的任務之一,我們腦海中浮現出來的算法無非就是:梯度下降法、牛頓法等無約束優化算法或者約束優化算法,但是在具體驗證這個想法是否可行之前,我們必須先認識兩個最本質概念的區別。

  • 參數與超參數:
    我們很自然的問題就是嶺回歸中的參數\lambda和參數w之間有什么不一樣?事實上,參數w是我們通過設定某一個具體的\lambda 后使用類似于最小二乘法、梯度下降法等方式優化出來的,我們總是設定了\lambda是多少后才優化出來的參數w。因此,類似于參數w一樣,使用最小二乘法或者梯度下降法等最優化算法優化出來的數我們稱為參數,類似于\lambda 一樣,我們無法使用最小二乘法或者梯度下降法等最優化算法優化出來的數我們稱為超參數。
    因而,我們可以總結如下:
  1. 模型參數是模型內部的配置變量,其值可以根據數據進行估計。它有如下特征:
  • 參數通常不由編程者手動設置。
  • 參數通常被保存為學習模型的一部分。
  • 參數是機器學習算法的關鍵,它們通常由過去的訓練數據中總結得出
  1. 模型超參數是模型外部的配置,其值無法從數據中估計。通常:
  • 超參數通常用于幫助估計模型參數。
  • 超參數通常由人工指定。
  • 超參數通常可以使用啟發式設置。
  • 超參數經常被調整為給定的預測建模問題。

一些典型的模型超參數如下:

  • 神經網絡算法中的隱含層層數
  • 決策樹算法中樹的深度和葉子節點的個數
  • 訓練神經網絡的學習速率;
  • 支持向量機的C和Sigma超參數;
  • KNN問題中的K;

我們前面(4)部分的優化都是基于模型本身的具體形式的優化,本次模型超參數優化就是針對超參數,也就是取不同的超參數的值對于模型的性能有不同的影響。

2. 網格搜索與隨機搜索

既然知道模型的超參數可以取不同的值,那么我們怎么知道取哪個值可以讓模型盡快收斂并獲得最佳的精度呢?一個很自然的想法自然是通過使用for循環,遍歷每個參數來查看每個參數下模型的準確率。理論上如果有三個參數,我們可以嵌套三個for循環逐個遍歷每種組合來獲得最佳參數,但是這樣做確實太low!
我們知道sklearn最大的特點就是封裝!sklearn下的model_selection模塊里面已經封裝好了網格搜索GridSearchCV()和隨機搜索 RandomizedSearchCV()來幫助我們完成最佳參數尋找這個過程。

  • 網格搜索GridSearchCV():
    網格搜索的思想非常簡單,比如你有2個超參數需要去選擇,然后針對每組超參數分別建立一個模型,然后選擇測試誤差最小的那組超參數。換句話說,我們需要從超參數空間中尋找最優的超參數,很像一個網格中找到一個最優的節點,因此叫網格搜索。
  • 隨機搜索 RandomizedSearchCV() :
    網格搜索相當于暴力地從參數空間中每個都嘗試一遍,然后選擇最優的那組參數,這樣的方法顯然是不夠高效的,因為隨著參數類別個數的增加,需要嘗試的次數呈指數級增長。有沒有一種更加高效的調優方式呢?那就是使用隨機搜索的方式,這種方式不僅僅高校,而且實驗證明,隨機搜索法結果比稀疏化網格法稍好(有時候也會極差,需要權衡)。參數的隨機搜索中的每個參數都是從可能的參數值的分布中采樣的。與網格搜索相比,這有兩個主要優點:
    • 可以獨立于參數數量和可能的值來選擇計算成本。
    • 添加不影響性能的參數不會降低效率。

3. 實例

我們使用之前的房價數據,并使用SVR方法進行預測,并對比網格搜索和隨機搜索.

  • Step1: 導入SVR和數據
import numpy as np
import pandas as pd
from sklearn.svm import SVR     # 引入SVR類
from sklearn.pipeline import make_pipeline   # 引入管道簡化學習流程
from sklearn.preprocessing import StandardScaler # 由于SVR基于距離計算,引入對數據進行標準化的類
from sklearn.model_selection import GridSearchCV  # 引入網格搜索調優
from sklearn.model_selection import cross_val_score # 引入K折交叉驗證
from sklearn import datasets

為了簡化學習流程,導入pipeline
注: Pipeline可以將許多算法模型串聯起來,比如將特征提取、歸一化、分類組織在一起形成一個典型的機器學習問題工作流。主要帶來兩點好處:

  • 直接調用fit和predict方法來對pipeline中的所有算法模型進行訓練和預測

  • 可以結合grid search對參數進行選擇。

  • Step 2. 我們先來對未調參的SVR進行評價:

boston = datasets.load_boston()     # 導入房價數據
X = boston.data
y = boston.target
features = boston.feature_names
pipe_SVR = make_pipeline(StandardScaler(),SVR())
score1 = cross_val_score(estimator=pipe_SVR,
                         X = X,
                         y = y,
                         scoring = 'r2',
                         cv = 10)       # 10折交叉驗證
print("CV accuracy: %.3f +/- %.3f" % ((np.mean(score1)),np.std(score1)))
>>>CV accuracy: 0.187 +/- 0.649

Step3: 下面我們使用網格搜索來對SVR調參:

from sklearn.pipeline import Pipeline
pipe_svr = Pipeline([("StandardScaler",StandardScaler()),
                                                         ("svr",SVR())])
param_range = [0.0001,0.001,0.01,0.1,1.0,10.0,100.0,1000.0]
param_grid = [{"svr__C":param_range,"svr__kernel":["linear"]},  # 注意__是指兩個下劃線,一個下劃線會報錯的
                            {"svr__C":param_range,"svr__gamma":param_range,"svr__kernel":["rbf"]}]
gs = GridSearchCV(estimator=pipe_svr,
                                                     param_grid = param_grid,
                                                     scoring = 'r2',
                                                      cv = 10)       # 10折交叉驗證
gs = gs.fit(X,y)
print("網格搜索最優得分:",gs.best_score_)
print("網格搜索最優參數組合:\n",gs.best_params_)

>>>網格搜索最優得分: 0.6081303070817048
網格搜索最優參數組合:
 {'svr__C': 1000.0, 'svr__gamma': 0.001, 'svr__kernel': 'rbf'}

step 4: 使用隨機搜索來對SVR調參:

from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform  # 引入均勻分布設置參數
pipe_svr = Pipeline([("StandardScaler",StandardScaler()),
                                                         ("svr",SVR())])
distributions = dict(svr__C=uniform(loc=1.0, scale=4),    # 構建連續參數的分布
                     svr__kernel=["linear","rbf"],                                   # 離散參數的集合
                    svr__gamma=uniform(loc=0, scale=4))

rs = RandomizedSearchCV(estimator=pipe_svr,
                                                     param_distributions = distributions,
                                                     scoring = 'r2',
                                                      cv = 10)       # 10折交叉驗證
rs = rs.fit(X,y)
print("隨機搜索最優得分:",rs.best_score_)
print("隨機搜索最優參數組合:\n",rs.best_params_)
>>>隨機搜索最優得分: 0.41965270949834066
隨機搜索最優參數組合:
 {'svr__C': 2.317537782011187, 'svr__gamma': 0.008558056985909612, 'svr__kernel': 'rbf'}

可以明顯的看到使用超參數調優后模型都獲得相應的提高!

參考: Datawhale開源項目:機器學習集成學習與模型融合(基于python)
作者: 李祖賢,陳琰鈺,趙可,楊毅遠,薛傳雨

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容