同樣都是調參,為什麼人家的神經網路比我牛逼100倍?

視學演算法發表於2020-04-06

轉自 | 人工智慧前沿講習

No.1

總結一下在曠視實習兩年來的煉丹經驗,我主要做了一些 RL,影像質量,影像分類,GAN 相關的任務,日常大概佔用 5 - 10 張卡。
可復現性和一致性
有的同學在打比賽的時候,從頭到尾只維護若干份丹方(程式碼),每次載入前一次的訓練引數,調一下丹方再煉,俗稱老丹。這樣會有幾個問題:某次引入一個 bug,過了很久才發現,然後不知道影響範圍;煉出一個金丹,但是不知道它是怎麼來的;忘了自己的 baseline,不知道改動是正面還是負面。
要儘可能確保每一個丹有可復現性,實踐上建議丹方不應該在煉丹後改動,煉新的丹時,把舊的丹方複製一遍。得到的實驗結果要開個文件記下來以便日後總結,避免遺忘。我經常通過閱讀自己和別人的記錄來得到靈感。
實驗一致性上也要多做努力,理想狀態是有合理的基準來測丹的效能,同一個丹方不應該由於超參的微小改動而有顯著結果差異。出現這種情況可能是資料太少或基準設定不當。
資源利用
對於新入行的同學,不要試圖在玩具級別的資料集或任務上做靠譜的研究,比如 MNIST。
不是每一個實驗都要出一個金丹,實驗是為了驗證結論的。如果每個實驗都要 8 張卡跑兩個星期,人力物力都耗不起。盡力把實驗控制在單卡一天以內,理想狀態是半天得一次結論。理論上來說,水多加面面多加水(加資料加計算量)的做法無限漲點。建議先設一個目標,比如說就是在一天的訓練時間下做對比實驗。
我的實踐經驗是,首先用小圖小模型,比如 128 x 128 輸入的 ResNet18;用 cProfile 來找效能瓶頸,比如我發現某個丹,煉的時候有一大半時間耗費在等資料,資料處理中一大半時間在呼叫 numpy 的 round 函式,前期把精力集中在提高做實驗的效率上。
模型不 work
先把錦上添花的東西去掉,比如資料增廣,玄學學習率和超參,魔幻損失函式,異形模型。如果世界上有一個非要加旋轉增廣和 1.96e-4 學習率 42 batchsize,配上四種混合損失函式才能煉好的丹,它應該存在於靈能文明。可以先造一些儘量玩具的模型,驗證程式碼正確性。
需要進一步改進
先確認影響模型效能的元件。感性認識就是,資料是否需要增加或增廣。模型是大了還是小了,再根據速度和精度期望開始尋找合適的模型。能用全卷積的任務,少用全連線層,引數量小。基本模型上 ResNet, Unet 結構還是主流。
當你的模型有 Batch Normalization,初始化通常不需要操心,啟用函式預設 Relu 即可(某引用數萬的大佬說的)。一般順序是 Conv - BN - Relu。如果沒有 BN(很多工上,BN降低訓練難度,但是可能影響最終效能 ),試著要做一些資料歸一化。
雖然有至少十種啟用函式,但在 Relu 外只推薦試一下 Swish。煉丹術只推薦 Momentum 和 Adam。在這些方面做嘗試意義不大,如果效能提升反倒可能說明模型不成熟。不推薦做人肉模型設計,比如把某層卷積改大一點,或者微調一下通道數。除非有特別 insight,不要自己亂設計新元件。
超參上,learning rate 最重要,推薦瞭解 cosine learning rate 和 cyclic learning rate,其次是 batchsize 和 weight decay。當你的丹還不錯的時候,可以試著做資料增廣和改損失函式錦上添花了。
祝讀到這裡的各位模型漲點!
參考文獻
  • Bag of Tricks for Image Classification with Convolutional Neural Networks,trick 合集 1。
  • Must Know Tips/Tricks in Deep Neural Networks,trick 合集 2。
  • 33條神經網路訓練祕技,trick 合集 3。
  • 26秒單GPU訓練CIFAR10,工程實踐。
  • Batch Normalization,雖然玄學,但是養活了很多煉丹師。
  • Searching for Activation Functions,swish 啟用函式。
作者:hzwer
https://www.zhihu.com/question/41631631/answer/859040970

No.2

