新手煉丹經(jīng)驗總結(jié)
當(dāng)你初入江湖,迷茫不知道該干什么的時候,不妨去模仿前人是如何進(jìn)行科研的,并從中歸納出最適合自己的道路。為此,我們推出“學(xué)術(shù)人生”專欄,介紹科研的方法與經(jīng)驗,為你的科研學(xué)習(xí)提供幫助,敬請關(guān)注。
煉丹入坑三年多,來總結(jié)一些經(jīng)驗,本文旨在幫助小白少走彎路,大佬輕噴:
本文源于一個舊回答:你有哪些deep learning(rnn、cnn)調(diào)參的經(jīng)驗?[1]我的工作可以參見 我的Github[2],一股濃濃調(diào)參風(fēng),所以感覺能來說點小經(jīng)驗。另,曠視研究院目前在春招實習(xí)生,歡迎大家投遞。
01、準(zhǔn)備工作
大部分情況下,我們的工作應(yīng)該站在巨人的肩膀上,切忌空中樓閣和徒手造輪子。在實踐中建議琢磨以下兩問:a. 目前的問題是否可能用神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)?b. 是否有人做過類似的工作?
a. 即使有數(shù)據(jù),神經(jīng)網(wǎng)絡(luò)不是萬能求解器。在視覺任務(wù)中的經(jīng)驗規(guī)律是,神經(jīng)網(wǎng)絡(luò)的水平普遍高于普通人,弱于專家。理解“不能被神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)”的任務(wù)比較困難,通常可以把問題做分解和規(guī)約。舉例,因為神經(jīng)網(wǎng)絡(luò)可以做圖片一千類別分類,那么訓(xùn)練分類器分類一個人有沒有戴口罩很可行;因為讓神經(jīng)網(wǎng)絡(luò)生成一張高分辨率圖片比較難,所以讓神經(jīng)網(wǎng)絡(luò)端到端生成抖音短視頻會非常難。
b. 最令人心態(tài)崩潰的事情有:開始寫了一半論文才發(fā)現(xiàn)別人早就發(fā)表過了;搞了個把月的項目,不如人家 git clone 下來一鍵生成水平。通過文獻(xiàn)調(diào)研和 paperswithcode,可以避免這類問題發(fā)生。有一個高的起點非常重要,做學(xué)校的課程項目時,同學(xué)們往往喜歡用一個很差的基準(zhǔn),跑一些不強的對比實驗,但正經(jīng)的研究工作,往往要從一個很強的基準(zhǔn)開始著手改進(jìn)。盡量不要在玩具級別的數(shù)據(jù)集或任務(wù)上做研究,比如 MNIST(有少數(shù)例外)。
02、煉丹方法論
以下總結(jié)了這幾年對我影響較大的幾個方法論。a. 可復(fù)現(xiàn)性。b. 高效實驗。c. 防呆實驗。
a. 有的朋友在煉丹的時候從頭到尾只維護(hù)若干份代碼,每次載入前一次的訓(xùn)練參數(shù),改一下代碼再煉,俗稱 老丹 。這樣會有很多問題:某次引入一個 bug,過了很久才發(fā)現(xiàn),不知道影響范圍;得到一個好模型,但是沒人知道它是怎么來的;忘了自己的 baseline 長什么樣,不知道改動是正向還是負(fù)向。
我們要盡可能確保每一個模型有可復(fù)現(xiàn)性,實踐上建議固定隨機(jī)種子,且不在訓(xùn)練過程中再改動訓(xùn)練代碼。訓(xùn)練新的模型時,把舊的代碼復(fù)制一遍。得到的實驗結(jié)果要開個文檔記下來以便日后總結(jié),避免遺忘。后續(xù)總結(jié)回顧實驗記錄,往往能獲得靈感。
b. 不是每一個實驗都要出一個好模型, 實驗是為了驗證結(jié)論的 。如果每個實驗都要 8 張卡跑兩個星期,人力物力都耗不起。盡力把實驗控制在單卡一天以內(nèi),理想狀態(tài)是半天得一次結(jié)論。理論上來說,水多加面面多加水(加數(shù)據(jù)加計算量)的做法無限漲點。建議先設(shè)一個目標(biāo),比如說就是在半天的訓(xùn)練時間下做對比實驗。等到實驗比較成熟以后再做大實驗。
我的實踐經(jīng)驗是,優(yōu)先選用小骨干網(wǎng)絡(luò) + 更小的輸入,直到消除了大部分 bugs;用 cProfile 來找找性能瓶頸(訓(xùn)練工程寫的不夠好時,常常有一大半時間耗費數(shù)據(jù)傳輸,我曾經(jīng)發(fā)現(xiàn)某個工程數(shù)據(jù)處理中一大半時間在調(diào)用 numpy 的 round 函數(shù),還有某個工程大部分的時間開銷在線程鎖上),解決這些問題能讓之后工作事半功倍。
c. 介紹幾種經(jīng)典的防呆實驗。首先可以只擬合一張圖片或者若干張圖片來觀察視覺效果,看看能不能正常過擬合。還可以把標(biāo)簽直接喂進(jìn)網(wǎng)絡(luò)中,看看網(wǎng)絡(luò)是否能夠快速學(xué)到 trivial 解。在訓(xùn)練過程中繪制訓(xùn)練集和驗證集的損失函數(shù)曲線,看是否有合理的 gap。
03、實戰(zhàn)小技巧
不迷信調(diào)參,如果發(fā)現(xiàn)一個模型對各種超參數(shù)都非常敏感,每天在各種組合上試的不亦樂乎,通常是有地方出了問題,包括測試腳本寫錯,任務(wù)定義不合理,數(shù)據(jù)太臟等。舉個例子,以前大家會非常注意一些細(xì)節(jié),比如模型初始化,輸入歸一化等,原因是當(dāng)時各種框架和算法實現(xiàn)不成熟。現(xiàn)在的框架通常在這些細(xì)節(jié)上都默認(rèn)是比較魯棒的設(shè)置,不建議特別關(guān)注。
我個人的經(jīng)驗是,優(yōu)化器用 AdamW(少數(shù)地方用 SGD with Momentum),學(xué)習(xí)率推薦 cosine learning rate,初始值選 3e-4(SGD 可以選 0.1),激活函數(shù)選 PReLU。Batchsize 取 64,盡量用多卡,如果用 torch 的話記得用 DistributedDataParallel。用上這些基本不出錯,唯一比較玄學(xué)的是 BatchNormalization,有的任務(wù)上用了就是會變差(比如超分辨率,光流估計),有的任務(wù)不用 BatchNormalization 就是不好調(diào)。不要迷信公眾號的“即插即用”方法,各種魔改優(yōu)化器、激活函數(shù)、魔幻注意力不建議碰(除非研究這個),盡量用大量研究者驗證過的方法。
如果感覺模型依然有 bugs,建議檢查以下幾條。a. 檢查模型是否正確開關(guān)了 eval 和 train 模式。b. 檢查模型每個模塊的輸入輸出范圍是否符合預(yù)期。c. 可視化帶增廣的訓(xùn)練數(shù)據(jù),看看是否符合預(yù)期(順便提一下 imgaug,這個開源庫用來做數(shù)據(jù)增廣性能很好,不容易踩坑)。
祝讀到這里的各位模型漲點!
參考文獻(xiàn)
[1]https://www.zhihu.com/question/41631631/answer/859040970
[2]https://github.com/hzwer
[3]https://arxiv.org/abs/1812.01187
[4]http://210.28.132.67/weixs/project/CNNTricks/CNNTricks.html
[5]半天2k贊火爆推特!李飛飛高徒發(fā)布33條神經(jīng)網(wǎng)絡(luò)訓(xùn)練秘技
[6]https://arxiv.org/abs/1502.03167
作者:知乎—hzwer?https://www.zhihu.com/people/hzwer
