NLP教程(5) - 語言模型、RNN、GRU與LSTM

ShowMeAI發表於2022-05-07


語言模型、RNN、GRU與LSTM
本系列為史丹佛CS224n《自然語言處理與深度學習(Natural Language Processing with Deep Learning)》的全套學習筆記,對應的課程視訊可以在 這裡 檢視。

迴圈神經網路與語言模型
梯度消失問題與RNN變種
ShowMeAI為CS224n課程的全部課件,做了中文翻譯和註釋,並製作成了 GIF動圖!點選 第6講-迴圈神經網路與語言模型第7講-梯度消失問題與RNN變種 檢視的課件註釋與帶學解讀。更多資料獲取方式見文末。


引言

CS224n是頂級院校史丹佛出品的深度學習與自然語言處理方向專業課程,核心內容覆蓋RNN、LSTM、CNN、transformer、bert、問答、摘要、文字生成、語言模型、閱讀理解等前沿內容。

本篇筆記對應史丹佛CS224n自然語言處理專項課程的知識板塊:**語言模型、迴圈神經網路RNN、變種RNN (LSTM、GRU等) **。首先介紹了語言模型及其應用場景,進而介紹迴圈神經網路RNN及優化後的變種LSTM和GRU模型。

筆記核心詞

  • 語言模型
  • RNN
  • 迴圈神經網路
  • 雙向RNN
  • 深度RNN
  • 長短時記憶網路
  • LSTM
  • GRU

1.語言模型

(語言模型部分內容也可以參考ShowMeAI的對吳恩達老師課程的總結文章 深度學習教程 | 序列模型與RNN網路

1.1 簡介

語言模型計算特定序列中多個單詞以一定順序出現的概率。一個 \(m\) 個單詞的序列 \(\{w_{1}, \dots, w_{m}\}\) 的概率定義為 \(P\left(w_{1}, \dots, w_{m}\right)\)。單詞 \(w_i\) 前有一定數量的單詞,其特性會根據它在文件中的位置而改變,\(P\left(w_{1}, \dots, w_{m}\right)\) 一般只考慮前 \(n\) 個單詞而不是考慮全部之前的單詞。

\[P(w_{1}, \ldots, w_{m})=\prod_{i=1}^{i=m} P(w_{i} \mid w_{1}, \ldots, w_{i-1}) \approx \prod_{i=1}^{i=m} P(w_{m} \mid w_{i-n}, \ldots, w_{i-1}) \]

上面的公式在語音識別和機器翻譯系統中有重要的作用,它可以輔助篩選語音識別和機器翻譯的最佳結果序列。

在現有的機器翻譯系統中,對每個短語/句子翻譯,系統生成一些候選的詞序列 (例如,\(\{ I have,I has,I had,me have,me had \}\)) ,並對其評分以確定最可能的翻譯序列。

在機器翻譯中,對一個輸入短語,通過評判每個候選輸出詞序列的得分的高低,來選出最好的詞順序。為此,模型可以在不同的單詞排序或單詞選擇之間進行選擇。它將通過一個概率函式執行所有單詞序列候選項,併為每個候選項分配一個分數,從而實現這一目標。最高得分的序列就是翻譯結果。例如:

  • 相比 small is the cat,翻譯系統會給 the cat is small 更高的得分;
  • 相比 walking house after school,翻譯系統會給 walking home after school 更高的得分。

1.2 n-gram語言模型

為了計算這些概率,每個 n-gram 的計數將與每個單詞的頻率進行比較,這個稱為 n-gram 語言模型。

  • 例如,如果選擇 bi-gram模型 (二元語言模型) ,每一個 bi-gram 的頻率,通過將單詞與其前一個單詞相結合進行計算,然後除以對應的 uni-gram 的頻率。
  • 下面的兩個公式展示了 bi-gram 模型和 tri-gram 模型的區別。

\[p(w_{2} \mid w_{1}) =\frac{count (w_{1}, w_{2})}{count(w_{1})} \]

\[p(w_{3} \mid w_{1}, w_{2}) =\frac{count (w_{1}, w_{2}, w_{3})}{count (w_{1}, w_{2})} \]

上式 tri-gram 模型的關係主要是基於一個固定的上下文視窗 (即前\(n\)個單詞) 預測下一個單詞。一般\(n\)的取值為多大才好呢?

  • 在某些情況下,前面的連續的 \(n\) 個單詞的視窗可能不足以捕獲足夠的上下文資訊。
    • 例如,考慮句子 (類似完形填空,預測下一個最可能的單詞)
    • Asthe proctor started the clock, the students opened their __。如果視窗只是基於前面的三個單詞 the students opened their ,那麼基於這些語料計算的下劃線中最有可能出現的單詞就是為 books ——但是如果 \(n\) 足夠大,能包括全部的上下文,那麼下劃線中最有可能出現的單詞會是 exam

這就引出了 n-gram 語言模型的兩個主要問題:「稀疏性」和「儲存」。

1) n-gram語言模型的稀疏性問題