訓練技巧對深度學習來說是非常重要的,作為一門實驗性質很強的科學,同樣的網路結構使用不同的訓練方法訓練,結果可能會有很大的差異。這裡我總結了近一年來的煉丹心得,分享給大家,也歡迎大家補充指正。
引數初始化
下面幾種方式,隨便選一個,結果基本都差不多。但是一定要做。否則可能會減慢收斂速度,影響收斂結果,甚至造成Nan等一系列問題。
下面的n_in為網路的輸入大小,n_out為網路的輸出大小,n為n_in或(n_in+n_out)*0.5
Xavier初始法論文:
http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf
He初始化論文:https://arxiv.org/abs/1502.01852
  • uniform均勻分佈初始化:
    w = np.random.uniform(low=-scale, high=scale, size=[n_in,n_out])
    • Xavier初始法,適用於普通啟用函式(tanh,sigmoid):scale = np.sqrt(3/n)
    • He初始化,適用於ReLU:scale = np.sqrt(6/n)
  • normal高斯分佈初始化:
    w = np.random.randn(n_in,n_out) * stdev # stdev為高斯分佈的標準差,均值設為0
    • Xavier初始法,適用於普通啟用函式 (tanh,sigmoid):stdev = np.sqrt(n)
    • He初始化,適用於ReLU:stdev = np.sqrt(2/n)
  • svd初始化:對RNN有比較好的效果。參考論文:https://arxiv.org/abs/1312.6120
資料預處理方式
  • zero-center ,這個挺常用的.
    X -= np.mean(X, axis = 0) # zero-center
    X /= np.std(X, axis = 0) # normalize
  • PCA whitening,這個用的比較少.
訓練技巧
  • 要做梯度歸一化,即算出來的梯度除以minibatch size
  • clip c(梯度裁剪): 限制最大梯度,其實是value = sqrt(w1^2+w2^2….),如果value超過了閾值,就算一個衰減繫系數,讓value的值等於閾值: 5,10,15
  • dropout對小資料防止過擬合有很好的效果,值一般設為0.5,小資料上dropout+sgd在我的大部分實驗中,效果提升都非常明顯.因此可能的話,建議一定要嘗試一下。dropout的位置比較有講究, 對於RNN,建議放到輸入->RNN與RNN->輸出的位置.關於RNN如何用dropout,可以參考這篇論文:http://arxiv.org/abs/1409.2329
  • adam,adadelta等,在小資料上,我這裡實驗的效果不如sgd, sgd收斂速度會慢一些,但是最終收斂後的結果,一般都比較好。如果使用sgd的話,可以選擇從1.0或者0.1的學習率開始,隔一段時間,在驗證集上檢查一下,如果cost沒有下降,就對學習率減半. 我看過很多論文都這麼搞,我自己實驗的結果也很好. 當然,也可以先用ada系列先跑,最後快收斂的時候,更換成sgd繼續訓練.同樣也會有提升.據說adadelta一般在分類問題上效果比較好,adam在生成問題上效果比較好。
  • 除了gate之類的地方,需要把輸出限制成0-1之外,儘量不要用sigmoid,可以用tanh或者relu之類的啟用函式.1. sigmoid函式在-4到4的區間裡,才有較大的梯度。之外的區間,梯度接近0,很容易造成梯度消失問題。2. 輸入0均值,sigmoid函式的輸出不是0均值的。
  • rnn的dim和embdding size,一般從128上下開始調整. batch size,一般從128左右開始調整.batch size合適最重要,並不是越大越好.
  • word2vec初始化,在小資料上,不僅可以有效提高收斂速度,也可以可以提高結果.
  • 儘量對資料做shuffle
  • LSTM 的forget gate的bias,用1.0或者更大的值做初始化,可以取得更好的結果,來自這篇論文:http://jmlr.org/proceedings/papers/v37/jozefowicz15.pdf, 我這裡實驗設成1.0,可以提高收斂速度.實際使用中,不同的任務,可能需要嘗試不同的值.
  • Batch Normalization據說可以提升效果,不過我沒有嘗試過,建議作為最後提升模型的手段,參考論文:Accelerating Deep Network Training by Reducing Internal Covariate Shift
  • 如果你的模型包含全連線層(MLP),並且輸入和輸出大小一樣,可以考慮將MLP替換成Highway Network,我嘗試對結果有一點提升,建議作為最後提升模型的手段,原理很簡單,就是給輸出加了一個gate來控制資訊的流動,詳細介紹請參考論文: http://arxiv.org/abs/1505.00387
  • 來自@張馨宇的技巧:一輪加正則,一輪不加正則,反覆進行。
Ensemble
Ensemble是論文刷結果的終極核武器,深度學習中一般有以下幾種方式
  • 同樣的引數,不同的初始化方式
  • 不同的引數,通過cross-validation,選取最好的幾組
  • 同樣的引數,模型訓練的不同階段,即不同迭代次數的模型。
  • 不同的模型,進行線性融合. 例如RNN和傳統模型.
