@翻譯:huangyongye
原文鏈接: Understanding LSTM Networks
前言:其實之前就已經用過 LSTM 了,是在深度學習框架 keras 上直接用的,但是到現在對LSTM詳細的網絡結構還是不了解,心里牽掛着難受呀!今天看了 tensorflow 文檔上面推薦的這篇博文,看完這后,煥然大悟,對 LSTM 的結構理解基本上沒有太大問題。此博文寫得真真真好!!!為了幫助大家理解,也是怕日后自己對這些有遺忘的話可以迅速回想起來,所以打算對原文寫個翻譯。首先聲明,由於本人水平有限,如有翻譯不好或理解有誤的多多指出!此外,本譯文也不是和原文一字一句對應的,為了方便理解可能會做一些調整和修改。另外本文是作為我自己的學習筆記,沒有經過原作者本人的授權,所以請勿轉載)
1. 循環神經網絡(RNNs)
人們思考問題往往不是從零開始的。就好像你現在閱讀這篇文章一樣,你對每個詞的理解都會依賴於你前面看到的一些詞,而不是把你前面看的內容全部拋棄了,忘記了,再去理解這個單詞。也就是說,人們的思維總是會有延續性的。
傳統的神經網絡是做不到這樣的延續性(它們沒辦法保留對前文的理解),這似乎成了它們一個巨大的缺陷。舉個例子,在觀看影片中,你想辦法去對每一幀畫面上正在發生的事情做一個分類理解。目前還沒有明確的辦法利用傳統的網絡把對影片中前面發生的事件添加進來幫助理解后面的畫面。
但是,循環神經網絡可以做到。在RNNs的網絡中,有一個循環的操作,使得它們能夠保留之前學習到的內容。

Fig1. RNNs 網絡結構
在上圖網絡結構中,對於矩形塊 A 的那部分,通過輸入xt(t時刻的特征向量),它會輸出一個結果ht(t時刻的狀態或者輸出)。網絡中的循環結構使得某個時刻的狀態能夠傳到下一個時刻。(譯者注:因為當前時刻的狀態會作為下一時刻輸入的一部分)
這些循環的結構讓 RNNs 看起來有些難以理解。但是,你稍微想一下就會發現,這似乎和普通的神經網絡有不少相似之處呀。我們可以把 RNNs 看成是一個普通的網絡做了多次復制后疊加在一起組成的。每一網絡會把它的輸出傳遞到下一個網絡中。我們可以把 RNNs 在時間步上進行展開,就得到下圖這樣:

fig2. RNNs 展開網絡結構
從 RNNs 鏈狀的結構很容易理解到它是和序列信息相關的。這種結構似乎生來就是為了解決序列相關問題的。
而且,它們的的確確非常管用!在最近的幾年中,人們利用 RNNs 不可思議地解決了各種各樣的問題:語音識別,語言模型,翻譯,圖像(添加)字幕,等等。關於RNNs在這些方面取得的驚人成功,我們可以看 Andrej Karpathy 的博客: The Unreasonable Effectiveness of Recurrent Neural Networks.
RNNs 能夠取得這樣的成功,主要還是 LSTMs 的使用。這是一種比較特殊的 RNNs,而且對於很多任務,它比普通的 RNNs 效果要好很多很多!基本上現在所使用的循環神經網絡用的都是 LSTMs,這也正是本文后面所要解釋的網絡。
2. 長時期依賴存在的問題
RNNs 的出現,主要是因為它們能夠把以前的信息聯系到現在,從而解決現在的問題。比如,利用前面的畫面,能夠幫助我們理解當前畫面的內容。如果 RNNs 真的可以做到這個,那么它肯定是對我們的任務有幫助的。但是它真的可以 做到嗎,恐怕還得看實際情況呀!
有時候,我們在處理當前任務的時候,只需要看一下比較近的一些信息。比如在一個語言模型中,我們要通過上文來預測一下個詞可能會是什么,那么當我們看到“ the clouds are in the ?”時,不需要更多的信息,我們就能夠自然而然的想到下一個詞應該是“sky”。在這樣的情況下,我們所要預測的內容和相關信息之間的間隔很小,這種情況下 RNNs 就能夠利用過去的信息, 很容易的實現。

fig2. 短期依賴
但是,有些情況是需要更多的上下文信息。比如我們要預測“I grew up in France … (此處省略1萬字)… I speak ?”這個預測的詞應該是 Franch,但是我們是要通過很長很長之前提到的信息,才能做出這個正確的預測的呀,普通的 RNNs 很難做到這個。
隨着預測信息和相關信息間的間隔增大, RNNs 很難去把它們關聯起來了。

