當前位置: 華文問答 > 數位

你有哪些deep learning(rnn、cnn)調參的經驗?

2016-03-21數位

總結一下我遇到的小朋友常犯的錯:

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(各種訓練技巧集大成)

Bag of Freebies for Training Object Detection Neural Networks(同上)

EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks(當前對參數利用最有效的 CNN,類似地還有一篇 EfficientDet)

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、GPU 上報錯時盡量放在 CPU 上重跑,錯誤資訊更友好。例如 GPU 報 "ERROR:tensorflow:Model diverged with loss = NaN" 其實很有可能是輸入 ID 超出了 softmax 詞表的範圍。

10、要有耐心

這一條放在最後,是因為很多人不把它當一回事兒。可能是覺得這一條不需要寫程式碼所以不重要?我見過太多人因為這條浪費時間了,所以專門強調一下。

有些指標是有滯後性的,需要等訓練一段時間才開始動(例如 BN 訓練和推斷行為不一致,可能訓練的準確率已經很高了,但測試準確率很低,這是因為 BN 的統計量還不準,再等等就好了)。很多人訓練幾步看沒什麽效果就把程式停掉開始 debug 了,但其實程式碼毫無問題。如此反復好幾天甚至一兩周都在原地踏步,其實需要做的僅僅是讓程式自個兒安安靜靜地跑上幾個小時或者一天……