微軟自動調參工具—NNI—安裝與使用教程

簡介

NNI是微軟的開源自動調參的工具。人工調參實在是太麻煩了,最近試了下水,感覺還不錯,能在幫你調參的同時,把可視化的工作一起給做了,簡單明瞭。其可以可以看到當前試驗的進展情況,搜索參數和效果最好的一些超參數組合。例如:
通過下面的顏色圖就能直觀地看到紅色(即精度較高的超參組合)線條所表達的豐富信息。如

  • 卷積核大一些會表現較好。
  • 全連接層大了不一定太好。也許是所需要的訓練時間增加了,訓練速度太慢造成的。
  • 而學習率小一些(小於0.03),表現基本都不錯。
  • ReLU 比 tanh 等其它激活函數也好不少。

  • 在這裏插入圖片描述
    通過試驗狀態頁面,能看到每個試驗的時間長度以及具體的超參組合。
    在這裏插入圖片描述
    通過控制頁面還可以實時的增加試驗的超參組合,或者調整超參的範圍。

在這裏插入圖片描述

本文分爲以下兩個部分:

  1. 如何安裝並使用NNI
  2. 調試經驗 & 錯誤彙總
第一步:安裝

nni的安裝十分簡單。通過pip命令就可以安裝了。並且提供了example供參考學習。
先決條件:tensorflow,python >= 3.5,

	# 安裝nni
    python3 -m pip install --upgrade nni

	# 示例程序,用於學習
	git clone https://github.com/Microsoft/nni.git
    # 如果想運行這個示例程序,需要安裝tensorflow
    python3 -m pip install tensorflow

第二步:設置超參數的搜索範圍

我們打開NNI的示例程序先來觀摩一下

cd ./nni/examples/trials/mnist/

可以看到目錄中有 config.yml, mnist.py ,search_space.json 三個文件,這三個文件分別決定了我們的NNI配置文件,main.py和超參數搜索空間。
1.打開 search_space.json文件

{
    "dropout_rate":{"_type":"uniform","_value":[0.5, 0.9]},
    "conv_size":{"_type":"choice","_value":[2,3,5,7]},
    "hidden_size":{"_type":"choice","_value":[124, 512, 1024]},
    "batch_size": {"_type":"choice", "_value": [1, 4, 8, 16, 32]},
    "learning_rate":{"_type":"choice","_value":[0.0001, 0.001, 0.01, 0.1]}
}

在這裏可以定義我們的超參數和搜索範圍,可以根據自己的需要隨意調整。
搜索的類型有很多種,常用的有uniform,choice等。
但是因爲這個example只寫了uniform和choice的用法,所以很多其他博客只介紹了choice和uniform的用法,在這裏進行補充。詳細內容見NNI的github幫助文檔

{"_type": "choice", "_value": options}
# dropout_rate":{"_type":"uniform","_value":[0.5, 0.9]}的結果爲0.5或者0.9

{"_type": "uniform", "_value": [low, high]}

# 變量是 low 和 high 之間均勻分佈的值。
# 當優化時,此變量值會在兩側區間內。

{"_type": "quniform", "_value": [low, high, q]}
# 從low開始到high結束,步長爲q。
# 比如{"_type": "quniform", "_value": [0, 10, 2]}的結果爲0,2,4,6,8,10

{"_type": "normal", "_value": [mu, sigma]}
# 變量值爲實數,且爲正態分佈,均值爲 mu,標準方差爲 sigma。 優化時,此變量不受約束。

{"_type": "randint", "_value": [lower, upper]}
# 從 lower (包含) 到 upper (不包含) 中選擇一個隨機整數。

第二步:配置config.yaml
打開config.yaml

authorName: default
experimentName: example_mnist
trialConcurrency: 1
maxExecDuration: 1h
maxTrialNum: 10
#choice: local, remote, pai
trainingServicePlatform: local
searchSpacePath: search_space.json
#choice: true, false
useAnnotation: false
tuner:
  #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner, GPTuner
  #SMAC (SMAC should be installed through nnictl)
  builtinTunerName: TPE
  classArgs:
    #choice: maximize, minimize
    optimize_mode: maximize
trial:
  command: python3 mnist.py
  codeDir: .
  gpuNum: 0