n-gram 語言模型的問題源於兩個問題。

① 對應公式中的分子,可能有稀疏性問題。

  • 如果\(w_1\)\(w_2\)\(w_3\) 在語料中從未出現過,那麼 \(w_3\) 的概率就是 \(0\)
  • 為了解決這個問題,在每個單詞計數後面加上一個很小的 \(\delta\),這就是平滑操作。

② 對應公式中的分母,可能有稀疏性問題。

  • 如果 \(w_1\)\(w_2\) 在語料中從未出現過,那麼 \(w_3\) 的概率將會無法計算。
  • 為了解決這個問題,這裡可以只是單獨考慮 \(w_2\),這就是backoff 操作。

增加 \(n\) 會讓稀疏問題更加嚴重,所以一般 \(n \leq 5\)

2) n-gram語言模型的儲存問題

我們知道需要儲存在語料庫中看到的所有 n-gram 的統計數。隨著\(n\)的增加(或語料庫大小的增加),模型的大小也會增加。

1.3 基於文字滑窗的預估型語言模型 (NNLM)

Bengio 的論文《A Neural Probabilistic Language Model》中首次解決了上面所說的“維度災難”,這篇論文提出一個自然語言處理的大規模的深度學習模型,這個模型能夠通過學習單詞的分散式表示,以及用這些表示來表示單詞的概率函式。

下圖展示了NNLM對應的神經網路結構,在這個模型中,輸入向量在隱藏層和輸出層中都被使用。

NNLM模型

下面公式展示了由標準 tanh 函式 (即隱藏層) 組成的 softmax 函式的引數以及線性函式\(W^{(3)} x+b^{(3)}\),捕獲所有前面 \(n\) 個輸入詞向量。

\[\hat{y}=\operatorname{softmax}\left(W^{(2)} \tanh \left(W^{(1)}x+b^{(1)}\right)+W^{(3)} x+b^{(3)}\right) \]

注意權重矩陣\(W^{(1)}\)是應用在詞向量上 (上圖中的綠色實線箭頭) ,\(W^{(2)}\)是應用在隱藏層 (也是綠色實線箭頭) 和\(W^{(3)}\)是應用在詞向量 (綠色虛線箭頭) 。

這個模型的簡化版本如下圖所示:

NNLM模型簡化版本

  • 藍色的層表示輸入單詞的 embedding 拼接:\(e=\left[e^{(1)} ; e^{(2)} ; e^{(3)} ; e^{(4)}\right]\)
  • 紅色的層表示隱藏層:\(\boldsymbol{h}=f\left(\boldsymbol{W} e+\boldsymbol{b}_{1}\right)\)
  • 綠色的輸出分佈是對詞表的一個 softmax 概率分佈:\(\hat{y}=\operatorname{softmax}\left(\boldsymbol{U} \boldsymbol{h}+\boldsymbol{b}_{2}\right)\)

2.迴圈神經網路 (RNN)

