較小超參數的Bayesian optimisation

2021-02-21 Datartisan數據工匠


在擬合一個單分類器時不需要花費太多時間,但是在擬合上百個分類器時卻需要大量時間。在尋找超參數時我們必須要擬合多個分類器,那我們應該怎麼解決這種問題呢?

本文研究了Bayesian optimisation的算法的內部工作,你可以通過使用它來減少設定的超參數集的數量並獲得最優的超參數集。如果你正在尋找一個已經實現的算法工具,Yelp提供了 MOE, metric optimisation

通常高斯過程回歸是一個有效的工具同時被大量使用在這裡。如果想獲得關於高斯過程回歸更多的信息可以參考Gaussian processes with george。

本文將從一個事前知道的得分方程的真實形式的案例開始,通過比較random grid search和Bayesian optimisation兩種算法,來發現對於實際分類器的最優的超參數。

首先從安裝和導入模塊開始。

%matplotlib inline      

import randomimport numpy as npnp.random.seed(9)from scipy.stats import randint as sp_randintimport matplotlib.pyplot as pltimport seaborn as snssns.set_style('whitegrid')sns.set_context("talk")

By George!

Bayesian optimisation對之前超參數空間中的評估點使用高斯過程來擬合回歸模型。同時這個模型將提供超參數空間中下一個用於評估模型的點(可能是最優的)。為了選擇最優的點我們需要定義一個準則,在這種情況下我們使用「提高期望」的準則。就像我們所知的那樣,在一個有精準的得分函數下,我們並不想簡單的選擇獲得最高分的點。相反我們選擇那些在能最大增加期望的點。這種方法允許我們將得分方程的不確定性納入流程,並引導參數空間的搜索。下面我們設置一個得分函數(-x sin x),從中抽取兩個點,並擬合我們的高斯過程模型。

import georgefrom george.kernels import ExpSquaredKernelscore_func = lambda x: -x*np.sin(x)x = np.arange(0, 10, 0.1)

xp = 10 * np.sort(np.random.rand(2))yerr = 0.2 * np.ones_like(xp)yp = score_func(xp) + yerr * np.random.randn(len(xp))

kernel = ExpSquaredKernel(1)gp = george.GP(kernel)gp.compute(xp, yerr)mu, cov = gp.predict(yp, x)std = np.sqrt(np.diag(cov))def basic_plot():    fig, ax = plt.subplots()    ax.plot(x, mu, label="GP median")    ax.fill_between(x, mu-std, mu+std, alpha=0.5)    ax.plot(x, score_func(x), '--', label=" True score function (unknown)")        ax.errorbar(xp, yp, yerr=yerr, fmt='ok', zorder=3, label="samples")    ax.set_ylim(-9,6)    ax.set_ylabel("score")    ax.set_xlabel('hyper-parameter X')    ax.legend(loc='best')    return fig,axbasic_plot()

(<matplotlib.figure.Figure at 0x109dd82d0>, <matplotlib.axes._subplots.AxesSubplot at 0x10b945590>)


其中綠色虛線代表得分函數(以超參數X為函數)的真實值。圖中黑的的點(以及他們的誤差線)是我們用於評估分類器的點同時我們也計算出其得分。在藍色線是我們利用回歸模型所試圖預測的得分函數,並用深藍色陰影區域代表得分函數值的不確定性。

下面我們計算在超參數X每個位置的提高的期望。我們也建立了一個多點優化程序(next_sample),它通過使用提高期望的方法來選擇哪個點將在下一步中使用。

from scipy.optimize import minimizefrom scipy import stats

def expected_improvement(points, gp, samples, bigger_better=False):        if bigger_better:        best_sample = samples[np.argmax(samples)]        mu, cov = gp.predict(samples, points)        sigma = np.sqrt(cov.diagonal())        Z = (mu-best_sample)/sigma        ei = ((mu-best_sample) * stats.norm.cdf(Z) + sigma*stats.norm.pdf(Z))                return -ei    else:        best_sample = samples[np.argmin(samples)]        mu, cov = gp.predict(samples, points)        sigma = np.sqrt(cov.diagonal())        Z = (best_sample-mu)/sigma        ei = ((best_sample-mu) * stats.norm.cdf(Z) + sigma*stats.norm.pdf(Z))                return -eidef next_sample(gp, samples, bounds=(0,10), bigger_better=False):    """Find point with largest expected improvement"""    best_x = None    best_ei = 0                for rand_x in np.random.uniform(bounds[0], bounds[1], size=30):        res = minimize(expected_improvement, rand_x,                       bounds=[bounds],                       method='L-BFGS-B',                       args=(gp, samples, bigger_better))        if res.fun < best_ei:            best_ei = res.fun            best_x = res.x[0]    return best_xfig, ax = basic_plot()ax.plot(x, 10*np.abs(expected_improvement(x, gp, yp)),        label='expected improvement')ax.legend(loc='best')

