循環神經網絡,是非線性動態系統,將序列映射到序列,主要參數有五個:[Whv,Whh,Woh,bh,bo,h0][Whv,Whh,Woh,bh,bo,h0],典型的結構圖以下:html
給定一個損失函數 L(z,y)=∑Tt=1L(zt,yt)L(z,y)=∑t=1TL(zt,yt)git
RNN由於加入了時間序列,所以訓練過程也是和以前的網絡不同,RNN的訓練使用的是BPTT(Back Prropagation Through TIme),該方法是由Werbo等人在1990年提出來的。github
上面的算法也就是求解梯度的過程,使用的也是經典的BP算法,並無什麼新鮮的。可是值得一提的是,在 t-1 時刻對 ht−1ht−1的求導值,也需加上t時刻的求導中對ht−1ht−1 的求導值,所以BPTT也是一個鏈式的求導過程。算法
可是由於上面算法中的第10行,在訓練t時刻的時候,出現了t-1的參數,所以對單個的求導就變成了對整個以前狀態的求導之和。網絡
也正是由於存在長依賴關係,BPTT沒法解決長時依賴問題(即當前的輸出與前面很長的一段序列有關,通常超過十步就無能爲力了),由於BPTT會帶來所謂的梯度消失或梯度爆炸問題(the vanishing/exploding gradient problem)。函數
這篇文章很好的解釋了爲何會產生梯度消失和爲何會梯度爆炸的問題,其實主要問題就是由於在BPTT算法中,以w爲例,其求導過程的鏈太長,而太長的求導鏈在以tanh爲激活函數(其求導值在0~1之間的BPTT中,連乘就會使得最終的求導爲0,這就是梯度消失問題,也就是t時刻已經學習不到t-N時刻的參數了。固然,有不少方法去解決這個問題,如LSTMs即是專門應對這種問題的,還有一些方法,好比設計一個更好的初始參數以及更換激活函數(如換成ReLU激活函數)。post
model.add(Embedding(output_dim=32, input_dim=2800, input_length=380)) model.add(SimpleRNN(units=16)) model.add(Dense(uints=256, activation=relu)) ... model.summary() #output simple_rnn_1 (SimpleRNN) param # 784 dense_1 (Dense) param # 4352
其中:784=16+1616+1632( WhvWhv + WhhWhh + bhbh)學習
假設咱們試着去預測「I grew up in France... I speak fluent French」最後的詞。當前的信息建議下一個詞多是一種語言的名字,可是若是咱們須要弄清楚是什麼語言,咱們是須要先前提到的離當前位置很遠的 France的上下文的。這說明相關信息和當前預測位置之間的間隔就確定變得至關的大。ui
不幸的是,在這個間隔不斷增大時,RNN會喪失學習到鏈接如此遠的信息的能力。在理論上,RNN絕對能夠處理"長期依賴"問題。人們能夠仔細挑選參數來解決這類問題中的最初級形式,但在實踐中,RNN 確定不可以成功學習到這些知識。Bengio, et al.等人對該問題進行了深刻的研究,他們發現一些使訓練 RNN 變得很是困難的根本緣由。atom
然而,幸運的是,LSTM 並無這個問題!
LSTM 由Hochreiter & Schmidhuber (1997)提出,並在近期被Alex Graves進行了改良和推廣。在不少問題,LSTM 都取得至關巨大的成功,並獲得了普遍的使用。
LSTM 經過刻意的設計來避免長期依賴問題。記住長期的信息在實踐中是 LSTM 的默認行爲,而非須要付出很大代價才能得到的能力!
全部 RNN 都具備一種重複神經網絡模塊的鏈式的形式。在標準的 RNN 中,這個重複的模塊只有一個很是簡單的結構。
LSTM 一樣是這樣的結構,可是重複的模塊擁有一個不一樣的結構。不一樣於單一神經網絡層,以一種很是特殊的方式進行交互。
LSTM 中的第一步是決定咱們會從細胞狀態中丟棄什麼信息。這個決定經過一個稱爲忘記門層完成。
下一步是肯定什麼樣的新信息被存放在細胞狀態中。
咱們把舊狀態與 ftft 相乘,丟棄掉咱們肯定須要丟棄的信息。接着加上 it∗C~tit∗C~t。這就是新的候選值,根據咱們決定更新每一個狀態的程度進行變化。
最終,咱們須要肯定輸出什麼值。這個輸出將會基於咱們的細胞狀態,可是也是一個過濾後的版本。
咱們到目前爲止都還在介紹正常的 LSTM。可是不是全部的 LSTM 都長成一個樣子的。實際上,幾乎全部包含 LSTM 的論文都採用了微小的變體。
圖中最上面的一條線的狀態即 s(t) 表明了長時記憶,而下面的 h(t)則表明了工做記憶或短時記憶。
model.add(Embedding(output_dim=32, input_dim=2800, input_length=380)) model.add(LSTM(32)) model.add(Dense(uints=256, activation=relu)) ... model.summary() #output lstm_1 (LSTM) param # 8320
其中:8320=(32+32)324+4*32( WoWo + WCWC + WiWi + WfWf + bobo + bCbC + bibi + bfbf)。
LSTM有不少變體,其中較大改動的是Gated Recurrent Unit (GRU),這是由 Cho, et al. (2014)提出。它將忘記門和輸入門合成了一個單一的 更新門。一樣還混合了細胞狀態和隱藏狀態,和其餘一些改動。最終的模型比標準的 LSTM模型要簡單。效果和LSTM差很少,可是參數少了1/3,不容易過擬合。