本文介紹RNN模型和LSTM模型。
RNN
為什么會出現RNN
在傳統的深度神經網絡模型中,我們的輸入信息是沒有順序的,比如,NLP領域中,我們輸入單詞經常使用embedding,將詞匯映射為詞向量,然后輸入到神經網絡。但是這種輸入方式會有一些問題,比如,"我 愛 你"和"你 愛 我"在傳統的神經網絡中不能很好的識別。在這種情況下,有人提出了將n-gram信息加入到輸入層,比如fasttext,這樣,在一定程度上解決了單詞間的順序問題,但是這種方法也有一些弊端,就是我們無法捕獲長句子的單詞依賴,比如一個句子n個單詞,那么如果想要捕獲全部的單詞順序信息,需要1+2+3....+n,所以這種方式會讓embedding_lookup變得非常大。
那么,RNN就是專門解決這種無法捕獲長距離的句子信息的模型。
RNN模型架構
RNN模型如下圖所示,在每一步,我們都輸入單詞\(w_{i}\)同時,經過公式\(h_{i+1} = sigmoid(W * h_{i} + U *x_{i} + b)\)這里,\(x_{i}\)表示在第\(i\)步輸入的單詞,\(h_{i}\)表示當前的隱藏層權值向量,\(h_{i+1}\)表示輸出。

多輸入單輸出
接下來介紹幾種RNN的使用形式,這些使用形式可以用在不同的場景中。
多輸入單輸出的形式基本上就是基本模型的一點點擴展,就是我們只用最后一個時間點的輸出,在最后一層輸出中加入一個softmax。

單輸入多輸出
單輸入多輸出是只在第一層輸入一次,后續不需要在輸入任何的東西,即除了第一層,后續幾層的\(U * x_{i}\) 為0.

多輸入多輸出
多輸入多輸出也可以叫做encoder-decoder模型,常用於翻譯。

梯度消失和梯度爆炸
RNN受限於梯度消失和梯度爆炸,為什么會出現這種現象呢?我們借鑒邱錫鵬老師的深度學習和神經網絡,來簡單的進行一下相關公式的推導,當得到推導結果的時候,我們就能很好的理解為啥會有這種現象了。首先,我們來定義一下RNN的公式
上面的公式是RNN的標准公式,其中\(U,W,b\)為需要求的參數,\(h_{t-1}\)為\(t-1\)時刻的輸出值,我們假定序列的長度為\(T\),即\(t=1,2,3,4.....T\),在\(T\)時刻輸出的時候,我們定義一個損失函數
這里\(y\)表示標簽,\(h_{T}\)表示最終的輸出。好了,有了損失函數,我們就可以對上述的參數進行求導,我們這里以\(U\)為例,根據損失函數,我們得到
我們這里無需關注\(\frac {\partial L} {\partial h_{T}}\),因為這里基本上不影響"梯度爆炸"和"梯度消失"現象的解釋。接下來,我們主要對\(\frac {\partial h_{T}} {\partial U}\)進行求導
這里\(\frac {\partial ^{+} z_{k}} {\partial U}\)這里表示\(z_{k}\)對\(U\)直接進行求導,即會把這個時刻的\(h_{k-1}\)當成一個常量處理。我們將兩個式子分開求導,可以得到
第二個式子,由於這里是直接求導,可以得到
所以,最終的求導結果為
最終\(U\)的優化結果為
那為啥會出現梯度消失和梯度爆炸呢?我們來觀察一下這個求導的式子\(\sum\limits_{k=1}^{T} \delta_{k} * h_{k-1}\)。展開之后會發現為
其中,上式中最小的值為1,也就是會從1一直累乘到T,在RNN中,\(f(z_{k})\)一般用sigmoid,這使得\(f^{'}(z_{i})\)的值基本上在0.25以下,當參數\(U\)初始值較大時,那么\(U^{T}\)是一個非常大的值,在一次更新后,新的\(U\)會變得非常大,會導致梯度爆炸。假如,在初始值\(U\)較小時,經過若干次和sigmoid函數累乘后,數值會變得非常小,那么\(U\)的更新對於最開始的時刻,比如1,2...等時刻變化就非常小,那么開始時刻的信息對梯度的變化貢獻就小,而離序列最近的T比如T,T-1.....這些貢獻就比較大,這種現象叫做梯度消失。
LSTM
為什么會出現LSTM呢?
由於RNN有"梯度消失"和"梯度爆炸"的現象,那么LSTM就是解決這兩個問題才出現的,那么LSTM是如何解決這兩個問題的呢?我們接下來進行討論
LSTM模型結構
LSTM模型的整體邏輯和RNN類似,都會經過一個閉合的隱藏中間單元,不同之處在於RNN只有隱藏權值\(h\),而LSTM卻加入了三個門控單元來解決RNN的"梯度消失"和"梯度爆炸"現象。

- 遺忘門
我們這里先搞一個遺忘門,遺忘門是表示我們希望什么樣的信息進行保留,什么樣的信息可以通過,所以這里的激活函數是sigmoid。

- 輸入門
首先,我們用sigmoid建立一個輸入門層,決定什么值我們將要更新,接着用tanh建立一個候選值向量,並將其加入到狀態中。

接着,我們就將這些層進行匯總,並更新\(C_{t}\)。如下圖所示

- 輸出門
最后我們來到輸出門層,更新\(h_{t}\)

2020年6月4日新增理解
這兩天看了一些博客和邱錫鵬老師的講解,對梯度消失和梯度爆炸的理解又更近了一步,接下來說說我對這幾個門的理解。梯度消失和梯度爆炸的理解已經加到文章中了。首先,對於梯度消失來說,我們一個直接的想法就是如果有一個記憶單元可以記憶從時刻t=1到t=T的信息就好了,所以就有了\(C(t)\)來保存之前的全部信息,由於乘法操作是控制信息量的流入和流出,而加法操作是將之前的舊信息和當前的新信息進行累加,所以\(C(t)\)的更新的一個想法就是用加法操作,即
但是我們想想,每個時間步的信息我們都需要保留嗎?比如當前時刻,我們只需要記住重要的信息就行了,所以就有了輸入門即\(i_{t}\),其控制當前的信息哪些需要流入,哪些流出,就好比人看一句話來說,他只會關注當前句子中重要的字,不重要的不關注。則公式更新為
但是這里又有一個問題是,\(C_{t}\)會不會由於信息存儲的過多,導致信息過多呢?對於人來說,之前的一些記憶我們也會忘記,所以,便有了遺忘門,遺忘門和輸入們類似,表示對信息流的控制。
那最后,我們對記憶單元進行激活,加上一個輸出門即可
那輸入門,遺忘門,輸出門以及\(\tilde C_{t}\)的公式為
[2]RNN 與 LSTM 的原理詳解:https://blog.csdn.net/HappyRocking/article/details/83657993