<matplotlib.legend.Legend at 0x109de4490>


print "The algorithm suggests sampling at X=%.4f"%(next_sample(gp, yp))

The algorithm suggests sampling at X=1.5833

其中紅色的線代表期望的提高。通過對比藍色實心線和陰影區域,優化算法建議將期望提高最大的點X=1.58作為下一個點來計算我們的得分函數。

現在讓我們看看一些實際的案例。

以隨機格點搜索的效果作為基準

為了讓這個簡單的示例更有趣,我們使用一個來自(Friedman1)的回歸問題以及一個決策樹回歸模型(它在這個數據集下面擬合大量分類器相當的快)。你可以在實際問題中用它來代替兩者。

為了評估在搜索超參數中誰比較快,我們將對bayesian optimisation和 隨機格點法進行對比。隨機格點搜索法已經比枚舉的格點法提升了很多。我通過一個來自Gilles Louppe’s的博士論文Understanding Random Forests: From Theory to Practice的特殊回歸問題來做實驗。

from sklearn.grid_search import GridSearchCVfrom sklearn.grid_search import RandomizedSearchCVfrom sklearn.datasets import make_friedman1from sklearn.tree import DecisionTreeRegressorfrom operator import itemgetterX, y = make_friedman1(n_samples=5000)clf = DecisionTreeRegressor()param_dist = {"min_samples_split": sp_randint(1, 101),             }n_iterations = 8random_grid = RandomizedSearchCV(clf,                                 param_distributions=param_dist,                                 n_iter=n_iterations,                                 scoring='mean_squared_error')random_grid = random_grid.fit(X, y)

from scipy.stats import semparams_ = []scores_ = []yerr_ = []for g in random_grid.grid_scores_:    params_.append(g.parameters.values()[0])    scores_.append(g.mean_validation_score)    yerr_.append(sem(g.cv_validation_scores))fig, ax = plt.subplots()ax.errorbar(params_, scores_, yerr=yerr_, fmt='ok', label='samples')ax.set_ylabel("score")ax.set_xlabel('min samples leaf')ax.legend(loc='best')

<matplotlib.legend.Legend at 0x10a52ebd0>


def top_parameters(random_grid_cv):    top_score = sorted(random_grid_cv.grid_scores_,                       key=itemgetter(1),                       reverse=True)[0]    print "Mean validation score: {0:.3f} +- {1:.3f}".format(        top_score.mean_validation_score,        np.std(top_score.cv_validation_scores))    print random_grid_cv.best_params_top_parameters(random_grid)

Mean validation score: -4.304 +- 0.161{'min_samples_split': 8}

最大的得分參數大概在8附近。現在讓我們來試試bayesian方法。

Bayesian optimisation

你已經準備好你的先驗函數了麼?讓我開始用bayesian的方法來試一下!那麼問題就是我們是否可以找到和 min_smples_split至少一樣的值或者更好的一個或者減少計算步驟。

首先我們使用在擬合高斯過程模型中的三個點來評估模型。而下一個點我們將採用能讓期望增加最大的點。

下面兩個圖展現了Bayesian optimisation在使用之前三個點,並且依據提高期望的準則,又納入了5個點後的情形