fig3. 長期依賴
從理論上來講,通過選擇合適的參數,RNNs 確實是可以把這種長時期的依賴關系(“long-term dependencies”) 聯系起來,並解決這類問題的。但遺憾的是在實際中, RNNs 無法解決這個問題。 Hochreiter (1991) [German] 和 Bengio, et al. (1994) 曾經對這個問題進行過深入的研究,發現 RNNs 的確很難解決這個問題。
但是非常幸運,LSTMs 能夠幫我們解決這個問題。
3. LSTM 網絡
長短期記憶網絡(Long Short Term Memory networks) - 通常叫做 “LSTMs” —— 是 RNN 中一個特殊的類型。由Hochreiter & Schmidhuber (1997)提出,廣受歡迎,之后也得到了很多人們的改進調整。LSTMs 被廣泛地用於解決各類問題,並都取得了非常棒的效果。
明確來說,設計 LSTMs 主要是為了避免前面提到的 長時期依賴 (long-term dependency )的問題。它們的本質就是能夠記住很長時期內的信息,而且非常輕松就能做到。
所有循環神經網絡結構都是由完全相同結構的(神經網絡)模塊進行復制而成的。在普通的RNNs 中,這個模塊結構非常簡單,比如僅是一個單一的 tanh 層。

fig4. 普通 RNNs 內部結構
LSTMs 也有類似的結構(譯者注:唯一的區別就是中間部分)。但是它們不再只是用一個單一的 tanh 層,而是用了四個相互作用的層。

fig5. LSTM 內部結構
別擔心,別讓這個結構給嚇着了,下面根據這個結構,我們把它解剖開,一步一步地來理解它(耐心看下去,你一定可以理解的)。現在,我們先來定義一下用到的符號:

fig6. 符號說明
在網絡結構圖中,每條線都傳遞着一個向量,從一個節點中輸出,然后輸入到另一個節點中。粉紅色的圓圈表示逐點操作,比如向量相加;黃色的矩形框表示的是一個神經網絡層(就是很多個神經節點);合並的線表示把兩條線上所攜帶的向量進行合並(比如一個帶 ht−1,另一個帶 xt , 那么合並后的輸出就是[ht−1,xt]); 分開的線表示將線上傳遞的向量復制一份,傳給兩個地方。
3.1 LSTMs 的核心思想
LSTMs 最關鍵的地方在於 cell(整個綠色的框就是一個 cell) 的狀態 和 結構圖上面的那條橫穿的水平線。
cell 狀態的傳輸就像一條傳送帶,向量從整個 cell 中穿過,只是做了少量的線性操作。這種結構能夠很輕松地實現信息從整個 cell 中穿過而不做改變。(譯者注:這樣我們就可以實現了長時期的記憶保留了)

fig7. 傳送帶結構
若只有上面的那條水平線是沒辦法實現添加或者刪除信息的。而是通過一種叫做 門(gates) 的結構來實現的。
門 可以實現選擇性地讓信息通過,主要是通過一個 sigmoid 的神經層 和一個逐點相乘的操作來實現的。

fig8. 門結構(sigmoid 層)
sigmoid 層輸出(是一個向量)的每個元素都是一個在 0 和 1 之間的實數,表示讓對應信息通過的權重(或者占比)。比如, 0 表示“不讓任何信息通過”, 1 表示“讓所有信息通過”。
每個 LSTM 有三個這樣的門結構,來實現保護和控制信息。(譯者注:分別是 “forget gate layer”, 遺忘門; “input gate layer”,傳入門; “output gate layer”, 輸出門)
3.2 逐步理解 LSTM
(好了,終於來到最激動的時刻了)
3.2.1 遺忘門
首先是 LSTM 要決定讓那些信息繼續通過這個 cell,這是通過一個叫做“forget gate layer ”的sigmoid 神經層來實現的。它的輸入是ht−1和xt,輸出是一個數值都在 0,1 之間的向量(向量長度和 cell 的狀態 Ct−1 一樣),表示讓 Ct−1的各部分信息通過的比重。 0 表示“不讓任何信息通過”, 1 表示“讓所有信息通過”。
回到我們上面提到的語言模型中,我們要根據所有的上文信息來預測下一個詞。這種情況下,每個 cell 的狀態中都應該包含了當前主語的性別信息(保留信息),這樣接下來我們才能夠正確地使用代詞。但是當我們又開始描述一個新的主語時,就應該把上文中的主語性別給忘了才對(忘記信息)。

