基本迴圈神經網路

雙向迴圈神經網路

深度迴圈神經網路

迴圈神經網路的時間步長和引數共享

迴圈神經網路的訓練演算法(BPTT)

RNN的梯度消失和梯度爆炸

RNN的Long-Term依賴問題

RNN的幾種架構

1. 基本迴圈神經網路

傳統的神經網路模型是從輸入層到隱含層再到輸出層的全連線,且同層的節點之間是無連線,網路的傳播也是順序的,但這種普通的網路結構對於許多問題卻顯得無能為力。例如,在自然語言處理中,如果要預測下一個單詞,就需要知道前面的部分單詞,因為一個句子中的單詞之間是相互聯絡的,即有語義。這就需要一種新的神經網路,即迴圈神經網路RNN,

迴圈神經網路對於序列化的資料有很強的模型擬合能力。

具體的結構為:迴圈神經網路在隱含層會對之前的資訊進行儲存記憶,然後輸入到當前計算的隱含層單元中,也就是隱含層的內部節點不再是相互獨立的,而是互相有訊息傳遞。隱含層的輸入不僅可以由兩部分組成,輸入層的輸出和隱含層上一時刻的輸出,即隱含層內的節點自連;隱含層的輸入還可以由三部分組成,輸入層的輸出、隱含層上一時刻的輸出、上一隱含層的狀態,即隱含層內的節點不僅自連還互連。結構如圖1所示。

迴圈神經網路(RNN)

圖1:迴圈神經網路結構圖

在圖1中,可以看到隱含層節點間有訊息的相互傳遞。為了更簡單的理解,現在我們將RNN在時間座標軸上展開成一個全神經網路,如圖2所示。例如,對一個包含3個單詞的語句,那麼展開的網路便是一個有3層的神經網路,每一層代表一個單詞。

迴圈神經網路(RNN)

圖2:迴圈神經網路展開圖

對於圖2的網路,計算過程如下:

x_t

表示第

t

步(step)的輸入。比如

x_1

為第二個詞的詞向量(

x_0

為第一個詞);

s_t

為隱藏層的第t步的狀態,它是網路的記憶單元。

s_t

根據當前輸入層的輸出與上一時刻隱藏層的狀態

s_{t-1}

進行計算,如公式1所示。其中,U是輸入層的連線矩陣,W是上一時刻隱含層到下一時刻隱含層的權重矩陣,f(x)一般是非線性的啟用函式,如tanh或ReLU。

s_t=f(Ux_{t}+Ws_{t-1})

(1)

o_t

是第t步的輸出。輸出層是全連線層,即它的每個節點和隱含層的每個節點都互相連線,V是輸出層的連線矩陣,g(x)是啟用函式。

o_t=g(V*s_t)

(2)

如果將(1)式迴圈帶入(2)式可得:

\begin{equation} \begin{split} o_{t}&=g(Vs_{t})\\ &=Vf(Ux_{t}+Ws_{t-1})\\ &=Vf(Ux_{t}+Wf(Ux_{t-1}+Ws_{t-2}))\\ &=Vf(Ux_{t}+Wf(Ux_{t-1}+Wf(Ux_{t-2}+Ws_{t-3})))\\ &=Vf(Ux_{t}+Wf(Ux_{t-1}+Wf(Ux_{t-2}+Wf(Ux_{t-3}+...)))) \end{split} \end{equation}

(3)

由式(3)可以看出,迴圈神經網路的輸出值與前面多個時刻的歷史輸入值有關,這就是為何迴圈神經網路能夠往前看任意多個輸入值的原因,也就是為何迴圈神經網路能夠對序列資料建模的原因。

在圖2中,我們展示了一個單向迴圈神經網路,但是單向迴圈神經網路也有不足之處。從單向的結構中可以知道它的下一時刻預測輸出是根據前面多個時刻的輸入共同影響的,而有些時候預測可能需要由前面若干輸入和後面若干輸出共同決定,這樣才會更加準確。

2. 雙向迴圈神經網路

2.1 雙向迴圈神經網路的介紹

