迴圈神經網路(RNN)是非常流行的模型,在NLP的很多工中已經展示出了很大的威力。但與此相對的是,能完整解釋RNN是如何工作,如何實現的資源非常有限。這也是本教程所要做的事情,本教程打算覆蓋下面幾個方面的內容:

1。 RNN簡介(本篇)

2。 用python和theano實現一個RNN

3。 理解隨時間反向傳播演算法(BPTT)和梯度消失問題

4。 實現一個GRU/LSTM RNN

作為本教程的一部分,將會實現一個基於RNN的語言模型(rnnlm)。語言模型有兩個方面的應用:一,基於每個序列在現實世界中出現的可能性對其進行打分,這實際上提供了一個針對語法和語義正確性的度量,語言模型通常為作為機器翻譯系統的一部分。二,語言模型可以用來生成新文字。根據莎士比亞的作品訓練語言模型可以生成莎士比亞風格的文字。這篇部落格(The Unreasonable Effectiveness of Recurrent Neural Networks)說明了基於RNN的字元級別的語言模型能做什麼。

這裡假設你已經熟悉一些基本的神經網路。否則的話,你可以先瀏覽一下這篇文章(Implementing A Neural Network From Scratch),它會帶你瞭解非迴圈神經網路的一些思想和具體實現。

RNN是什麼?

RNN背後的思想是利用順序資訊。在傳統的神經網路中,我們假設所有的輸入(包括輸出)之間是相互獨立的。對於很多工來說,這是一個非常糟糕的假設。如果你想預測一個序列中的下一個詞,你最好能知道哪些詞在它前面。RNN之所以迴圈的,是因為它針對系列中的每一個元素都執行相同的操作,每一個操作都依賴於之前的計算結果。換一種方式思考,可以認為RNN記憶了到當前為止已經計算過的資訊。理論上,RNN可以利用任意長的序列資訊,但實際中只能回顧之前的幾步。下面是RNN的一個典型結構圖:

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

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

上面的圖中展示了RNN被展開成一個全網路後的結構。這裡展開的意思是把針對整個序列的網路結構表示出來。例如,如果這裡我們關心的是一個包含5個詞的句子,那這裡網路將會被展開成一個5層的網路,每個詞對應一層。在RNN中進行的計算公式如下:

x_{t}

t

時刻的輸入。例如,

x_{1}

是句子中第二個詞的one hot編碼向量。

s_{t}

是對應

t

時刻的隱藏狀態,是網路的記憶單元。

s_{t}

透過前一步的隱藏狀態和當前時刻的輸入得到:

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

。函式

f

通常是非線性的,例如tanh和ReLU。

s_{-1}

通常用來計算第一個隱藏狀態,會被全0初始化。

o_{t}

t

時刻的輸出。例如,如果想要預測句子中的下一個詞,那麼它就會是包含詞表中所有詞的一個機率向量,

o_{t}=softmax(Vs_{t})

這裡有一些需要注意的地方:

你可以認為隱藏狀態

s_{t}

是網路的記憶單元。

s_{t}

可以捕捉到之前所有時刻產生的資訊。輸出

o_{t}

僅僅依賴於

t

時刻的記憶。就像之前提到的那樣,在實際中是比較複雜的,因為

s_{t}

通常難以捕捉許多時刻之前的資訊。

與傳統深度神經網路中每一層使用不同的引數的做法不同,RNN在所有時刻中共享相同的引數

U,V,W

。這反應了在每一步中都在執行相同的任務,只是用了不同的輸入。這極大地減少了需要學習的引數的個數。

上面的圖中每一時刻都有輸出,在具體的任務中,這可能是不必要的。例如,在預測一句話的情感時,我們關心的可能只是最終的輸出,並不是每一個詞之後的情感。相似地,可能並不是每一時刻都需要輸入。RNN的主要特徵是它的隱藏狀態,可以捕捉一句話中的資訊。

RNN能做什麼?

RNN在NLP的很多工中都取得了很大的成功。這裡我要提下最常用的RNN型別是LSTM,相比於普通的RNN,它更擅長於捕捉長期依賴。但是不要擔心,LSTM和我們這個教程裡要介紹的RNN本質上是相同的,只是使用了一種不同的方式來計算隱藏狀態。在後面的文章中,將會更詳細的介紹LSTM。下面是RNN在NLP中的一些應用例子。

語言模型和文字生成