(迴圈神經網路部分內容也可以參考ShowMeAI的對吳恩達老師課程的總結文章深度學習教程 | 序列模型與RNN網路

傳統的統計翻譯模型,只能以有限視窗大小的前 \(n\) 個單詞作為條件進行語言模型建模,迴圈神經網路與其不同,RNN 有能力以語料庫中所有前面的單詞為條件進行語言模型建模。

下圖展示的 RNN 的架構,其中矩形框是在一個時間步的一個隱藏層 \(t\)

迴圈神經網路 (RNN)

每個這樣的隱藏層都有若干個神經元,每個神經元對輸入向量用一個線性矩陣運算然後通過非線性變化 (例如 tanh 函式) 得到輸出。

  • 在每一個時間步,隱藏層都有兩個輸入

    • 前一個時間步的隱藏層 \(h_{t-1}\)
    • 當前時間步的輸入 \(x_t\)
  • 前一個時間步的隱藏層 \(h_{t-1}\) 通過和權重矩陣 \(W^{(hh)}\) 相乘和當前時間步的輸入 \(x_t\) 和權重矩陣 \(W^{(hx)}\) 相乘得到當前時間步的隱藏層 \(h_t\)

  • \(h_t\) 和權重矩陣 \(W^{(S)}\) 相乘,接著對整個詞表通過 softmax 計算得到下一個單詞的預測結果 \(\hat y\),如下面公式所示:

\[h_{t} =\sigma\left(W^{(h h)} h_{t-1}+W^{(h x)} x_{[t]}\right) \]

\[\hat{y} =\operatorname{softmax}\left(W^{(S)} h_{t}\right) \]

每個神經元的輸入和輸出如下圖所示:

RNN神經元的輸入和輸出

在這裡一個有意思的地方是在每一個時間步使用相同的權重\(W^{(hh)}\)\(W^{(hx)}\)。這樣模型需要學習的引數就變少了,這與輸入序列的長度無關——這從而解決了維度災難。

以下是網路中每個引數相關的詳細資訊:

  • \(x_{1}, \dots, x_{t-1}, x_{t}, x_{t+1}, \dots x_{T}\):含有 \(T\) 個單詞的語料庫對應的詞向量

  • \(h_{t}=\sigma\left(W^{(h h)} h_{t-1}+W^{(h x)} x_{t}\right)\):每個時間步 \(t\) 的隱藏層的輸出特徵的計算關係

  • \(x_{t} \in \mathbb{R}^{d}\):在時間步 \(t\) 的輸入詞向量

  • \(W^{h x} \in \mathbb{R}^{D_{h} \times d}\):輸入詞向量 \(x_t\) 對應的權重矩陣

  • \(W^{h h} \in \mathbb{R}^{D_{h} \times D_{h}}\):上一個時間步的輸出 \(h_{t-1}\) 對應的權重矩陣

  • \(h_{t-1} \in \mathbb{R}^{D_{h}}\):上一個時間步 \(t-1\) 的非線性函式輸出。\(h_{0} \in \mathbb{R}^{D_{h}}\) 是在時間步 \(t=0\) 的隱藏層的一個初始化向量

  • \(\sigma\):非線性函式 (這裡是 sigmoid 函式)

  • \(\hat{y}=\operatorname{softmax}\left(W^{(S)} h_{t}\right)\):在每個時間步 \(t\) 全部單詞的概率分佈輸出。本質上 \(\hat y\) 是給定文件上下文分數 (例如 \(h_{t-1}\)) 和最後觀測的詞向量 \(x_t\),對一個出現單詞的預測。這裡 \(W^{(S)} \in \mathbb{R}^{|V| \times D_{h}}\)\(\hat{y} \in \mathbb{R}^{\left | V \right |}\),其中 \(\left | V \right |\) 是詞彙表的大小。

一個 RNN 語言模型的例子如下圖所示。

RNN語言模型

圖中的符號有一些的不同:

  • \(W_h\) 等同於 \(W^{(hh)}\)
  • \(W_e\) 等同於 \(W^{(hx)}\)
  • \(U\) 等同於 \(W^{(S)}\)
  • \(E\) 表示單詞輸入 \(x^{(t)}\) 轉化為 \(e^{(t)}\)

在 RNN 中常用的損失函式是在之前介紹過的交叉熵誤差。下面的公式是這個函式在時間步 \(t\) 全部單詞的求和。最後計算詞表中的 softmax 計算結果展示了基於前面所有的單詞對輸出單詞 \(x^{(5)}\) 的不同選擇的概率分佈。這時的輸入可以比4到5個單詞更長。

2.1 RNN損失與困惑度

RNN 的損失函式一般是交叉熵誤差。

\[J^{(t)}(\theta)=\sum_{j=1}^{\left | V \right |} y_{t, j} \times \log \left(\hat{y}_{t, j}\right) \]

在大小為\(T\)的語料庫上的交叉熵誤差的計算如下:

\[J=-\frac{1}{T} \sum_{t=1}^{T} J^{(t)}(\theta)=-\frac{1}{T} \sum_{t=1}^{T} \sum_{j=1}^{\left | V \right |} y_{t, j} \times \log \left(\hat{y}_{t, j}\right) \]

2.2 RNN的優缺點及應用

RNN 有以下優點

  • 它可以處理任意長度的序列
  • 對更長的輸入序列不會增加模型的引數大小
  • 對時間步 \(t\) 的計算理論上可以利用前面很多時間步的資訊
  • 對輸入的每個時間步都應用相同的權重,因此在處理輸入時具有對稱性

但是 RNN 也有以下不足

  • 計算速度很慢——因為它每一個時間步需要依賴上一個時間步,所以不能並行化
  • 在實際中因為梯度消失和梯度爆炸,很難利用到前面時間步的資訊

執行一層 RNN 所需的記憶體量與語料庫中的單詞數成正比。

例如,我們把一個句子是為一個 mini batch,那麼一個有 \(k\) 個單詞的句子在記憶體中就會佔用 \(k\) 個詞向量的儲存空間。同時,RNN必須維持兩對 \(W\)\(b\) 矩陣。然而 \(W\) 的可能是非常大的,它的大小不會隨著語料庫的大小而變化 (與傳統的語言模型不一樣) 。對於具有\(1000\)個迴圈層的RNN,矩陣\(W\)的大小為\(1000 \times 1000\)而與語料庫大小無關。


RNN可以應用在很多工,例如:

  • 標註任務 (詞性標註、命名實體識別)
  • 句子分類 (情感分類)
  • 編碼模組 (問答任務,機器翻譯和其他很多工)

在後面的兩個任務,我們希望得到對句子的表示,這時可以通過採用該句子中時間步長的所有隱藏狀態的\(element-wise\)的最大值或平均值來獲得。

下圖是一些資料中對 RNN 模型的另外一種表示。它將 RNN 的每個隱層用一個環來表示。

RNN隨時間步長迴圈的圖示

2.3 梯度消失與梯度爆炸問題

(梯度消失和梯度爆炸部分內容也可以參考ShowMeAI的對吳恩達老師課程的總結文章深度學習教程 | 深度學習的實用層面

RNN 從一個時間步傳播權值矩陣到下一個時間步。回想一下,RNN 實現的目標是通過長距離的時間步來傳播上下文資訊。例如,考慮以下兩個句子:

場景1

Jane walked into the room. John walked in too. Jane said hi to __

場景2

Jane walked into the room. John walked in too. It was late in the day, and everyone was walking home after a long day at work. Jane said hi to __

對上面的兩個句子,根據上下文,都可以知道空白處的答案是John,第二個在兩個句子的上下文中均提及了好幾次的人。

迄今為止我們對 RNN 的瞭解,在理想情況下,RNN 也是能夠計算得到正確的答案。然而,在實際中,RNN 預測句子中的空白處答案正確可能性,第一句要比第二句高。這是因為在反向傳播的階段的過程中,從前面時間步中回傳過來的梯度值會逐漸消失。因此,對於長句子,預測到 John 是空白處的答案的概率會隨著上下文資訊增大而減少。

下面,我們討論梯度消失問題背後的數學原因。

考慮公式在時間步 \(t\),計算RNN誤差 \(\frac{dE}{dW}\),然後我們把每個時間步的誤差都加起來。也就是說,計算並累積每個時間步長 \(t\)\(\frac{dE_t}{dW}\)

\[\frac{\partial E}{\partial W}=\sum_{i=1}^{T} \frac{\partial E_{t}}{\partial W} \]

通過將微分鏈式法則應用於以下公式來計算每個時間步長的誤差

\[\begin{aligned} h_{t} &=\sigma\left(W^{(h h)} h_{t-1}+W^{(h x)} x_{[t]}\right) \\ \hat{y} &=\operatorname{softmax}\left(W^{(S)} h_{t}\right) \end{aligned} \]

下列公式展示對應的微分計算。注意 \(\frac{d h_{t}}{d h_{k}}\)\(h_t\) 對之前所有的 \(k\) 個時間步的偏導數。

\[\frac{\partial E_{t}}{\partial W}=\sum_{k=1}^{T} \frac{\partial E_{t}}{\partial y_{t}} \frac{\partial y_{t}}{\partial h_{t}} \frac{\partial h_{t}}{\partial h_{k}} \frac{\partial h_{k}}{\partial W} \]

下式展示了計算每個 \(\frac{d h_{t}}{d h_{k}}\) 的關係;這是在時間間隔 \([k,t]\) 內對所有的隱藏層的應用一個簡單的微分鏈式法則。

\[\frac{\partial h_{t}}{\partial h_{k}}=\prod_{j=k+1}^{t} \frac{\partial h_{j}}{\partial h_{j-1}}=\prod_{j=k+1}^{t} W^{T} \times \operatorname{diag}\left[f^{\prime}\left(j_{j-1}\right)\right] \]

因為 \(h \in \mathbb{R}^{D_{n}}\),每個 \(\frac{\partial h_{j}}{\partial h_{j-1}}\)\(h\) 的Jacobian矩陣的元素:

\[\begin{aligned} \frac{\partial h_{j}}{\partial h_{j-1}}&=\left[\frac{\partial h_{j}}{\partial h_{j-1,1}} \cdots \frac{\partial h_{j}}{\partial h_{j-1, D_{n}}}\right] \\ &=\begin{bmatrix} {\frac{\partial h_{j, 1}}{\partial h_{j-1,1}}} & \cdots & {\frac{\partial h_{j,1}}{\partial h_{j-1, D_{n}}}} \\ \vdots & \ddots & \vdots \\ {\frac{\partial h_{j, D_{n}}}{\partial h_{j - 1,1}}} & \cdots & {\frac{\partial h_{j, D_{n}}}{\partial h_{j-1, D_{n}}}} \end{bmatrix} \end{aligned} \]

將公式合起來,我們有以下關係。

\[\frac{\partial E}{\partial W}=\sum_{t=1}^{T} \sum_{k=1}^{t} \frac{\partial E_{t}}{\partial y_{t}} \frac{\partial y_{t}}{\partial h_{t}}\left(\prod_{j=k+1}^{t} \frac{\partial h_{j}}{\partial h_{j-1}}\right) \frac{\partial h_{k}}{\partial W} \]

下式展示了Jacobian矩陣的範數。這裡的 \(\beta_{W}\)\(\beta_{h}\) 是這兩個矩陣範數的上界值。因此通過公式所示的關係計算在每個時間步 \(t\) 的部分梯度範數。

\[\left\|\frac{\partial h_{j}}{\partial h_{j-1}}\right\| \leq \left\| W^{T} \right\| \quad \left\| \operatorname{diag} \left [f^{\prime}\left(h_{j-1}\right)\right]\right\| \leq \beta_{W} \beta_{h} \]

計算這兩個矩陣的L2範數。在給定的非線性函式sigmoid下,\(f^{\prime}\left(h_{j-1}\right)\) 的範數只能等於1。

\[\left\|\frac{\partial h_{t}}{\partial h_{k}}\right\|=\left\|\prod_{j=k+1}^{t} \frac{\partial h_{j}}{\partial h_{j-1}}\right\| \leq (\beta_{W} \beta_{h})^{t-k} \]

\(t - k\) 足夠大和 \(\beta_{W} \beta_{h}\) 遠遠小於1或者遠遠大於1,指數項 \(\left(\beta_{W} \beta_{h}\right)^{t-k}\) 的值就很容易變得非常小或者非常大。

由於單詞之間的距離過大,用一個很大的 \(t-k\) 評估交叉熵誤差可能會出現問題。在反向傳播的早期就出現梯度消失,那麼遠處單詞對在時間步長\(t\)預測下一個單詞中,所起到的作用就會變得很小。

在實驗的過程中:

  • 一旦梯度的值變得非常大,會導致在執行過程中容易檢測到其引起的溢位 (即NaN) ;這樣的問題稱為「梯度爆炸」問題。
  • 當梯度接近為0的時候,梯度近乎不再存在,同時降低模型對語料庫中的遠距離的單詞的學習質量;這樣的問題稱為「梯度消失」問題。
    • 如果相對梯度消失問題的有更直觀的瞭解,你可以訪問這個 樣例網站

2.4 梯度消失與爆炸解決方法

現在我們知道了梯度消失問題的本質以及它在深度神經網路中如何表現出來,讓我們使用一些簡單實用的啟發式方法來解決這些問題。

2.4.1 梯度爆炸解決方法

為了解決梯度爆炸的問題,Thomas Mikolov 等人首先提出了一個簡單的啟發式解決方案,每當梯度大於一個閾值的時候,將其截斷為一個很小的值,具體如下面演算法中的虛擬碼所示。

\[\begin{array}{l} \hat{g} \leftarrow \frac{\partial E}{\partial W} \\ \text { if }\|\hat{g}\| \geq \text { threshold then } \\ \qquad \hat{g} \leftarrow \frac{\text { threshold }}{\|\hat{g}\|} \hat{g} \\ \text { end if } \end{array} \]

❐ Algorithm : Pseudo-code for norm clipping in the gradients whenever they explode【範數梯度裁剪的虛擬碼】

下圖視覺化了梯度截斷的效果。它展示了一個權值矩陣為 \(W\) 和偏置項為 \(b\) 的很小的RNN神經網路的決策介面。該模型由一個單一單元的迴圈神經網路組成,在少量的時間步長上執行;實心箭頭闡述了在每個梯度下降步驟的訓練過程。

漸變爆炸剪裁視覺化

當在梯度下降的過程中,模型碰到目標函式中的高誤差壁時,梯度被推到決策面上的一個遙遠的位置。截斷模型生成了虛線,在那裡它將誤差梯度拉回到靠近原始梯度的地方。

2.4.2 梯度消失解決方法

為了解決梯度消失問題,研究人員提出兩個技術:

  • 第一個技術是不去隨機初始化 \(W^{(hh)}\),而是初始化為單位矩陣。
  • 第二個技術是使用Rectified Linear (ReLU) 單元代替 sigmoid 函式。ReLU 的導數是 \(0\) 或者 \(1\)。這樣梯度傳回神經元的導數是\(1\),而不會在反向傳播了一定的時間步後梯度變小。

2.5 深度雙向迴圈神經網路

前面部分我們講解了用 RNN 如何使用過去的詞來預測序列中的下一個單詞。同理,可以通過令 RNN 模型向反向讀取語料庫,根據未來單詞進行預測。

Irsoy 等人展示了一個雙向深度神經網路;在每個時間步 \(t\),這個網路維持兩個隱藏層,一個是從左到右傳播,而另外一個是從右到左傳播。

為了在任何時候維持兩個隱藏層,該網路要消耗的兩倍儲存空間來儲存權值和偏置引數。最後的分類結果\(\hat y\),是結合由兩個 RNN 隱藏層生成的結果得分產生。

下圖展示了雙向 RNN 的網路結構

雙向RNN模型

而下式展示了給出了建立雙向RNN隱層的數學公式。兩個公式之間唯一的區別是遞迴讀取語料庫的方向不同。最後一行展示了通過總結過去和將來的單詞表示,顯示用於預測下一個單詞的分類關係:

\[\overrightarrow{h}_{t}=f(\overrightarrow{W} x_{t}+\overrightarrow{V} \overrightarrow{h}_{t-1}+\overrightarrow{b}) \]

\[\overleftarrow{h}_{t}=f(\overleftarrow{W} x_{t}+\overleftarrow{V} \overleftarrow{h}_{t-1}+\overleftarrow{b}) \]

\[\hat{y}_{t}=g (U h_{t}+c)=g(U \left[\overrightarrow{h}_{t} ; \overleftarrow{h}_{t}\right]+c) \]

RNN也可以是多層的。下圖展示一個多層的雙向 RNN,其中下面的隱藏層傳播到下一層。

如圖所示,在該網路架構中,在時間步 \(t\),每個中間神經元從前一個時間步 (在相同的 RNN 層) 接收一組引數和前一個 RNN 隱藏層的兩組引數;這兩組引數一組是從左到右的 RNN 輸入,另外一組是從右到左的 RNN 輸入。

具有三個RNN層的深雙向RNN

為了構建一個 L 層的深度 RNN,上述的關係要修改為在公式中的關係,其中在第 \(i\) 層的每個中間神經元的輸入是在相同時間步 \(t\) 的RNN第 \(i-1\) 層的輸出。最後的輸出 \(\hat y\),每個時間步都是輸入引數通過所有隱層傳播的結果。

\[\overrightarrow{h}_{t}^{(i)}=f\left(\overrightarrow{W}^{(i)} h_{t}^{(i-1)}+\overrightarrow{V}^{(i)} \overrightarrow{h}_{t-1}^{(i)}+\overrightarrow{b}^{(i)}\right) \]

\[\overleftarrow{h}_{t}^{(i)}=f\left(\overleftarrow{W}^{(i)} h_{t}^{(i-1)}+\overleftarrow{V}^{(i)} \overleftarrow{h}_{t+1}^{(i)}+\overrightarrow{b}^{(i)}\right) \]

\[\hat{y}_{t}=g\left(U h_{t}+c\right)=g\left(U\left[\overrightarrow{h}_{t}^{(L)} ; \overleftarrow{h}_{t}^{(L)}\right]+c\right) \]

2.6 應用:基於RNN的翻譯系統

(神經機器翻譯部分內容也可以參考ShowMeAI的對吳恩達老師課程的總結文章深度學習教程 | Seq2Seq序列模型和注意力機制

傳統的翻譯模型是非常複雜的:它們包含很多應用在語言翻譯流程的不同階段的機器學習演算法。這裡講解採用 RNN 作為傳統翻譯模型的替代方法。

考慮下圖中展示的 RNN 模型:其中德語短語 Echt dicke Kiste 翻譯為 Awesome sauce。

基於RNN的翻譯模型

首先,前三個時間步的隱藏層編碼德語單詞為一些語言的單詞特徵 (\(h_3\)) 。後面兩個時間步解碼 \(h_3\) 為英語單詞輸出。下式分別展示了編碼階段和解碼階段(後兩行)。

\[{h_{t}=\phi\left(h_{t-1}, x_{t}\right)=f\left(W^{(h h)} h_{t-1}+W^{(h x)} x_{t}\right)} \]

\[{h_{t}=\phi\left(h_{t-1}\right)=f\left(W^{(h h)} h_{t-1}\right)} \]

\[{y_{t}=\operatorname{softmax}\left(W^{(s)} h_{t}\right)} \]

一般可以認為使用交叉熵函式的RNN模型可以生成高精度的翻譯結果。在實際中,在模型中增加一些擴充套件方法可以提升翻譯的準確度表現。

\[\max _{\theta} \frac{1}{N} \sum_{n=1}^{N} \log p_{\theta}\left(y^{(n)} \mid x^{(n)}\right) \]

擴充套件 1:在訓練 RNN 的編碼和解碼階段時,使用不同的權值。這使兩個單元解耦,讓兩個 RNN 模組中的每一個進行更精確的預測。這意味著在公式中 \(\phi( )\) 函式裡使用的是不同的 \(W^{(hh)}\) 矩陣。

擴充套件 2:使用三個不同的輸入計算解碼器中的每個隱藏狀態

使用三個不同的輸入計算解碼器中的每個隱藏狀態

  • 前一個隱藏狀態 \(h_{t-1}\) (標準的)
  • 編碼階段的最後一個隱藏層 (上圖中的\(c=h_T\))
  • 前一個預測的輸出單詞 \(\hat y_{t-1}\)

將上述的三個輸入結合將之前公式的解碼函式中的 \(\phi\) 函式轉換為下式的 \(\phi\) 函式。上圖展示了這個模型。

\[h_{t}=\phi\left(h_{t-1}, c, y_{t-1}\right) \]

擴充套件 3:使用多個 RNN 層來訓練深度迴圈神經網路。神經網路的層越深,模型的就具有更強的學習能力從而能提升預測的準確度。當然,這也意味著需要使用大規模的語料庫來訓練這個模型。

擴充套件 4:訓練雙向編碼器,提高準確度。

擴充套件 5:給定一個德語詞序列\(A B C\),它的英語翻譯是\(X Y\)。在訓練\(RNN\)時不使用\(A B C \to X Y\),而是使用\(C B A \to X Y\)。這麼處理的原因是\(A\)更有可能被翻譯成\(X\)。因此對前面討論的梯度消失問題,反轉輸入句子的順序有助於降低輸出短語的錯誤率。

3.Gated Recurrent Units (GRU模型)

(GRU模型的講解也可以參考ShowMeAI的對吳恩達老師課程的總結文章深度學習教程 | 序列模型與RNN網路

除了迄今為止討論的擴充套件方法之外,我們已經瞭解到 RNN 通過使用更復雜的啟用單元來獲得表現更好。到目前為止,我們已經討論了從隱藏狀態\(h_{t-1}\)\(h_t\)轉換的方法,使用了一個仿射轉換和\(point-wise\)的非線性轉換。

研究者通過調整門啟用函式的結構完成對 RNN 結構的修改。

雖然理論上 RNN 能捕獲長距離資訊,但實際上很難訓練網路做到這一點。門控制單元可以讓 RNN 具有更多的永續性記憶體,從而更容易捕獲長距離資訊。讓我們從數學角度上討論 GRU 如何使用 \(h_{t-1}\)\(x_t\) 來生成下一個隱藏狀態\(h_t\)。然後我們將深入瞭解 GRU 架構。

Update gate\(z_{t} =\sigma \left(W^{(z)} x_{t}+U^{(z)} h_{t-1}\right)\)

Reset gate\(r_{t} =\sigma\left(W^{(r)} x_{t}+U^{(r)} h_{t-1}\right)\)

New memory\(\tilde{h}_{t} = \tanh \left(r_{t} \circ U h_{t-1}+W x_{t}\right)\)

Hidden state\(h_{t} = \left(1-z_{t}\right) \circ \tilde{h}_{t}+z_{t} \circ h_{t-1}\)

上述的共識可以認為是 GRU 的四個基本操作階段,下面對這些公式作出更直觀的解釋,下圖展示了 GRU 的基本結構和計算流程:

GRU的詳細內部結構

  • 新記憶生成:一個新的記憶 \(\tilde{h}_{t}\) 是由一個新的輸入單詞 \(x_t\) 和過去的隱藏狀態 \(h_{t-1}\) 共同計算所得。這個階段是將新輸入的單詞與過去的隱藏狀態 \(h_{t-1}\) 相結合,根據過去的上下文來總結得到向量 \(\tilde{h}_{t}\)

  • 重置門:復位訊號 \(r_t\) 是負責確定 \(h_{t-1}\) 對總結 \(\tilde{h}_{t}\) 的重要程度。如果確定 \(\tilde{h}_{t}\) 與新的記憶的計算無關,則復位門能夠完全消除過去的隱藏狀態 (即忽略之前隱藏的資訊) 。

  • 更新門:更新訊號 \(z_t\) 負責確定有多少 \(h_{t-1}\) 可以向前傳遞到下一個狀態。例如,如果 \(z_{t} \approx 1\),然後 \(h_{t-1}\) 幾乎是完全向前傳遞到下一個隱藏狀態。反過來,如果 \(z_{t} \approx 0\),然後大部分的新的記憶 \(\tilde{h}_{t}\) 向前傳遞到下一個隱藏狀態。

  • 隱狀態:利用更新門的建議,使用過去的隱藏輸入 \({h}_{t-1}\) 和新生成的記憶 \(\tilde{h}_{t}\) 生成隱藏狀態 \({h}_{t}\)

需要注意的是,為了訓練GRU,我們需要學習所有不同的引數:\(W, U, W^{(r)}, U^{(r)}, W^{(z)}, U^{(z)}\)。這些引數同樣是通過反向傳播演算法學習所得。

4.長短時記憶網路 (LSTM)

(LSTM模型的講解也可以參考ShowMeAI的對吳恩達老師課程的總結文章深度學習教程 | 序列模型與RNN網路

Long-Short-Term-Memories 是和 GRU 有一點不同的另外一種型別的複雜啟用神經元。它的作用與 GRU 類似,但是神經元的結構有一點區別。我們首先來看看 LSTM 神經元的數學公式,然後再深入瞭解這個神經元的設計架構:

輸入門/Input gate\(i_{t}=\sigma\left(W^{(i)} x_{t}+U^{(i)} h_{t-1}\right)\)

遺忘門/Forget gate\(f_{t}=\sigma\left(W^{(f)} x_{t}+U^{(f)} h_{t-1}\right)\)

輸出門/Output/Exposure gate\(o_{t}=\sigma\left(W^{(o)} x_{t}+U^{(o)} h_{t-1}\right)\)

新記憶生成/New memory cell\(\tilde{c}_{t}=\tanh \left(W^{(c)} x_{t}+U^{(c)} h_{t-1}\right)\)

最終記憶合成/Final memory cell\(c_{t}=f_{t} \circ c_{t-1}+i_{t} \circ \tilde{c}_{t}\)

\[h_{t}=o_{t} \circ \tanh \left(c_{t}\right) \]

下圖是LSTM的計算圖示

LSTM的詳細內部結構

我們可以通過以下步驟瞭解 LSTM 的架構以及這個架構背後的意義:

  • 新記憶生成:這個階段是類似於 GRU 生成新的記憶的階段。我們基本上是用輸入單詞 \(x_t\) 和過去的隱藏狀態來生成一個包括新單詞 \(x^{(t)}\) 的新的記憶 \(\tilde{c}_{t}\)

  • 輸入門:我們看到在生成新的記憶之前,新的記憶的生成階段不會檢查新單詞是否重要——這需要輸入門函式來做這個判斷。輸入門使用輸入詞和過去的隱藏狀態來決定輸入值是否值得儲存,從而用來進入新記憶體。因此,它產生它作為這個資訊的指示器。

  • 遺忘門:這個門與輸入門類似,只是它不確定輸入單詞的有用性——而是評估過去的記憶是否對當前記憶的計算有用。因此,遺忘門檢視輸入單詞和過去的隱藏狀態,並生成 \(f_t\)

  • 最終記憶合成:這個階段首先根據忘記門 \(f_t\) 的判斷,相應地忘記過去的記憶 \(c_{t-1}\)。類似地,根據輸入門 \(i_t\) 的判斷,相應地輸入新的記憶 \(\tilde c_t\)。然後將上面的兩個結果相加生成最終的記憶 \(c_t\)

  • 輸出門:這是GRU中沒有明確存在的門。這個門的目的是從隱藏狀態中分離最終的記憶。最終的記憶 \(c_t\) 包含很多不需要儲存在隱藏狀態的資訊。隱藏狀態用於LSTM的每個單個門,因此,該門是要評估關於記憶單元 \(c_t\) 的哪些部分需要顯露在隱藏狀態 \(h_t\) 中。用於評估的訊號是 \(o_t\),然後與 \(c_t\) 通過 \(o_{t} \circ \tanh \left(c_{t}\right)\) 運算得到最終的 \(h_t\)

5.參考資料

ShowMeAI 系列教程推薦

NLP系列教程文章

史丹佛 CS224n 課程帶學詳解

相關文章