對於語言模型來說,很多時候單向迴圈神經網路表現是不好的,比如下面這句話:

我的手機壞了,我打算____一部新手機。

可以想象,如果我們只看橫線前面的詞,手機壞了,那麼我是打算修一修?換一部新的?還是大哭一場?這些都是無法確定的。但如果我們也看到了橫線後面的詞是『一部新手機』,那麼,橫線上的詞填『買』的機率就大得多了。

對於上面的語言模型,單向迴圈神經網路是無法對此進行建模的。因此,我們需要用雙向迴圈神經網路,如圖3所示。

迴圈神經網路(RNN)

圖3:雙向迴圈神經網路

從圖3中可以看出,雙向迴圈神經網路的隱藏層要儲存兩個值,一個A參與正向計算,另一個值

A^{

參與反向計算。我們以

y_{2}

的計算為例,推出迴圈神經網路的一般規律。最終的輸出值

y_{2}

取決於

A_{2}

A_{2}^{

。其計算方式為公式4:

y_{2} = g(VA_{2}+V^{

(4)

A_{2}

A_{2}^{

則分別計算為:

A_{2} = f(WA_{1}+Ux_{2})

(5)

A_{2}^{

(6)

現在,我們已經可以看出一般的規律:正向計算時,隱藏層的值

s_{t}

s_{t-1}

有關;反向計算時,隱藏層的值

s^{

s^{

有關;最終的輸出取決於正向和反向計算的

加和

。現在,我們仿照

式5

式6

,寫出雙向迴圈神經網路的計算方法:

o_{t} = g(Vs_{t}+V^{

(7)

s_{t} = f(Ux_{t}+Ws_{t-1})

(8)

s^{

(9)

從上面三個公式我們可以看到,正向計算和反向計算

不共享權重

,也就是說U和U‘、W和W’、V和V‘都是不同的

權重矩陣

2.2 雙向迴圈神經網路的訓練

前向傳播:

沿著時刻0到時刻i正向計算一遍,得到並儲存每個時刻向前隱含層的輸出。

沿著時刻i到時刻0反向計算一遍,得到並儲存每個時刻向後隱含層的輸出。

正向和反向都計算完所有輸入時刻後,每個時刻根據向前向後隱含層得到最終輸出。

反向傳播:

計算所有時刻輸出層的損失函式項。

根據所有輸出層的損失函式項,使用 BPTT 演算法更新向前層。

根據所有輸出層的損失函式項,使用 BPTT 演算法更新向後層。

3. 深度迴圈神經網路

上面介紹的基本迴圈神經網路和雙向迴圈神經網路只有單個隱藏層,有時不能很好的學習資料內部關係,可以透過疊加多個隱藏層,形成深度迴圈神經網路結構。

迴圈神經網路(RNN)

圖4:深度迴圈神經網路

Deep (Bidirectional)RNN和Bidirectional RNN相似,只是在每個時刻會有多個隱藏層。在實際中會有更強的學習能力,但也需要更多的訓練資料。

4. 迴圈神經網路的時間步長和引數共享

4.1 迴圈神經網路的time steps

time steps 就是迴圈神經網路認為每個輸入資料與前多少個陸續輸入的資料有聯絡。

例如具有這樣一段序列資料 “…ABCDBCEDF…”,當 time steps 為 3 時,在模型預測中如果輸入資料為“D”,那麼之前接收的資料如果為“B”和“C”則此時的預測輸出為 B 的機率更大,之前接收的資料如果為“C”和“E”,則此時的預測輸出為 F 的機率更大。

4.2 迴圈神經網路的引數共享

迴圈神經網路引數共享指的是:在每一個時間步上,所對應的引數是共享的。引數共享的目的有兩個:一、用這些引數來捕獲序列上的特徵;二、共享引數減少模型的複雜度。

如圖2所示,在RNN中每輸入一步,每一層各自都共享引數U、V、W。其反映著RNN中每一時刻都在做相同的事情,只是輸入不同,因此大大減少了網路中需要學習的引數。

對於RNN的引數共享,我們可以理解為對於一個句子或者文字,引數U可以看成是語法結構、引數W是一般規律,而下一個單詞的預測必須是上一個單詞和一般規律W與語法結構U共同作用的結果。我們知道,語法結構和一般規律在語言當中是共享的。所以,引數自然就是共享的!

CNN和RNN引數共享的區別:

我們需要記住的是,深度學習是怎麼減少引數的,很大原因就是引數共享,而

CNN是在空間上共享引數,RNN是在時間序列上共享引數。

迴圈神經網路中關於引數共享比較好的文章推薦:

【1】YJango的迴圈神經網路——介紹 - YJango的文章 - 知乎

https://

zhuanlan。zhihu。com/p/24

720659

【2】全面理解RNN及其不同架構 - Evan的文章 - 知乎

https://

zhuanlan。zhihu。com/p/34

152808

5. 迴圈神經網路的訓練演算法(BPTT)

RNN的反向傳播演算法為Backpropagation Through Time (BPTT)。讓我們先回憶一下RNN的基本公式,注意到這裡在符號上稍稍做了改變(

o

變成

\hat{y}

),這只是為了和我參考的一些資料保持一致。

s_{t}=tanh(Ux_{t}+Ws_{t-1})

\hat{y}_{t}=softmax(Vs_{t})

同樣把損失值定義為交叉熵損失,如下:

E_{t}(y_{t}, \hat{y}_{t})=-y_{t}log(\hat{y}_{t})

E(y, \hat{y})=\sum_{t}{E_{t}(y_{t}, \hat{y}_{t})}= -\sum_{t}{y_{t}log\hat{y}_{t}}

這裡,

y_{t}

表示時刻

t

正確的詞,

\hat{y}_{t}

是我們的預測。通常我們會把整個句子作為一個訓練樣本,所以總體誤差是每一時刻的誤差的累加和。

迴圈神經網路(RNN)

圖5:迴圈神經網路的展開圖

我們的目標是計算誤差值相對於引數

U, V, W

的梯度以及用隨機梯度下降學習好的引數。就像我們要把所有誤差累加一樣,我們同樣會把每一時刻針對每個訓練樣本的梯度值相加:

\frac{\partial{E}}{\partial{W}}=\sum_{t}{\frac{\partial{E}_{t}}{\partial{W}}}

為了計算梯度,我們使用鏈式求導法則,主要是用反向傳播演算法往後傳播誤差。下面我們使用

E_{3}

作為例子,主要是為了描述方便。

\frac{\partial{E_{3}}}{\partial{V}} = \frac{\partial{E_{3}}}{\partial{\hat{y}_{3}}} \frac{\partial{\hat{y}_{3}}}{\partial{V}} =\frac{\partial{E_{3}}}{\partial{\hat{y}_{3}}}  \frac{{\partial{\hat{y}_{3}}}}{\partial{z_{3}}} \frac{\partial{z_{3}}}{\partial{V}} =(\hat{y}_{3}-y_{3})\otimes s_{3}

上面

z_{3}=Vs_{3}

\otimes

是向量的外積。如果你不理解上面的公式,不要擔心,我在這裡對上面的推導過程進行補充。這裡我想說明的一點是梯度值只依賴於當前時刻的結果

\hat{y}_{3}, y_{3}, s_{3}

。根據這些,計算

V

的梯度就只剩下簡單的矩陣乘積了。

補充上面式子推導過程:

\frac{\partial E_{3}}{\partial z_{3}} = -\sum_{i=0}^{C}{y_{3} \frac{\partial log(\hat y_{3})}{\partial z_{3}}}=-\sum_{i=0}^{C}{y_{3}\frac{1}{\hat y_{3}}\frac{\partial \hat y_{3}}{\partial z_{3}}}

(*)

上式中

\frac{\partial \hat y_{3}}{\partial z_{3}}

求導結果,其實是Softmax函式求導結果。我這裡直接給出Softmax求導結果:

i=j

時,

\frac{\partial \hat y_{i}}{\partial z_{j}} = \hat y_{i}(1-\hat y_{j})

i\ne j

時,

\frac{\partial \hat y_{i}}{\partial z_{j}} = - \hat y_{i} \hat y_{j}

所以,將Softmax求導結果代入(*)式:

\begin{split} -\sum_{i = 0}^{C}y_i \frac{1}{\hat y_i}\frac{\partial \hat y_i}{\partial z_j} &= -\frac{y_i}{\hat y_i}\frac{\partial \hat  y_i}{\partial z_i} - \sum_{i \ne j}^{C} \frac{y_i}{ \hat y_i}\frac{\partial \hat  y_i}{\partial z_j} \\ & = -\frac{y_j}{\hat y_i}\hat y_i(1 - \hat  y_j) - \sum_{i \ne j}^{C} \frac{y_i}{\hat y_i}(- \hat y_i \hat y_j) \\ & = -y_j + y_j \hat y_j + \sum_{i \ne j}^{C}y_i \hat y_j = -y_j + \sum_{i = 0}^{C}y_i \hat y_j \\ & = -y_j + \hat y_j\sum_{i = 0}^{C}y_i = \hat y_j - y_j \end{split}

但是對於梯度

\frac{\partial{E}_{3}}{\partial{W}}

情況就不同了,我們可以像上面一樣寫出鏈式法則。

\frac{\partial{E_{3}}}{\partial{W}}= \frac{\partial{E_{3}}}{\partial{\hat{y}_{3}}} \frac{\partial{\hat{y}_{3}}}{\partial{s_{3}}} \frac{\partial{s_{3}}}{\partial{W}}

注意到這裡的

s_{3}=tanh(Ux_{t}+Ws_{2})

依賴於

s_{2}

s_{2}

依賴於

W

s_{1}

,等等。所以為了得到

W

的梯度,我們不能將

s_{2}

看作常量。我們需要再次使用鏈式法則,得到的結果如下:

\frac{\partial{E_{3}}}{\partial{W}}= \sum_{k=0}^{3}{ \frac{\partial{E_{3}}}{\partial{\hat{y}_{3}}} \frac{\partial{\hat{y}_{3}}}{\partial{s_{3}}} \frac{\partial{s_{3}}}{\partial{s_{k}}} \frac{\partial{s_{k}}}{\partial{W}}}

我們把每一時刻得到的梯度值累加,換句話說,

W

在計算輸出的每一步中都使用了。我們需要透過將

t=3

時刻的梯度反向傳播至

t=0

時刻。

迴圈神經網路(RNN)

圖6:迴圈神經網路的BPTT訓練演算法

請注意,這與我們在深層前饋神經網路中使用的標準反向傳播演算法是完全相同的。關鍵的區別是,我們把每一時刻針對

W

的不同梯度做了累加。在傳統的神經網路中,我們不需要跨層共享權重,所以不需要求和。但在我看來,BPTT是應用於展開的RNN上的標準反向傳播的另一個名字。就像反向傳播一樣,你也可以定義一個反向傳遞的delta向量,例如,

\delta ^{(3)}_{2}=\frac{\partial{E}_{3}}{z_{2}}                           =\frac{\partial{E}_{3}}{\partial{s_{3}}} \frac{\partial{s}_{3}}{\partial{s_{2}}}  \frac{\partial{s}_{2}}{\partial{z_{2}}}

,其中

z_{2}=Ux_{2}+Ws_{1}

透過以上的推導,我們可以得出結論:

RNN很難訓練的原因是:序列(句子)可能很長,可能是20個單詞或更多,因此需要在許多層中進行反向傳播。在實踐中,許多人限定反向傳播為有限的步驟(也是因為有梯度消失的問題存在)。

本部分參考文章:

【1】迴圈神經網路教程第三部分-BPTT和梯度消失 - 徐志強的文章 - 知乎

https://

zhuanlan。zhihu。com/p/22

338087

6. RNN的梯度消失和梯度爆炸

上面我們講到的單向迴圈神經網路、雙向迴圈神經網路和深度迴圈神經網路都是傳統的迴圈神經網路。這些傳統的迴圈神經網路在學習過程中容易出現梯度消失和梯度爆炸的現象。所謂的梯度消失是指:資訊在反向傳播時誤差減小為0;而梯度爆炸是指:資訊在反向傳播時誤差呈指數增長。下面,我們來深入的瞭解一下迴圈神經網路中產生梯度消失和梯度爆炸的本質原因。

6.1 梯度消失

RNN很難學到長範圍的依賴-即相隔幾步的詞之間的聯絡。傳統的RNN不能捕獲長距離詞之間的關係。要理解為什麼,讓我們先仔細看一下下面計算的梯度:

\frac{\partial{E_{3}}}{\partial{W}}= \sum_{k=0}^{3}{ \frac{\partial{E_{3}}}{\partial{\hat{y}_{3}}} \frac{\partial{\hat{y}_{3}}}{\partial{s_{3}}} \frac{\partial{s_{3}}}{\partial{s_{k}}} \frac{\partial{s_{3}}}{\partial{W}}}

注意到

\frac{\partial{s_{3}}}{\partial{s_{k}}}

也需要使用鏈式法則。例如,

\frac{\partial{s_{3}}}{\partial{s_{1}}}=\frac{\partial{s_{3}}}{\partial{s_{2}}} \frac{\partial{s_{2}}}{\partial{s_{1}}}

。注意到因為我們是用向量函式對向量求導數,結果是一個矩陣(稱為Jacobian Matrix),矩陣元素是每個點的導數。我們可以把上面的梯度重寫成:

\frac{\partial{E_{3}}}{\partial{W}}= \sum_{k=0}^{3}{ \frac{\partial{E_{3}}}{\partial{\hat{y}_{3}}} \frac{\partial{\hat{y}_{3}}}{\partial{s_{3}}} (\prod_{j=k+1}^{3} \frac{\partial{s_{j}}}{\partial{s_{j-1}}}) \frac{\partial{s_{k}}}{\partial{W}}}

可以證明上面的Jacobian矩陣的二範數(可以認為是一個絕對值)的上界是1。這很直觀,因為啟用函式

tanh

把所有值對映到-1和1之間,導數值得界限也是1。

迴圈神經網路(RNN)

圖7:tanh函式及其導數

從圖7中我們可以看到,tanh函式在x趨近於無窮大和無窮小時梯度值都為0。當這種情況出現時,我們就認為相應的神經元飽和。它們的梯度為0使得前面層的梯度也為0,因為前面層的梯度是由後面層的梯度連乘得到的。梯度中存在比較小的值,多個梯度相乘會使梯度值以指數級速度下降,最終在反向傳播幾步後就完全消失。比較遠的時刻的梯度值為0,這些時刻的狀態對學習過程沒有幫助,導致你無法學習到長距離依賴。梯度訊息問題不僅出現在RNN中,同樣也出現在深度前向神經網中。只是RNN網路通常比較深,使得這個問題更加普遍。

6.2 梯度爆炸

RNN的學習依賴於我們的啟用函式和網路初始引數,如果Jacobian矩陣中的值太大,會產生梯度爆炸而不是梯度消失問題。梯度消失比梯度爆炸受到了更多的關注有兩方面的原因。其一,梯度爆炸容易發現,梯度值會變成NaN,導致程式崩潰。其二,用預定義的閾值裁剪梯度可以簡單有效的解決梯度爆炸問題。梯度消失問題就不容易發現並且也不好處理,這也是梯度消失比梯度爆炸受到學術界更多關注的原因。

7. RNN的Long-Term依賴問題

上面我們講到的迴圈神經網路梯度消失問題在RNN中會造成不能Long-Term依賴問題。

例如,考慮一個語言模型試圖基於先前的詞預測下一個詞。如果我們要預測“the clouds are in the sky”,我們不需要其它更遙遠的上下文資訊就能預測出下一個詞應該是sky。在這樣的例子中,句子長度很小,相關資訊和預測單詞的距離很小,RNN可以學著去使用過去的資訊。

但是,在大部分情況下我們需要更多的上下文資訊。考慮預測這個句子中最後一個詞:“I grew up in France… I speak fluent French。” 最近的資訊表明下一個詞可能是一種語言的名字,但如果我們想要找出是哪種語言,我們需要從更久遠的地方獲取France的上下文。相關資訊和預測單詞之間的距離完全可能是非常巨大的。而不幸的是,隨著距離的增大,RNN會產生梯度消失的問題,造成不能夠連線更長的上下文資訊。

8. RNN的幾種架構

由於RNN對於序列化的資料有很強的模型擬合能力,因此在不同的應用場景中可以對RNN組合形成不同的網路架構。

8.1 1 to 1

迴圈神經網路(RNN)

圖8:Vanilla Neural Networks

圖8是普通的單個神經網路,由於圖8模型過於簡單,在實際的場景中沒有什麼應用價值。但是對於我們學習RNN的模型來說,它是最基本的也是最好理解的。

8.2 1 to N

這種情況有兩種方式,一種是隻在序列開始進行輸入計算

迴圈神經網路(RNN)

圖9:1 to N(1)

還有一種結構是把輸入資訊X作為每個階段的輸入:

迴圈神經網路(RNN)

圖10:1 to N(2)

這種1 to N的結構可以處理的問題有很多,比如影象標註,輸入的X是影象的特徵,而輸出的y序列是一段句子。

8.3 N to 1

輸入是一個序列,輸出是一個單獨的值而不是序列。這種結構通常用來處理序列分類問題。如輸入一段文字判別它所屬的類別,輸入一個句子判斷其情感傾向,輸入一段文件並判斷它的類別等等。具體如圖11:

迴圈神經網路(RNN)

圖11:N to 1

8.4 N to N

迴圈神經網路(RNN)

圖12:N to N

輸入和輸出序列是等長的。這種可以作為簡單的Char RNN可以用來生成文章,詩歌,甚至是程式碼,非常有意思。

8.5 N to M

這種結構又叫Encoder-Decoder模型,也稱之為Seq2Seq模型。在現實問題中,我們遇到的大部分序列都是不等長的。如機器翻譯中,源語言和目標語言的句子往往並沒有相同的長度。而Encoder-Decoder結構先將輸入資料編碼成一個上下文向量c,之後在透過這個上下文向量輸出預測序列。

迴圈神經網路(RNN)

圖13:N to M

迴圈神經網路(RNN)

圖14:帶有Attention機制的N to M

注意,很多時候只用上下文向量C效果並不是很好,而attention機制很大程度彌補了這點。

seq2seq的應用的範圍非常廣泛,機器翻譯,文字摘要,閱讀理解,對話生成等等。

Reference

【1】 零基礎入門深度學習(5) - 迴圈神經網路

【2】 全面理解RNN及其不同架構

【3】完全圖解RNN、RNN變體、Seq2Seq、Attention機制

【4】迴圈神經網路教程第一部分-RNN簡介

【5】Understanding LSTM Networks

【6】]YJango的迴圈神經網路——介紹 - YJango的文章 - 知乎

https://

zhuanlan。zhihu。com/p/24

720659

【7】迴圈神經網路教程第三部分-BPTT和梯度消失 - 徐志強的文章 - 知乎

https://

zhuanlan。zhihu。com/p/22

338087

【8】迴圈神經網路(RNN)介紹3:RNN的反向傳播演算法Backpropagation Through Time (BPTT) - 劉博的文章 - 知乎

https://

zhuanlan。zhihu。com/p/32

930648

【9】神經網路梯度消失和梯度爆炸及解決辦法

我的個人

微信公眾號

Microstrong

微信公眾號ID:MicrostrongAI

公眾號介紹:

Microstrong(小強)同學主要研究機器學習、深度學習、計算機視覺、智慧對話系統相關內容,分享在學習過程中的讀書筆記!期待您的關注,歡迎一起學習交流進步!

個人部落格: