RNN
循環神經網絡,是非線性動態系統,將序列映射到序列,主要參數有五個:[Whv,Whh,Woh,bh,bo,h0][Whv,Whh,Woh,bh,bo,h0],典型的結構圖如下:
- 和普通神經網絡一樣,RNN有輸入層輸出層和隱含層,不一樣的是RNN在不同的時間t會有不同的狀態,其中t-1時刻隱含層的輸出會作用到t時刻的隱含層.
- 參數意義是: WhvWhv:輸入層到隱含層的權重參數,WhhWhh:隱含層到隱含層的權重參數,WohWoh:隱含層到輸出層的權重參數,bhbh:隱含層的偏移量,bobo輸出層的偏移量,h0h0:起始狀態的隱含層的輸出,一般初始為0.
- 不同時間的狀態共享相同的權重w和偏移量b
RNN的計算方式
給定一個損失函數 L(z,y)=∑Tt=1L(zt,yt)L(z,y)=∑t=1TL(zt,yt)
RNN因為加入了時間序列,因此訓練過程也是和之前的網絡不一樣,RNN的訓練使用的是BPTT(Back Prropagation Through TIme),該方法是由Werbo等人在1990年提出來的。
上面的算法也就是求解梯度的過程,使用的也是經典的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激活函數)。
參數量
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)
LSTM
假設我們試着去預測“I grew up in France... I speak fluent French”最后的詞。當前的信息建議下一個詞可能是一種語言的名字,但是如果我們需要弄清楚是什么語言,我們是需要先前提到的離當前位置很遠的 France的上下文的。這說明相關信息和當前預測位置之間的間隔就肯定變得相當的大。
不幸的是,在這個間隔不斷增大時,RNN會喪失學習到連接如此遠的信息的能力。在理論上,RNN絕對可以處理"長期依賴"問題。人們可以仔細挑選參數來解決這類問題中的最初級形式,但在實踐中,RNN 肯定不能夠成功學習到這些知識。Bengio, et al.等人對該問題進行了深入的研究,他們發現一些使訓練 RNN 變得非常困難的根本原因。
然而,幸運的是,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)。
GRU
LSTM有很多變體,其中較大改動的是Gated Recurrent Unit (GRU),這是由 Cho, et al. (2014)提出。它將忘記門和輸入門合成了一個單一的 更新門。同樣還混合了細胞狀態和隱藏狀態,和其他一些改動。最終的模型比標准的 LSTM模型要簡單。效果和LSTM差不多,但是參數少了1/3,不容易過擬合。