微信號:deep_intelligence(歡迎關注!)

weixin.qq.com/r/ry7r8xz (二維碼自動識別)

您是否厭倦了babysittin您的DL模型?如果是這樣,你就來對地方了。在這篇文章中,我們討論了有效搜索任何深度學習模型的最佳超參數集的動機和策略。我們將演示如何在FloydHub上完成這項工作。當您閱讀完這篇文章後,您會學到一個有用的工具 ,使您儘可能自動地為深度學習任務找到最佳配置。

與機器學習模型不同,深度學習模型實際上充滿了超參數。當然,並非所有這些變數都以相同的方式對模型的學習過程做出貢獻,但是,鑒於這種額外的複雜性,很明顯在這樣一個高維空間中找到這些變數的最佳配置並不是一個微不足道的挑戰。幸運的是,我們有不同的策略和工具來解決搜索問題。

我們的目標

如何?

我們希望找到超參數的最佳配置,為感興趣的度量實現驗證/測試集的最佳分數

為什麼?

在給定可用資源的情況下,每個科學家和研究人員都希望獲得最佳模型:??,??和?(又名計算金錢時間)。有效的超參數搜索是這個難題的缺失部分,將幫助我們實現這一目標。

什麼時候?

  • 研究人員和業餘愛好者在最後的開發階段嘗試其中一種搜索策略是很常見的。
  • 超參數搜索作為半/全自動深度學習流程中的階段或組件也很常見。顯然,這在公司的數據科學團隊中更為常見。

等等,但究竟什麼是超參數?

讓我們從最簡單的定義開始,

超參數是您在構建機器/深度學習模型時可以轉動的旋鈕。

或者:

超參數是在開始訓練前需要預先確定和手動設置的訓練變數。

我們可能會同意學習率和丟棄率(dropout)是超參數,但模型的設計變數呢?例如嵌入,層數,激活函數等。我們應該將這些變數視為超參數嗎?

為簡單起見,是的 - 我們也可以將模型設計組件視為超參數集的一部分。

那麼,從訓練過程中獲得的參數—— 從數據中學習的變數是超參數嗎?這些權重稱為模型參數。但我們會將它們從超參數集中排除。

好的,讓我們嘗試一個真實的例子。請看下面的圖片,說明深度學習模型中變數的不同分類。

我們的下一個問題:搜索費用很高

現在我們知道我們想要搜索超參數的最佳配置,我們面臨的挑戰是搜索超參數是一個????constra約束的迭代過程

一切都以有前途的配置的猜測(步驟1)開始,然後我們將需要等到完全訓練(步驟2)以獲得對感興趣的度量的實際評估(步驟3)。我們將跟蹤搜索過程的進度(步驟4),然後根據我們的搜索策略,我們將選擇一個新的猜測(步驟1)。

我們將繼續這樣做,直到我們達到終止條件(例如用完???)。

我們來談談策略

我們有四種主要策略可用於搜索最佳配置。

  • Babysitting (或 Trial & Error)
  • 網格搜索 Grid Search
  • 隨機搜索 Random Search
  • 貝葉斯優化 Bayesian Optimization

Babysitting

Babysitting在學術領域也被稱為Grad Student DescentGrad Student Descent。這種方法是100%手動,是研究人員,學生和業餘愛好者最廣泛採用的方法。

端到端的工作流程非常簡單:學生設計了一個新的實驗,她通過學習過程的所有步驟(從數據收集到特徵圖可視化),然後她將按順序迭代超參數直到她運行時間結束(通常是由於截止日期)。

如果您已經註冊了deeplearning.ai課程,那麼您就熟悉這種方法 - 這是由Andrew Ng教授描述的Panda工作流程【1】。

這種方法非常有教育意義,但它不能在團隊或公司內部擴展,因為數據科學家的時間非常寶貴。

因此,我們的問題是:

「有不那麼費時的更好的方法嗎

當然!我們可以通過定義超參數搜索的自動策略來優化您的時間!

