你在訓練RNN的時候有哪些特殊的trick?

一直在用tensorflow訓練chatbot。試過了各種框架:
包括谷歌自己開源的tf-seq2seq
以及github上很著名的tf_chatbot項目
還有各種自己實現的,或者用tensorflow0.2裡面model.rnn的做machine translation的框架。

總之這些框架訓練了好幾天,結果都不是很理想。雖然可能是數據集的原因,但是我想問一下各位在訓練seq2seq模型的時候有沒有什麼trick來加速。或者大家一般做seq2seq時,需要多少時間?

表達能力很差,希望大家理解

---------------4-10----更新-------------------------------

大家好,我發現是我的語料相關性太差,而且網路太淺造成的。在更換語料後效果明顯提升,另外貼一組參數吧,大家可以自行去論文中找,個人覺得還是很科學的。

Topic Aware Neural Response Generation

在論文的最後,作者給出了非常詳細的參數,雖然還沒有實驗,但是有些我已經踩過的坑,覺得作者的參數非常合理

再次感謝知乎的學術氛圍!


謝@杜存宵邀。我實際上幫不上什麼忙。雖然有些了解,卻並沒有實際做過機器翻譯的項目和seq2seq。不過玩了和訓練了很多RNN(LSTM/GRU)的網路,也嘗試了各種變化。

如果你要問的是RNN的訓練,那我的回答還能有點作用。下面的並非seq2seq,而是RNN的訓練技巧。

基礎知識:

循環神經網路--介紹

循環神經網路--實現LSTM/GRU

循環神經網路--scan實現LSTM/GRU

循環神經網路--雙向LSTM/GRU

正題:

總體感覺RNN(這裡特指LSTM/GRU)的訓練確實有些tricky,很不起眼的小細節就能讓你的網路效果很糟糕,都不如全連接(前饋)網路的效果。

1. gates的權重初始化:我覺得最重要,最重要,最重要的。這不僅僅影響收斂速度,還影響最後的測試集表現。在單向RNN(LSTM/GRU)的時候,gates的初始化尤其重要。全部為0的效果基本上最差。首推orthogonal初始化。雙向RNN(LSTM/GRU)時,初始化對結果的影響會變小一些。

可以下圖中充分體會到gates的初始化的重要性

下面的圖是用3種不同的gates的初始化方式後的train/vali loss下降圖

紅色的是全部為zero初始化

綠色的是用的一種對feedforward網路非常有效的初始化方式(代碼:代碼演示LV3)

藍色的用的是orthogonal初始化(代碼:循環神經網路--雙向LSTMamp;amp;amp;amp;GRU)

虛線是Train 的loss,實線是Vali 的loss

可以看到zero初始化會讓訓練非常非常的慢,不僅是vali的loss,連train的loss都很慢

而綠色的初始化會讓train的loss迅速下降,但vali的loss卻在20 epoch左右開始上升,overfitting的現象。

藍色的orthogonal初始化的train的loss下降速度一般,但是vali的loss卻很好,三組中效果最好的。

訓練20後的loss值比較表

2. forget gate的bias初始值(LSTM時):幾乎所有的材料都會告訴你初始值為1.0會使效果變好。tensorflow自帶的LSTM的的默認值就是1.0。很多情況下都正確,但是並非絕對。我遇到過初始值為0.0比初始值為1.0的效果要好的情況。這時1.0會使train set的loss下降速度非常的快,造成驗證集的overfitting。

可以從下面的兩組train/vali loss圖裡看出來(紅色是forget gate的bias初始值為1.0,藍色是0.0;實線是vali的loss,而虛線是train的loss)。1.0的情況,train的loss急速下降(到0.061),但是vali的loss卻不好(到0.438)。而0.0的情況train的loss到0.123,但vali的loss到0.387

3. Clipping Gradients 我做過實驗比較,確實比不用要好一些。詳細解釋查閱deeplearning book的415頁。

4. Dropout/L2 regularization:不要認為你的RNN節點很少,模型參數很低,不應該出現overfitting的情況。LSTM、GRU的overfitting和全連接網路有些許的不同。gated RNN(LSTM/GRU)是相當於神經網路中嵌套著gate這樣控制數據流大小的神經網路。

gated RNN中,真正容易overfitting的是gates,而不是整體網路。

所以,即便是你的網路規模很小,只有一層的RNN,加入Dropout/L2 regularization,都會使gates對數據流的控制正加優秀,從而增加效果。

RNN(LSTM/GRU)的Dropout可以加在輸入輸出中,也可以加在gates上(驗證過,有效)。論文[1409.2329] Recurrent Neural Network Regularization,另一種[1512.05287] A Theoretically Grounded Application of Dropout in Recurrent Neural Networks (論文最後有Code)。

下圖演示的是將dropout加在input gate和output gate上的效果(其他參數一致)

加入regularization會對網路的訓練進行約束,所以比不加入regularization需要更多次的訓練。可以看出加入dropout後,vali的表現變好。而不加的話,vali的loss會隨著train loss的下降而上升。事實上,如果再加入一層RNN的話,效果會更好。意味著這個只有一層RNN的神經網路其實並不大。但仍然出現了overfitting的現象。所以個人感覺,這裡是gates的overfitting。