除了command,maxExecDuration,trialConcurrency,gpuNum,optimize_mode需要更改,這裏的參數一般不需要更改。

command是nni的運行後將要執行的指令,mnist.py改爲你的main.py或者train.py等等主程序。

maxExecDuration是整個NNI自動調參的時間,注意不是一次訓練的時間(我一開始就理解成了一次訓練所需要的最大時間),假如你用一個gpu跑,要訓練10種不同的參數,每次訓練都要2小時,這個值就設置爲20h

trialConcurrency是trail的併發數,這個需要根據自己的GPU數量設置,而不是下面的gpuNum!!!爲什麼呢,因爲一個trail代表一次調參的過程,理解爲用一種超參數在運行你的train.py,併發數設爲x,就有x個trainer在訓練!

gpuNum是每個trail所需要的gpu個數,而不是整個nni調參所需要的gpu個數。對於大型任務,單獨訓練一次需要N個GPU的話,這個值就設置爲N;如果單次訓練,一個GPU就足夠,請把這個值設置爲1;沒有GPU?我要寫個慘字…

所以你最後需要的GPU總數爲trialConcurrencygpuNum,即 trail的個數每個trail需要的gpu個數

optimize_mode對應着優化的方向,有最大和最小兩種方式,具體如何設置在下一步中提到。
一般來說這裏的配置已經足夠。

如果需要調節網格搜索的算法等等更細節的東西,請參考NNI的github幫助文檔

第三步 修改我們的代碼
# 引入nni
import nni
"""
設置參數自動更新,假設params 是我們的默認參數
注意params是**字典**類型的變量
"""
params = vars(get_params())
tuner_params= nni.get_next_parameter() # 這會獲得一組搜索空間中的參數
params.update(tuner_params)
"""
向nni報告我們的結果
如果test_acc是準確率,那第二步(5)optimize_mode就選maximize。如果這裏的test_acc如果是loss,
那第二步(5)optimize_mode就選minimize,也可以填其他訓練的指標
另外這裏的報告結果都是數字,一般選擇float類型
"""
nni.report_intermediate_result(test_acc)
'''
report_intermediate_result是彙報中間結果,一般可以設置每個epoch報告一次
'''
nni.report_final_result(best_acc)
'''
report_final_result是彙報最終結果,可以是last_acc,也可以設置爲報告best_acc
'''

很多體驗者說report_intermediate_result彙報loss,report_final_result彙報精確度,這種說法是錯的。
這兩個report的內容應該是一個意義的(都是loss or 都是準確度 or 其他)
原因下面會講到

第四步 兩行代碼直接運行
cd ./YourCode_dir
nnictl create --config config.yml -p 8888

切換到代碼的目錄下,直接運行。
-p代表使用的端口號。注意如果代碼使用的是conda虛擬環境,需要激活conda虛擬環境。

第五步 查看訓練過程

相信此刻你應該看到了succes的字樣,別興奮,這並不代表成功開始調參了,反正我是不知道多少次才成功。

打開命令行給的網站,如下圖,點開Trail Detial->Intermediate result
在這裏插入圖片描述
如果你打開的太快,應該是WATING的狀態。別急,稍等一會兒就開始RUNNING了。如果直接Fail了,請檢查你的代碼。

如果report_intermediate_result是每一個epoch report一次,那麼跑完一個epoch過後會看到有Default metric,後面加了個括號(LATEST),這個時候基本就大工告成了,恭喜你!

如果report_final_result是訓練結束時report,那麼等訓練結束後會有Default metric(FINAL)的數值。

所以這說明了report_intermediate_result和report_final_result其實都是Default metric,是一個意義的衡量指標,都用於衡量模型的好壞。

下圖是超參數曲線,其實從上圖可以看出來我剛始調參不久,只有幾個trail是SUCCEED的。不過我想說,在這種條件下!!這個曲線也太美了吧!!!
在這裏插入圖片描述

第六步 停止

在你不想繼續搜尋超參數的時候,可以使用nnictl stop停止自動調參。
但是這只是說不會開始下一個trail了,沒有運行完的trail依然會繼續執行。如果想終止trail可以用nvidia-smi中找到訓練進程的PID,然後用kill -9 PID殺死進程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章