網格搜索

網格搜索 ——簡單地嘗試各種可能的配置的幼稚的做法。它的工作流程如下:

  • n維上定義網格,其中每個都為超參數映射。例如n =(learning_rate,dropout_rate,batch_size)
  • 對於每個維度,定義可能值的範圍:例如batch_size = [4,8,16,32,64,128,256]
  • 搜索所有可能的配置並等待結果建立最佳配置:例如C1 =(0.1,0.3,4) - > acc = 92%,C2 =(0.1,0.35,4) - > acc = 92.3%,等等...

下圖顯示了Dropout和學習速率在兩個維度上的簡單網格搜索。

這種策略的並行很尷尬,因為它沒有考慮計算歷史。但它的意思是,你的可用計算資源??越多,那麼你可以在同一時間嘗試越多的猜測!

這種方法的真正痛點被稱為維度的詛咒。這意味著我們添加的維度越多,搜索在時間複雜度(通常是指數級別的)的爆炸越多,最終使這個策略變得不可行!

當尺寸小於或等於4時,通常使用這種方法。但是,實際上,即使它保證在最後找到最佳配置,它仍然不是優選的。相反,最好使用隨機搜索 - 我們將在下面討論

使用FloyHub進行網格搜索!

可在FloydHub上打開工作區【2】。您可以使用工作區在完全配置的雲計算機上運行以下代碼(使用Scikit-learn和Keras進行網格搜索)。

# Load the dataset
x, y = load_dataset()

# Create model for KerasClassifier
def create_model(hparams1=dvalue,
hparams2=dvalue,
...
hparamsn=dvalue):
# Model definition
...

model = KerasClassifier(build_fn=create_model)

# Define the range
hparams1 = [2, 4, ...]
hparams2 = [elu, relu, ...]
...
hparamsn = [1, 2, 3, 4, ...]

# Prepare the Grid
param_grid = dict(hparams1=hparams1,
hparams2=hparams2,
...
hparamsn=hparamsn)

# GridSearch in action
grid = GridSearchCV(estimator=model,
param_grid=param_grid,
n_jobs=,
cv=,
verbose=)
grid_result = grid.fit(x, y)

# Show the results
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
means = grid_result.cv_results_[mean_test_score]
stds = grid_result.cv_results_[std_test_score]
params = grid_result.cv_results_[params]
for mean, stdev, param in zip(means, stds, params):
print("%f (%f) with: %r" % (mean, stdev, param))

隨機搜索

幾年前,Bergstra和Bengio發表了一篇驚人的論文【3】,他們證明瞭網格搜索的低效率。網格搜索和隨機搜索之間唯一真正的區別在於策略週期的第1步 - 隨機搜索從配置空間中隨機選取點。讓我們使用下面的圖片(在論文中提供)來顯示研究人員報告的聲明。

網格搜索VS隨機搜索

圖像中,通過在兩個超參數空間上搜索最佳配置來比較兩種方法。它還假設一個參數比另一個參數更重要。這是一個安全的假設,因為開頭提到的深度學習模型確實充滿了超參數,並且通常研究人員/科學家/學生知道哪些對訓練影響最大。

在網格搜索中,很容易注意到,即使我們已經訓練了9個模型,我們每個變數只使用了3個值!然而,使用隨機搜索,我們不太可能多次選擇相同的變數。最後,通過第二種方法,我們將使用9個不同的值為每個變數訓練9個模型。

從圖像中每個佈局頂部的空間探索可以看出,我們使用隨機搜索更廣泛地探索了超參數空間(特別是對於更重要的變數)。這將有助於我們在更少的迭代中找到最佳配置。

總結:如果搜索空間包含3到4個以上的維度,請不要使用網格搜索。相反,使用隨機搜索,它為每個搜索任務提供了非常好的基線。

使用FloydHub進行隨機搜索!

在這裡(floydhub.com/run?)可在FloydHub上打開工作區。您可以使用工作區在配置完整的雲計算機上運行以下代碼(使用Scikit-learn和Keras進行隨機搜索。)。