RNN(LSTM/GRU)的L2 regularization同樣也是加在gates的W權重之上。

5. Soft targets預訓練:從上面可以看出來RNN是很容易overfitting的(個人覺得是gates的overfitting),所以幾乎所有的regularization的可以提升效果。這個Soft targets的效果是可以與Dropout匹敵的,可以說是我用過的regularization里最好的。不過也比較麻煩。首先是獲得soft targets(RNN的soft targets可以先用全連接網路feedforward訓練後取得),其次是使用。使用方法也有兩種,像Hinton等在[1503.02531] Distilling the Knowledge in a Neural Network 里的格外增加另一個loss function的方法。不過也有另一個更簡單而且有效的方法[1505.04630] Recurrent Neural Network Training with Dark Knowledge Transfer:用soft targets預訓練,再用hard targets來fine tuning,效果很好。

關於soft targets的詳細解釋,請參照 如何理解soft target這一做法?

6. learning rate的個人習慣:我喜歡用適中並且稍微偏大的learning rate訓練,然後加入較強的regularization到vali loss停止下降3次後early stopping。再重新讀取3次以前的parameters後用較小的learning rate來fine tuning。純屬個人喜歡。感興趣的同學可以自己試試效果。

7. 雙向LSTM/GRU:雙向的效果毋庸置疑非常非常的棒,演示到目前為止最好的結果是orthogonal初始化後的單向LSTM,初始的forget gate的bias為0.0,input和output gates的dropout為0.2。在此基礎上,將LSTM變為雙向,並且使用兩層LSTM,正向與反向的LSTM cell是用sum來結合。其他參數保持不變,下面的圖就可以看出雙向的效果。

在訓練200 epoch後,vali的loss已經降低到0.214

最後:

seq2seq的chat_bot的話,兩個RNN網路的對接,應該還會加入注意力機制。這三部分不太容易確定你在訓練時出現的問題在哪裡。

做幾個對照組,你如果用tensorflow的話,創建cell的時候,注意改我上面提的幾個內容。

#version r1.0
cell = tf.contrib.rnn.LSTMCell(num_units, input_size=None, use_peepholes=False, cell_clip=None, initializer=None, num_proj=None, proj_clip=None, num_unit_shards=None, num_proj_shards=None, forget_bias=1.0, state_is_tuple=True, activation=tf.tanh)
# 改變initializer= 和forget_bias=
# 或者改成GRUCell,只改變initializer=

再參考這裡llSourcell/tensorflow_chatbot


推薦這本書,業界良心(請無視rating)

Tricks of the Trade (Lecture Notes in Computer Science): Grégoire Montavon, Geneviève Orr, Klaus-Robert Müller: 9783642352881: Amazon.com: Books


頂一下。我也遇到相同的問題


最近也在搞這個,初見成效了。但不知道這裡你說的效果不理想具體指什麼?

perplexity降不下去?test data生成的效果不行?


首先得驗證模型對不對,我們通常使用數字排序來驗證(即seq2seq的input sequence是亂序的數字,output sequence是排序後的結果),通常用比較小的網路就能做到。其次是語料,如果模型正確性有保障的話,在訓練Responding Machine的時候對語料的依賴性很大。如果語料中post和response的相關性低,很難訓練出正常的結果。即使是從Github上clone的模型,也難以保證結果。一般訓練前要對語料進行一遍清洗。

關於訓練時長,我用pytorch實現的版本,訓練400萬對大概300分鐘一個epoch。網路就是seq2seq with attention,單層單向,hidden_size 800, embedding size 400,2到3個epoch收斂。實際上訓練數據不用這麼多也能收斂,我試過20萬對的照樣能把ppl下降到正常範圍,也大概是3個epoch左右。


  • 重要的事情說三遍:orthogonal初始化,orthogonal初始化,orthogonal初始化

一個簡單易懂的文章見:Explaining and illustrating orthogonal initialization for recurrent neural networks

  • 有時orthogonal初始化+prelu/elu activation 配合使用食味更佳。。。
  • 如果是用gru,另外可以嘗試用最開始這篇文獻的decoder gru cell框架[1406.1078] Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation

就是cell的輸入多了一個context/summary的hidden state 信息。我用tf沒找到直接能調用的API不過在自帶的gru cell的基礎上改很方便


tree LSTM效果咋樣?


最近我也發現gru竟然還沒全連接效果好,我也是醉了。試試樓上良心trick再瞅瞅??

個人項目經驗:

1.gru替換fc之後,迭代次數相應變多

2.變數初始化使用正交向量

3.變數regularation

比較好一些..


推薦閱讀:

有沒有可能運用人工神經網路將一種編程語言的代碼翻譯成任意的另一種編程語言,而不經過人工設計的編譯過程?
怎麼選取訓練神經網路時的Batch size?
模式識別、機器學習、神經網路、(泛函分析?)的學習順序
機器學習中梯度下降演算法公式是不是有問題?
梯度下降or擬牛頓法?

TAG:人工智慧 | 神經網路 | 深度學習DeepLearning | TensorFlow |