from sklearn.cross_validation import cross_val_scoredef plot_optimisation(gp, x, params, scores, yerr):    mu, cov = gp.predict(scores, x)    std = np.sqrt(np.diag(cov))    fig, ax = plt.subplots()    ax.plot(x, mu, label="GP median")    ax.fill_between(x, mu-std, mu+std, alpha=0.5)    ax_r = ax.twinx()    ax_r.grid(False)    ax_r.plot(x,              np.abs(expected_improvement(x, gp, scores, bigger_better=True)),              label='expected improvement',              c=sns.color_palette()[2])    ax_r.set_ylabel("expected improvement")        ax.errorbar(params, scores, yerr=yerr,                fmt='ok', zorder=3, label='samples')    ax.set_ylabel("score")    ax.set_xlabel('min samples leaf')    ax.legend(loc='best')    return gpdef bayes_optimise(clf, X,y, parameter, n_iterations, bounds):    x = range(bounds[0], bounds[1]+1)    params = []    scores = []    yerr = []    for param in np.linspace(bounds[0], bounds[1], 3, dtype=int):        clf.set_params(**{parameter: param})        cv_scores = cross_val_score(clf, X,y, scoring='mean_squared_error')        params.append(param)        scores.append(np.mean(cv_scores))        yerr.append(sem(cv_scores))            kernel = ExpSquaredKernel(1000)    gp = george.GP(kernel, mean=np.mean(scores))    gp.compute(params, yerr)    plot_optimisation(gp, x, params, scores, yerr)    for n in range(n_iterations-3):        gp.compute(params, yerr)        param = next_sample(gp, scores, bounds=bounds, bigger_better=True)        clf.set_params(**{parameter: param})        cv_scores = cross_val_score(clf, X,y, scoring='mean_squared_error')        params.append(param)        scores.append(np.mean(cv_scores))        yerr.append(sem(cv_scores))    plot_optimisation(gp, x, params, scores, yerr)    return params, scores, yerr, clfparams, scores, yerr, clf = bayes_optimise(DecisionTreeRegressor(),                                           X,y,                                           'min_samples_split',                                           8, (1,100))



print "Best parameter:"print params[np.argmax(scores)], 'scores', scores[np.argmax(scores)]

Best parameter:14.8626450189 scores -4.26649894389

你可以看到通過抽樣所得的點都非常接近最大值。當隨機格點搜索法抽樣到的點遠離最高點的區域時(40或者以上),baiyesian optimization方法所抽得的點集中於最大值附近(大約20左右)。這樣快速有效的找到最大值。有時候我們甚至可以提前停止計算後續的五個點,因為他們都十分接近彼此。

利器—MOE

雖然它很容易為你自己建立一個小的bayesian optimisation過程,我依然建議你看看MOE。它是一個用於做全局,黑箱優化的一個非常優秀的產品,由Yelp的專業學者們開發,因此比我們自己做的方案更加強大。

結論

bayesian optimisation並不可怕,通過兩個例子,我們可以相信通過使用像這樣的聰明方法可以獲得比格點搜索法更快的解決問題(即使在高維的情況下),但實際上並沒有任何魔法發生。

作者:betatim

翻譯:董安瀾

