bayes調參

轉自:http://www.javashuo.com/article/p-avbjwgvm-gm.html

1、簡介

貝葉斯優化用於機器學習調參由J. Snoek(2012)提出,主要思想是,給定優化的目標函數(廣義的函數,只需指定輸入和輸出便可,無需知道內部結構以及數學性質),經過不斷地添加樣本點來更新目標函數的後驗分佈(高斯過程,直到後驗分佈基本貼合於真實分佈。簡單的說,就是考慮了上一次參數的信息**,從而更好的調整當前的參數。html

他與常規的網格搜索或者隨機搜索的區別是:python

  • 貝葉斯調參採用高斯過程,考慮以前的參數信息,不斷地更新先驗;網格搜索未考慮以前的參數信息
  • 貝葉斯調參迭代次數少,速度快;網格搜索速度慢,參數多時易致使維度爆炸
  • 貝葉斯調參針對非凸問題依然穩健;網格搜索針對非凸問題易獲得局部優最

2、理論

介紹貝葉斯優化調參,必需要從兩個部分講起:git

  • 高斯過程,用以擬合優化目標函數
  • 貝葉斯優化,包括了「開採」和「勘探」,用以花最少的代價找到最優值

2.1 高斯過程

高斯過程能夠用於非線性迴歸、非線性分類、參數尋優等等。以往的建模須要對 p(y|X)github

建模,當用於預測時,則是算法

 

p(yN+1|XN+1)

 

而高斯過程則, 還考慮了 yN數組

yN+1bash

之間的關係,即:app

 

p(yN+1|XN+1,yN)

 

高斯過程經過假設 Ydom

值服從聯合正態分佈,來考慮 yNyN+1機器學習

之間的關係,所以須要給定參數包括:均值向量和協方差矩陣,即:

 

y1y2...ynN(0,k(x1,x1),k(x1,x2),...,k(x1,xn)k(x2,x1),k(x2,x2),...,k(x2,xn)...k(xn,x1),k(xn,x2),...,k(xn,xn))

 

其中協方差矩陣又叫作 核矩陣, 記爲 K

,僅和特徵 x 有關,和 y

無關。

高斯過程的思想是: 假設 Y

服從高維正態分佈(先驗),而根據訓練集能夠獲得最優的核矩陣 ,從而獲得後驗以估計測試集 Y

 

咱們有後驗:

 

p(y|yN(KK1y, KKK1KT)

 

其中,K

爲訓練集的核向量,有以下關係:

 

[yy]N(0,[K,KTK,K])

 

能夠發現,在後驗公式中,只有均值和訓練集 Y

有關,方差則僅僅和核矩陣,也就是訓練集和測試集的 X 有關,與訓練集 Y

無關

高斯過程的估計(訓練)方法

假設使用平方指數核(Squared Exponential Kernel),那麼有:

 

k(x1,x2)=σ2fexp((x1x2)22l2)

 

那麼所須要的肯定的超參數 θ=[σ2f,l]

,因爲 Y

服從多維正態分佈,所以似然函數爲:

 

L=logp(y|x,θ)=12log|K|12(yμ)TK1(yμ)nlog(2π)/2

 

因爲 K

是由 θ 決定的,因此經過梯度降低便可求出超參數 θ

,而根據核矩陣的計算方式也能夠進行預測。

上圖是一張高斯分佈擬合函數的示意圖,能夠看到,它只須要九個點,就能夠大體擬合出整個函數形狀(圖片來自:https://github.com/fmfn/BayesianOptimization

2.2 貝葉斯優化理論

貝葉斯優化是一種逼近思想,當計算很是複雜、迭代次數較高時能起到很好的效果,多用於超參數肯定

基本思想

是基於數據使用貝葉斯定理估計目標函數的後驗分佈,而後再根據分佈選擇下一個採樣的超參數組合。它充分利用了前一個採樣點的信息,其優化的工做方式是經過對目標函數形狀的學習,並找到使結果向全局最大提高的參數

高斯過程 用於在貝葉斯優化中對目標函數建模,獲得其後驗分佈

經過高斯過程建模以後,咱們嘗試抽樣進行樣本計算,而貝葉斯優化很容易在局部最優解上不斷採樣,這就涉及到了開發和探索之間的權衡。

  • 開發 (exploitation): 根據後驗分佈,在最可能出現全局最優解的區域進行採樣, 開發高意味着均值高
  • 探索 (exploration): 在還未取樣的區域獲取採樣點, 探索高意味着方差高

而如何高效的採樣,即開發和探索,咱們須要用到 Acquisition Function, 它是用來尋找下一個 x 的函數。

Acquistion Function

通常形式的Acquisition Funtion是關於x的函數,映射到實數空間R,表示改點的目標函數值可以比當前最優值大多少的機率,目前主要有如下幾種主流的Acquisition Function

POI(probability of improvement)

 

POI(X)=P(f(X)f(X+)+ξ)=Φ(μ(x)f(X+)ξσ(x))

 

其中, f(X)

爲X的目標函數值, f(X+)到目前爲止 最優的X的目標函數值, μ(x),σ(x) 分別是高斯過程所獲得的目標函數的均值和方差,即 f(X) 的後驗分佈。 ξ 爲trade-off係數,若是沒有該係數,POI函數會傾向於取在 X+

周圍的點,即傾向於exploit而不是explore,所以加入該項進行權衡。

而咱們要作的,就是嘗試新的X,使得 POI(X)

最大,則採起該X (由於f(X)

的計算代價很是大),一般咱們使用 蒙特卡洛模擬 的方法進行。

詳細狀況見下圖(圖片來自 Ref[5])

Expected Improvement

POI是一個機率函數,所以只考慮了f(x) 比 f(x+)

大的機率,而EI則是一個指望函數,所以考慮了 f(x) 比 f(x+)

大多少。咱們經過下式獲取x

 

x=argmaxx  E(max{0,ft+1(x)f(X+)}|Dt)

 

其中 Dt

爲前t個樣本,在正態分佈的假定下,最終獲得:

 

EI(x)={(μ(x)f(x+))Φ(Z)+σ(x)ϕ(Z),if σ(x)>00,if σ(x)=0

 

其中 Z=μ(x)f(x+)σ(x)

 

Confidence bound criteria

 

LCB(x)=μ(x)κσ(x)

 

 

UCB(x)=μ(x)+κσ(x)

 

2.3 缺點和不足

  • 高斯過程核矩陣很差選

3、例子

目前能夠作貝葉斯優化的包很是多,光是python就有:

本文使用BayesianOptimization爲例,利用sklearn的隨機森林模型進行分類

安裝

pip install bayesian-optimization

前期準備

from sklearn.datasets import make_classification from sklearn.ensemble import RandomForestClassifier from sklearn.cross_validation import cross_val_score from bayes_opt import BayesianOptimization # 產生隨機分類數據集,10個特徵, 2個類別 x, y = make_classification(n_samples=1000,n_features=10,n_classes=2)

咱們先看看不調參的結果:

rf = RandomForestClassifier()
print(np.mean(cross_val_score(rf, x, y, cv=20, scoring='roc_auc'))) >>> 0.965162

能夠看到,不調參的話模型20此交叉驗證AUC均值是0.965162,算是一個不錯的模型,那麼若是用bayes調參結果會怎麼樣呢

bayes調參初探

咱們先定義一個目標函數,裏面放入咱們但願優化的函數。好比此時,函數輸入爲隨機森林的全部參數,輸出爲模型交叉驗證5次的AUC均值,做爲咱們的目標函數。由於bayes_opt庫只支持最大值,因此最後的輸出若是是越小越好,那麼須要在前面加上負號,以轉爲最大值。因爲bayes優化只能優化連續超參數,所以要加上int()轉爲離散超參數。

def rf_cv(n_estimators, min_samples_split, max_features, max_depth): val = cross_val_score( RandomForestClassifier(n_estimators=int(n_estimators), min_samples_split=int(min_samples_split), max_features=min(max_features, 0.999), # float max_depth=int(max_depth), random_state=2 ), x, y, scoring='roc_auc', cv=5 ).mean() return val 

而後咱們就能夠實例化一個bayes優化對象了:

rf_bo = BayesianOptimization(
        rf_cv,
        {'n_estimators': (10, 250), 'min_samples_split': (2, 25), 'max_features': (0.1, 0.999), 'max_depth': (5, 15)} )

裏面的第一個參數是咱們的優化目標函數,第二個參數是咱們所須要輸入的超參數名稱,以及其範圍。超參數名稱必須和目標函數的輸入名稱一一對應。

完成上面兩步以後,咱們就能夠運行bayes優化了!

rf_bo.maximize()

完成的時候會不斷地輸出結果,以下圖所示:

等到程序結束,咱們能夠查看當前最優的參數和結果:

rf_bo.res['max'] >>> {'max_params': {'max_depth': 5.819908283575526, 'max_features': 0.4951745603509127, 'min_samples_split': 2.3110014720414958, 'n_estimators': 249.73529231990733}, 'max_val': 0.9774079407940794}

bayes調參進階

上面bayes算法獲得的參數並不必定最優,固然咱們會遇到一種狀況,就是咱們已經知道有一組或是幾組參數是很是好的了,咱們想知道其附近有沒有更好的。這個操做至關於上文bayes優化中的Explore操做,而bayes_opt庫給了咱們實現此方法的函數:

rf_bo.explore(
    {'n_estimators': [10, 100, 200], 'min_samples_split': [2, 10, 20], 'max_features': [0.1, 0.5, 0.9], 'max_depth': [5, 10, 15] } )

這裏咱們添加了三組較優的超參數,讓其在該參數基礎上進行explore,可能會獲得更好的結果。

同時,咱們還能夠修改高斯過程的參數,高斯過程主要參數是核函數(kernel),還有其餘參數能夠參考sklearn.gaussianprocess

gp_param={'kernel':None} rf_bo.maximize(**gp_param)

最終咱們的到參數以下:

{'max_params': {'max_depth': 5.819908283575526, 'max_features': 0.4951745603509127, 'min_samples_split': 2.3110014720414958, 'n_estimators': 249.73529231990733}, 'max_val': 0.9774079407940794}

運行交叉驗證測試一下:

rf = RandomForestClassifier(max_depth=6, max_features=0.39517, min_samples_split=2, n_estimators=250) np.mean(cross_val_score(rf, x, y, cv=20, scoring='roc_auc')) >>> 0.9754953

獲得最終結果是0.9755,比以前的0.9652提升了約0.01,作過kaggle的朋友都懂,這在後期已是很是大的提升了!到後面想提升0.001都極其困難,所以bayes優化真的很是強大!

結束!

Reference

相關文章
相關標籤/搜索