# Load the dataset
X, Y = load_dataset()

# Create model for KerasClassifier
def create_model(hparams1=dvalue,
hparams2=dvalue,
...
hparamsn=dvalue):
# Model definition
...

model = KerasClassifier(build_fn=create_model)

# Specify parameters and distributions to sample from
hparams1 = randint(1, 100)
hparams2 = [elu, relu, ...]
...
hparamsn = uniform(0, 1)

# Prepare the Dict for the Search
param_dist = dict(hparams1=hparams1,
hparams2=hparams2,
...
hparamsn=hparamsn)

# Search in action!
n_iter_search = 16 # Number of parameter settings that are sampled.
random_search = RandomizedSearchCV(estimator=model,
param_distributions=param_dist,
n_iter=n_iter_search,
n_jobs=,
cv=,
verbose=)
random_search.fit(X, Y)

# Show the results
print("Best: %f using %s" % (random_search.best_score_, random_search.best_params_))
means = random_search.cv_results_[mean_test_score]
stds = random_search.cv_results_[std_test_score]
params = random_search.cv_results_[params]
for mean, stdev, param in zip(means, stds, params):
print("%f (%f) with: %r" % (mean, stdev, param))

退後一步,前進兩步

另外,當您需要為每個維度設置空間時,為每個變數使用正確的比例非常重要。

例如,通常使用批量大小的值作為2的冪,並在對數標度中對學習率進行採樣。

從上面的一個佈局開始進行一定數量的迭代也是很常見的,然後通過在每個變數範圍內更密集地採樣來放大到有希望的子空間,甚至用相同或不同的搜索策略開始新的搜索。

還有一個問題:獨立猜測!

不幸的是,網格和隨機搜索都有共同的缺點:

「每一個新猜測都獨立於之前的運行!」

這聽起來有些奇怪和令人驚訝,但是,儘管需要大量的時間,但babysitting是科學家通過將過去的經驗作??為參考來改善下一次運行來有效推動搜索和實驗的能力。等一下,聽起來很熟悉......如果我們嘗試將超參數搜索建模為機器學習任務如何?!這就是貝葉斯優化所做的。

貝葉斯優化

此搜索策略構建了一個代理模型,該模型試圖從超參數配置中預測我們關注的指標。在每次新的迭代中,代理將對哪些新的猜測可以帶來改進越來越自信。就像其他搜索策略一樣,它共享相同的終止條件。

高斯過程在起作用

我們可以將高斯過程定義為代理,它將學習從超參數配置到感興趣度量的映射。它不僅會將預測產生為一個值,而且還會給我們提供不確定性的範圍(均值和方差)。讓我們深入研究這個教程的示例。

在上圖中,我們遵循單個變數(在水平軸上)的高斯過程優化的第一步。它可以代表學習率或丟棄率等超參數。

在垂直軸上,我們把感興趣的度量作為單個超參數的函數進行繪製。由於我們正在尋找儘可能低的值,我們可以將其視為損失函數。

黑點代表到目前為止訓練的模型。紅線是實際值,換句話說,就是我們正在努力學習的函數。黑線表示我們對實際函數的實際假設的平均值,灰色區域表示空間中的相關不確定性或方差。

我們可以注意到,不確定性在點周圍減少,因為我們對這些點的結果非常有信心(因為我們已經在這裡訓練了模型)。那麼,在我們擁有較少信息的區域,不確定性會增加。

現在我們已經定義了起點,我們已經準備好選擇下一個有希望的變數來訓練一個模型。為此,我們需要定義一個採集函數,它將告訴我們在哪裡採樣下一個配置。

在此示例中,我們使用預期改進(Expected Improvement):如果我們將使用來自不確定區域的建議配置,則函數旨在找到最低可能值。上面的預期改進圖表中的藍點顯示了為下一次訓練選擇的點。