相關焦點

  • 使用Python進行超參數優化
    超參數是每個機器學習和深度學習算法的組成部分。與算法本身學習的標準機器學習參數(例如線性回歸中的w和b或神經網絡中的連接權重)不同,工程師在訓練過程之前會設置超參數。它們是控制工程師完全定義的學習算法行為的外部因素。需要一些例子嗎?
  • Python 機器學習:超參數調優
    1.什麼是超參數超參數(hyper parameters)就是機器學習或深度學習算法中需要預先設置的參數,這些參數不是通過訓練數據學習到的參數;原始算法一般只給出超參數的取值範圍和含義,根據不同的應用場景,同一個算法的同一超參數設置也不同。那超參數應該如何設置呢?似乎沒有捷徑,去嘗試不同的取值,比較不同的結果取最好的結果。貝葉斯優化(Bayesian optimization)2.
  • 機器學習4個常用超參數調試方法!
    ML工作流中最困難的部分之一是為模型找到最好的超參數。ML模型的性能與超參數直接相關。超參數調優的越好,得到的模型就越好。調優超參數可能是非常乏味和困難的,更像是一門藝術而不是科學。超參數超參數是在建立模型時用於控制算法行為的參數。這些參數不能從常規訓練過程中獲得。
  • 機器學習 4 個常用超參數調試方法!
    ML工作流中最困難的部分之一是為模型找到最好的超參數。ML模型的性能與超參數直接相關。超參數調優的越好,得到的模型就越好。調優超參數可能是非常乏味和困難的,更像是一門藝術而不是科學。超參數超參數是在建立模型時用於控制算法行為的參數。這些參數不能從常規訓練過程中獲得。在對模型進行訓練之前,需要對它們進行賦值。內容1.
  • 資源 | NIPS 2017 Spotlight論文Bayesian GAN的TensorFlow實現
    我們介紹了一個生成器參數的多模態後驗。這些參數的每個設置對應數據的不同生成假設。這裡我們將展示兩種權重向量設置下生成的樣本,不同的權重向量設置對應不同的寫作風格。貝葉斯 GAN 保留該參數分布。MNIST、CIFAR10、CELEBA、SVHNbayesian_gan_hmc 腳本允許在標準和自定義數據集上訓練模型。下面,我們將介紹如何使用該腳本。
  • 每個算法人員都應該知道的4個超參數調試方法
    ML工作流中最困難的部分之一是為模型找到最好的超參數。ML模型的性能與超參數直接相關。超參數調優的越好,得到的模型就越好。調優超參數可能是非常乏味和困難的,更像是一門藝術而不是科學。超參數超參數是在建立模型時用於控制算法行為的參數。這些參數不能從常規訓練過程中獲得。在對模型進行訓練之前,需要對它們進行賦值。
  • 深度學習中的超參數優化技術
    設置超參數的過程需要專業知識和廣泛的試驗和錯誤。沒有簡單易行的方法來設置超參數 - 特別是學習率、批量大小、動量和權重衰減。深度學習模型充滿了超參數,在如此高維空間中找到這些參數的最佳配置並不是一項微不足道的挑戰。
  • 支持向量機超參數的可視化解釋
    在這篇文章中,我們將深入探討支持向量機的兩個重要超參數C和gamma,並通過可視化解釋它們的影響。所以我假設你對算法有一個基本的理解,並把重點放在這些超參數上。支持向量機用一個決策邊界來分離屬於不同類別的數據點。
  • 一文詳解超參數調優方法
    超參數,在訓練中一般是固定數值或者以預設規則變化,比如批大小(batch size)、學習率(learning rate)、正則化項係數(weight decay)、核函數中的 gamma 等。超參數調優的目標通常是最小化泛化誤差(generalization error),也可以根據具體任務自定義其他優化目標。
  • 【機器學習基礎】支持向量機超參數的可視化解釋
    在這篇文章中,我們將深入探討支持向量機的兩個重要超參數C和gamma,並通過可視化解釋它們的影響。所以我假設你對算法有一個基本的理解,並把重點放在這些超參數上。支持向量機用一個決策邊界來分離屬於不同類別的數據點。
  • 交叉驗證和超參數調整:如何優化你的機器學習模型
    現在我們知道了交叉驗證是什麼以及它為什麼重要,讓我們看看是否可以通過調優超參數從我們的模型中獲得更多。超參數調優模型參數是在模型訓練時學習的,不能任意設置。與模型參數不同,超參數是用戶在訓練機器學習模型前可以設置的參數。
  • 如何選擇神經網絡的超參數
    神經網絡的超參數分類  神經網路中的超參數主要包括1. 學習率 ηη,2. 正則化參數 λλ,3. 神經網絡的層數 LL,4. 每一個隱層中神經元的個數 jj,5. 學習的回合數EpochEpoch,6. 小批量數據 minibatchminibatch 的大小,7. 輸出神經元的編碼方式,8. 代價函數的選擇,9. 權重初始化的方法,10.
  • Keras/Python深度學習中的網格搜索超參數調優(附源碼)
    超參數優化是深度學習中的重要組成部分。其原因在於,神經網絡是公認的難以配置,而又有很多參數需要設置。最重要的是,個別模型的訓練非常緩慢。
  • 手動搜索超參數的一個簡單方法
    我們並沒有讓模型盲目地嘗試,而是設定了一些超參數。為了解釋超參數,我們可以舉一個孩子在IPad上玩的例子。你不能控制他/她在上面玩什麼或看什麼,但你可以控制孩子在上面花了多少時間。類似地,我們可以調整這些超參數,使模型對特徵進行評級,在此基礎上生成預測結果。
  • 調整超參數:決定模型是「金子」還是「垃圾」!
    ,首先要明確參數與超參數的區別:參數:是模型內部的配置變量,在機器學習中生成的。超參數的調整概述在scikit-learn中提供很多不同的機器學習模型,並且提供了各模型超參數的初始值設置,這些初始值的搭配僅是針對解決某些問題的可能的最優搭配,並不是針對解決所有問題的最優搭配,因此,當使用scikit-learn中的模型進行建模時,調整超參數仍是必要的。
  • 超參數優化,這些策略了解一下!
    我們希望找到最佳的超參數配置,幫助我們在驗證/測試集的關鍵度量上得到最佳分數。為何?在計算力、金錢和時間資源有限的情況下,每個科學家和研究員都希望獲得最佳模型。但是我們缺少有效的超參數搜索來實現這一目標。何時?等等,究竟何謂超參數?