給定一個詞的序列,我們想預測在前面的詞確定之後,每個詞出現的機率。語言模型可以度量一個句子出現的可能性,這可以作為機器翻譯的一個重要輸入(因為出現機率高的句子通常是正確的)。能預測下一個詞所帶來的額外效果是我們得到了一個生成模型,這可以讓我們透過對輸出機率取樣來生成新的文字。根據訓練資料的具體內容,我們可以生成任意東西。在語言模型中,輸入通常是詞的序列(編碼成one hot向量),輸出是預測得到的詞的序列。在訓練網路是,設定

o_{t}=x_{t+1}

,因為我們想要的

t

時刻的輸出是下一個詞。

關於語言模型和文字生成的研究論文:

Recurrent neural network based language model

Extensions of Recurrent neural network based language model

Generating Text with Recurrent Neural Networks

機器翻譯

機器翻譯與語言模型相似,輸入是源語言中的一個詞的序列(例如,德語),輸出是目標語言(例如,英語)的一個詞的序列。一個關鍵不同點在於在接收到了完整的輸入後才會開始輸出,因為我們要翻譯得到的句子的第一個詞可能需要前面整個輸入序列的資訊。

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

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

關於機器翻譯的研究論文:

A Recursive Recurrent Neural Network for Statistical Machine Translation

Sequence to Sequence Learning with Neural Networks

Joint Language and Translation Modeling with Recurrent Neural Networks

語音識別

給定一段從聲波中產生的輸入聲學訊號序列,我們想要預測一個語音片段序列及其機率。

關於語音識別的研究論文:

Towards End-to-End Speech Recognition with Recurrent Neural Networks

影象描述生成

和卷及神經網路一起,RNN可以作為生成無標註影象描述模型的一部分。對於這個如何工作的看起來非常令人驚訝。這個聯合模型甚至可以對齊生成的詞和影象中的特徵。

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

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

RNN訓練

訓練RNN和訓練傳統神經網路相似,同樣要使用反向傳播演算法,但會有一些變化。因為引數在網路的所有時刻是共享的,每一次的梯度輸出不僅依賴於當前時刻的計算結果,也依賴於之前所有時刻的計算結果。例如,為了計算

t=4

時刻的梯度,需要反向傳播3步,並把前面的所有梯度加和。這被稱作隨時間的反向傳播(BPTT)。如果你現在沒有理解,不要擔心,後面會有關於更多細節的文章。現在,只要知道普通的用BPTT訓練的RNN對於學習長期依賴(相距很長時間的依賴)是很困難的,因為這裡存在梯度消失或爆炸問題。當然也存在一些機制來解決這些問題,特定型別的RNN(如LSTM)就是專門設計來解決這些問題的。

RNN擴充套件

這些年來,研究者們已經提出了更加複雜的RNN型別來克服普通RNN模型的缺點,在後面的部落格中會更詳細的介紹它們,這一節只是一個簡單的概述讓你能夠熟悉模型的類別。

Bidirectional RNN

的思想是

t

時刻的輸出不僅依賴於序列中之前的元素,也依賴於之後的元素。例如,要預測一句話中缺失的詞,你可能需要左右上下文。Bidirecrtional RNN很直觀,只是兩個RNN相互堆疊在一起,輸出是由兩個RNN的隱藏狀態計算得到的。

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

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

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

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

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

LSTM network最近非常流行,上面也簡單討論過。LSTM與RNN在結構上並沒有本質的不同,只是使用了不同的函式來計算隱藏狀態。LSTM中的記憶單元被稱為細胞,你可以把它當作是黑盒,它把前一刻的狀態

h_{t-1}

和當前輸入

x_{t}

。內部這些細胞能確定什麼被儲存在記憶中,什麼被從記憶中刪除。這些細胞把之前的狀態,當前的記憶和輸入結合了起來,事實證明這些型別的單元對捕捉長期依賴十分有效。LSTM在剛開始時會讓人覺得困惑,如果你想了解更多,這篇部落格(Understanding LSTM Networks)有很好的解釋。

總結

到目前為止一切都很好,希望你已經對RNN是什麼以及能做什麼有了基本的瞭解,在接下來的文章中,我會使用python和theano實現RNN語言模型的第一個版本。

PS:本文是針對Recurrent Neural Networks Tutorial, Part 1這篇文章的中文翻譯,主要是為了加深自己的理解,後面還會對後續的文章進行翻譯,如果有什麼翻譯的不好的地方,請參見原文。