我們訓練的模型越多,代理對下一個有希望的樣本點的信心就越大。這是8個訓練模型後的圖表:

高斯過程屬於稱為基於順序模型的優化(SMBO)的演算法類。正如我們剛剛看到的,這些演算法為開始搜索最佳超參數配置提供了非常好的基線。但是,就像每個工具一樣,它們也有它們的缺點:

  • 根據定義,該過程是順序的
  • 它只能處理數字參數
  • 如果訓練表現不佳,它不提供任何停止訓練的機制

請注意,我們只是簡單地談到了這個有趣的話題,如果您對更詳細的閱讀以及如何擴展SMBO感興趣,那麼請看一下這篇論文。

使用呢FloydHub進行貝葉斯優化!

單擊這裡(floydhub.com/run?)可在FloydHub上打開工作區。您可以使用工作區在完整配置的雲計算機上運行以下代碼(使用Hyperas進行貝葉斯優化(SMBO-TPE))。

def data():
"""
Data providing function:
This function is separated from model() so that hyperopt
wont reload data for each evaluation run.
"""
# Load / Cleaning / Preprocessing
...
return x_train, y_train, x_test, y_test

def model(x_train, y_train, x_test, y_test):
"""
Model providing function:
Create Keras model with double curly brackets dropped-in as needed.
Return value has to be a valid python dictionary with two customary keys:
- loss: Specify a numeric evaluation metric to be minimized
- status: Just use STATUS_OK and see hyperopt documentation if not feasible
The last one is optional, though recommended, namely:
- model: specify the model just created so that we can later use it again.
"""
# Model definition / hyperparameters space definition / fit / eval
return {loss: <metrics_to_minimize>, status: STATUS_OK, model: model}

# SMBO - TPE in action
best_run, best_model = optim.minimize(model=model,
data=data,
algo=tpe.suggest,
max_evals=,
trials=Trials())

# Show the results
x_train, y_train, x_test, y_test = data()
print("Evalutation of best performing model:")
print(best_model.evaluate(x_test, y_test))
print("Best performing model chosen hyper-parameters:")
print(best_run)

搜索策略比較

現在總結一下我們到目前為止所涵蓋的內容,以瞭解每個提案的優缺點。

貝葉斯SMBO可能是最佳候選者,只要資源不是您或您的團隊的約束,但您還應考慮使用隨機搜索建立基線。

另一方面,如果你還在學習或處於開發的階段,那麼Babysitting- 即使在空間探索方面不切實際 - 也是要走的路。

就像我在SMBO部分提到的那樣,如果訓練表現不佳甚至更差,這些策略都沒有提供保存資源的機制 - 我們必須等到計算結束。

因此,我們得出了最後一個問題:

「我們可以優化訓練時間嗎?」

讓我們來看看。

Early Stopping

Early Stopping不僅是一種著名的正規化技術,而且它還提供了一種很好的機制,可以在訓練不正確的時候防止資源浪費。這是最常採用的停止標準圖:

前三個標準是不言自明的,所以讓我們把注意力集中在最後一個標準上。根據研究實驗室內的實驗類別來限制訓練時間是很常見的。此政策充當實驗的渠道,並優化團隊內部的資源。通過這種方式,我們將能夠將更多資源分配給最有希望的實驗。

floyd-cli提供了一個標誌來達到這個目的:FloydHub的用戶都在使用它大量規範他們的實驗。

這些標準可以在照看學習過程時手動應用,或者您可以通過最常見框架中提供的鉤子/回調在實驗中集成這些規則來做得更好:

  • Keras提供了極強的EarlyStopping功能,是一套超級有用的回調。由於Keras最近已集成在Tensorflow中,您將能夠在tensorflow代碼中使用回調。
  • Tensorflow提供了訓練鉤子,這些可能不像Keras回調(或tf.keras API)那樣直觀,但它們可以讓您更好地控制執行狀態。
  • 目前,Pytorch尚未提供鉤子或回調組件,但您可以查看TorchSample的repo和論壇。我不知道Pytorch 1.0的功能列表(團隊可能會在PyTorch開發者大會上發布一些內容),但可能是這個功能將隨新版本一起提供。
  • fast.ai庫提供回調,即使它不提供任何形式的的文檔,你可以查看教程(在這裡)。或者他們有一個很棒的社區。
  • Ignite(Pytorch的高級庫)提供類似於keras的回調。該庫實際上正在積極開發中,但它確實看起來是一個非常有趣的選擇。