作者:蕭瑟
https://www.zhihu.com/question/41631631/answer/94816420

No.3

總結一下我遇到的小朋友常犯的錯:
1、一上來就自己動手寫模型。建議首先用成熟的開源專案及其預設配置(例如 Gluon 對經典模型的各種復現、各個著名模型作者自己放出來的程式碼倉庫)在自己的資料集上跑一遍,在等程式執行結束的時間裡仔細研究一下程式碼裡的各種細節,最後再自己寫或者改程式碼。
2、訓 RNN 不加 gradient clipping,導致訓練一段時間以後 loss 突然變成 Nan。
3、tying input & output embedding(就是詞向量層和輸出 softmax 前的矩陣共享引數,在語言模型或機器翻譯中常用)時學習率需要設定得非常小,不然容易 Nan。
4、在資料集很大的情況下,一上來就跑全量資料。建議先用 1/100、1/10 的資料跑一跑,對模型效能和訓練時間有個底,外推一下全量資料到底需要跑多久。在沒有足夠的信心前不做大規模實驗。
5、只喜歡漂亮的模型結構,瞧不起調引數的論文/實驗報告,看論文時經常不看超引數設定等細節。舉個例子,現在還有相當多的人不知道 BERT 的啟用函式是 GELU 而不是 transformer 原論文中的 ReLU。在自己沒有太多資源實驗的情況下,實驗報告類文章簡直是業界良心好不好!
NLP 領域主要推薦以下幾篇:
Regularizing and Optimizing LSTM Language Models(LSTM 的訓練技巧)
Massive Exploration of Neural Machine Translation Architectures(NMT 裡各個超參的影響)
Training Tips for the Transformer Model(訓練 Transformer 時會發生的各種現象)
RoBERTa: A Robustly Optimized BERT Pretraining Approach(BERT 預訓練技巧,雖然跟大部分人沒啥關係)
CV 我不算太熟,不過也可以勉強推薦幾篇:
Training ImageNet in 1 Hour(大批量訓練技巧)
Bag of Tricks for Image Classification with Convolutional Neural Networks(各種訓練技巧集大成)
EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks(當前對引數利用最有效的 CNN)
6、初始學習率:
有時受 batch size、sequence length 各種因素的影響,loss 很大(比如說好幾萬),對於這種數字人是沒有數感的,建議首先計算一下 per token loss(如果是多工,可以每個任務單獨算;類似地,某些 CV 任務可以計算 per pixel loss),心裡有點感覺。脫離損失函式的形式談學習率沒有意義(例如單是對 batch size 求和或者取平均這個差異就會使梯度差成百上千倍)。
在確定初始學習率的時候,從一個很小的值(例如 1e-7)開始,然後每一步指數增大學習率(例如擴大1.05 倍)進行訓練。訓練幾百步應該能觀察到損失函式隨訓練步數呈對勾形,選擇損失下降最快那一段的學習率即可。
7、Adam 可以解決一堆奇奇怪怪的問題(有時 loss 降不下去,換 Adam 瞬間就好了),也可以帶來一堆奇奇怪怪的問題(比如單詞詞頻差異很大,當前 batch 沒有的單詞的詞向量也被更新;再比如Adam和L2正則結合產生的複雜效果)。用的時候要膽大心細,萬一遇到問題找各種魔改 Adam(比如 MaskedAdam, AdamW 啥的)搶救。
8、subword 總是會很穩定地漲點,只管用就對了。
9、要有耐心!
這一條放在最後,是因為很多人不把它當一回事兒。可能是覺得這一條不需要寫程式碼所以不重要?我見過太多人因為這條浪費時間了,所以專門強調一下。
有些指標是有滯後性的,需要等訓練一段時間才開始動。很多人訓練幾步看沒什麼效果就把程式停掉開始 debug 了,但其實程式碼毫無問題。如此反覆好幾天甚至一兩週都在原地踏步,其實需要做的僅僅是讓程式自個兒安安靜靜地跑上幾個小時或者一天……
作者:Towser
https://www.zhihu.com/question/41631631/answer/862075836

- END -
如果看到這裡,說明你喜歡這篇文章,請轉發、點贊。微信搜尋「perfect_iscas」,關注後回覆「進群」或者掃描下方二維碼即可進入無廣告技術交流群。
掃描二維碼進群↓

640?wx_fmt=jpeg

640

640?wx_fmt=gif

在看 640?wx_fmt=jpeg

相關文章