fig9. 遺忘門 (forget gates)
3.2.2 傳入門
下一步是決定讓多少新的信息加入到 cell 狀態 中來。實現這個需要包括兩個 步驟:首先,一個叫做“input gate layer ”的 sigmoid 層決定哪些信息需要更新;一個 tanh 層生成一個向量,也就是備選的用來更新的內容,Ct~ 。在下一步,我們把這兩部分聯合起來,對 cell 的狀態進行一個更新。

fig10. 傳入門 (input gates)
在我們的語言模型的例子中,我們想把新的主語性別信息添加到 cell 狀態中,來替換掉老的狀態信息。
有了上述的結構,我們就能夠更新 cell 狀態了, 即把Ct−1更新為 Ct。 從結構圖中應該能一目了然, 首先我們把舊的狀態 Ct−1和ft相乘, 把一些不想保留的信息忘掉。然后加上it∗Ct~。這部分信息就是我們要添加的新內容。

fig11. 更新 cell 狀態
3.2.3 輸出門
最后,我們需要來決定輸出什么值了。這個輸出主要是依賴於 cell 的狀態Ct,但是又不僅僅依賴於 Ct,而是需要經過一個過濾的處理。首先,我們還是使用一個 sigmoid 層來(計算出)決定Ct中的哪部分信息會被輸出。接着,我們把Ct通過一個 tanh 層(把數值都歸到 -1 和 1 之間),然后把 tanh 層的輸出和 sigmoid 層計算出來的權重相乘,這樣就得到了最后輸出的結果。
在語言模型例子中,假設我們的模型剛剛接觸了一個代詞,接下來可能要輸出一個動詞,這個輸出可能就和代詞的信息相關了。比如說,這個動詞應該采用單數形式還是復數的形式,那么我們就得把剛學到的和代詞相關的信息都加入到 cell 狀態中來,才能夠進行正確的預測。

fig12. cell 輸出
4. LSTM 的變種 GRU
原文這部分介紹了 LSTM 的幾個變種,還有這些變形的作用。在這里我就不再寫了。有興趣的可以直接閱讀原文。
下面主要講一下其中比較著名的變種 GRU(Gated Recurrent Unit ),這是由 Cho, et al. (2014) 提出。在 GRU 中,如 fig.13 所示,只有兩個門:重置門(reset gate)和更新門(update gate)。同時在這個結構中,把細胞狀態和隱藏狀態進行了合並。最后模型比標准的 LSTM 結構要簡單,而且這個結構后來也非常流行。

fig13. GRU結構
其中, rt 表示重置門,zt 表示更新門。重置門決定是否將之前的狀態忘記。(作用相當於合並了 LSTM 中的遺忘門和傳入門)當 rt 趨於 0 的時候,前一個時刻的狀態信息 ht−1 會被忘掉,隱藏狀態 ht~ 會被重置為當前輸入的信息。更新門決定是否要將隱藏狀態更新為新的狀態ht~(作用相當於 LSTM 中的輸出門) 。
和 LSTM 比較一下:
- (1) GRU 少一個門,同時少了細胞狀態 Ct。
- (2) 在 LSTM 中,通過遺忘門和傳入門控制信息的保留和傳入;GRU 則通過重置門來控制是否要保留原來隱藏狀態的信息,但是不再限制當前信息的傳入。
- (3) 在 LSTM 中,雖然得到了新的細胞狀態 Ct,但是還不能直接輸出,而是需要經過一個過濾的處理: ht=ot∗tanh(Ct); 同樣,在 GRU 中, 雖然 (2) 中我們也得到了新的隱藏狀態 ht~, 但是還不能直接輸出,而是通過更新門來控制最后的輸出: ht=(1−zt)∗ht−1+zt∗ht~ 。
后記:好了,到這里對一般形式的 LSTM 的結構講解已經結束了,原文后面對 LSTM 的各種變形講解也比較簡單,在這里我就不再寫了,有興趣的可以直接閱讀原文。上面我結合了原論文比較詳細地介紹了一下 GRU,個人水平有限,難免也會出錯。其實英語理解能力還行的話建議還是閱讀原文比較好,有些東西翻譯過來連我自己都不知道該怎么表達了,如果您覺得有什么地方不對,歡迎指出。翻譯完后才發現網上已經有很多翻譯的版本了,所以參考那些版本又做了一些調整,主要是參考了[譯] 理解 LSTM 網絡這篇文章。后面如果有時間的話,我應該會寫個用 TensorFlow 來實現 LSTM 的例子,敬請期待,哈哈哈!
(LSTM 的例子還真寫好了,歡迎戳: TensorFlow入門(五)多層 LSTM 通俗易懂版)