這不是結束。

機器學習的子領域稱為「AutoML」(自動機器學習),其目的是自動化模型選擇,特徵提取和/或超參數優化的方法。

這個工具是最後一個問題的答案(我保證!):

「我們可以瞭解整個過程嗎?」

您可以將AutoML視為機器學習任務,它正在用機器學習的演算法解決另一個機器學習任務,類似於我們對Baeysian Optimiziation所做的工作。從本質上講,這是元機器學習(Meta-Machine Learning)。

研究:AutoML和PBT

您很可能聽說過Google的AutoML,這是他們對神經網路搜索的新品牌。在本文開頭,我們決定將模型設計組件合併到超參數變數中。那麼,Neural Architecture Search(網路架構搜索)是AutoML的子領域,旨在為給定任務找到最佳模型。關於這一主題的全面討論需要一系列文章。幸運的是,來自fast.ai的Rachel Thomas博士做了一項了不起的工作,這裡是鏈接。

我想與您分享來自DeepMind的另一項有趣的研究工作,他們使用Evolution Strategy(進化論)演算法的變體來執行稱為基於種羣的訓練的超參數搜索(PTB也是DeepMind的另一項令人驚嘆的研究的基礎)。引用DeepMind:

PBT - 就像隨機搜索 - 通過與隨機超參數並行訓練許多神經網路開始。但是,它不是獨立地進行網路訓練,而是使用來自其他種羣的信息來細化超參數,並將計算資源引導到具有希望的模型。這得益於遺傳演算法,其中每個種羣(稱為工人)可以利用其餘種羣的信息。例如,工作人員可以從性能更好的工作人員複製模型參數。它還可以通過隨機更改當前值來探索新的超參數。

在FloydHub上管理您的實驗

FloydHub的最大特點之一是能夠在使用不同的超參數集時比較您正在訓練的不同模型。

下圖顯示了FloydHub項目中的作業列表。您可以看到此用戶正在使用作業的message欄位(例如floyd run --message "SGD, lr=1e-3, l1_drop=0.3" ... )來突出顯示在每個作業中使用的超參數。

此外,您還可以查看每項工作的訓練指標。這些提供了快速瀏覽,幫助您瞭解哪些工作表現最佳,以及使用的機器類型和總訓練時間。

FloydHub dashboard為您提供了一種簡單的方法來比較您在超參數搜索中所做的所有訓練 - 並且實時更新。

我們的建議是為您必須解決的每個任務/問題創建一個不同的FloydHub項目。通過這種方式,您可以更輕鬆地組織工作並與團隊協作。

訓練指標

如上所述,您可以輕鬆地在FloydHub上發布您的訓練指標。當您在FloydHub dashboard上查看作業時,您將找到您定義的每個指標的實時圖表。

此功能無意替代Tensorboard(我們也提供此功能),而是旨在突出顯示您已選擇的超參數配置的訓練行為。

例如,如果您正在監督訓練過程,那麼訓練指標肯定會幫助您確定和應用停止標準。

FloydHub HyperSearch(即將推出!)

FloydHub目前正計劃發布一些floyd-cli命令行工具的示例,工具封裝這篇文章中提議的策略,以便在FloydHub上有效地運行超參數搜索。所以,請繼續關注!

參考資料:

【1】coursera.org/lecture/de

【2】Workspaces on FloydHub

【3】jmlr.org/papers/volume1

本文翻譯自:blog.floydhub.com/guide


推薦閱讀:
相關文章