使用Keras進行深度學習:(五)RNN和雙向RNN講解及實踐

磐石001發表於2018-04-26

歡迎大家關注我們的網站和系列教程:http://www.tensorflownews.com/,學習更多的機器學習、深度學習的知識!

筆者:Ray

介紹

通過對前面文章的學習,對深度神經網路(DNN)和卷積神經網路(CNN)有了一定的瞭解,也感受到了這些神經網路在各方面的應用都有不錯的效果。然而這些網路都有一個共同的特點:每一層的神經元之間是相互獨立的,如輸入層的神經元彼此之間是獨立的。然而,現實世界中很多元素之間都是有相互聯絡的。比如一部連續劇的內容,上一集和這一集的內容會有一定的聯絡;同樣的,一句話,如“天空很藍”,我們通過“天空”和“很”會認為接下來的詞為“藍”的概率會較高。正如這種時序資料問題,使用之前所學的模型(除了text-CNN)可能很難做到準確的推斷,因此我們引入今天所講的迴圈神經網路(recurrent neural network),其主要的用處就是處理和預測序列資料

目錄

  • RNN網路結構及原理講解
  • 雙向RNN網路結構及原理講解
  • 深層RNN網路結構
  • Keras對RNN的支援
  • 使用Keras RNN、BRNN、DBRNN模型進行實踐

一、RNN網路結構及原理講解

RNN的網路結構如下圖:

圖中左側是未展開RNN模型,在模型中間有個大圓圈表示迴圈,正是這個迴圈允許資訊的持久化。但這個看起來可能不太好理解,因此將其展開為右側的模型,並做進一步詳細介紹如何實現資訊的持久化。

右圖中圓圈可以看作一個單元。定義Xi為第i時刻的輸入,hi為第i時刻的記憶,yi為第i時刻的輸出。

舉個例子說明RNN實現過程:假設有一個句子的輸入是”今天天空很”,要預測下個詞是什麼。通過分詞後可能得到三個詞作為輸入:“今天”,“天空”,“很”,對應的就是上圖的Xi-1,Xi,Xi+1,那麼輸出yi-1應該是“天空”,yi應該是“很”,預測下個詞yi+1是什麼,根據這句話,“藍”的概率比較大。因此預測下個詞應該是“藍”。

通過上述淺顯易懂的例子讀者應該對RNN實現過程有個大概的瞭解,接下來將具體講解RNN實現的詳細過程。

輸入層到隱藏層

從上圖的箭頭指示,讀者或許發現第i時刻的輸出是由上一時刻的記憶和當前時刻共同決定的。這個思想很符合對時序資料處理的思路。正如我們在看連續劇的時候如果直接看中間某一集,可能會對部分劇情不能理解,但是,當我們看過前幾集後會對劇情有所記憶,再加上該集劇情內容,我們就能更好的理解接下來劇情內容。因此用公式表示RNN當前時刻的記憶為:

其中f()函式為啟用函式。在此處要加上啟用函式也很好理解,因為得到的資訊並不是所有的都是重要的資訊,而我們只需要記住重要的資訊即可。這個時候就可以使用啟用函式,如tanh,去對一些不重要的資訊進行過濾,保留重要的資訊即可。

隱藏層到輸出層

同樣使用電視劇的例子進行通俗解釋,當我們對上幾集和該集的劇情進行整理,留下一些重要資訊之後,我們會試圖去猜測下一集的內容大概會是怎麼樣的。同樣的,RNN的思路也如此。當我們hi中保留了i時刻的重要資訊後,就試圖使用這些重要資訊進行預測下一個詞應該是什麼。用公式表示RNN當前時刻的輸出為:

使用softmax函式是RNN希望預測每個詞出現的概率,然後概率最高的詞就是預測的下一個詞。

注:U、W、V分別是對應的權重矩陣,通過反向傳播演算法調整相應的值使得預測的結果更加準確。與CNN一樣,網路中的每個單元都共享同一組(U、V、W),可以極大的降低了計算量。

具體的前向傳播計算過程如下:

在t1時刻的輸入為2,結合上一時刻的記憶(0.537,0.462),得到(0.54,0.46,2.0),然後與隱藏層的權重矩陣相乘得到該時刻的記憶(0.860,0.884)。通過該時刻的記憶與輸出層的權重矩陣相乘得到該時刻的預測值2.73。這就是一個時刻RNN前向傳播的具體過程。

 

因此,通過上述思想,RNN就能有效的處理時序資料,對每個輸入保留一些重要的資訊,理論上最後就能得到整個輸入的所有重要資訊,進而綜合考慮所有輸入去預測輸出。

 

二、雙向RNN(BRNN)網路結構及原理講解

在RNN中只考慮了預測詞前面的詞,即只考慮了上下文中“上文”,並沒有考慮該詞後面的內容。這可能會錯過了一些重要的資訊,使得預測的內容不夠準確。正如電視劇的例子,當在該集新出現了一個人物,若要預測該人物的名字,單從前幾集的內容,並不能有效的進行預測。但如果我們看了後幾集的內容,可能就能更加有效的進行預測。雙向RNN也是基於這種思想,不僅從前往後(如下圖黃色實箭頭)保留該詞前面的詞的重要資訊,而且從後往前(如下圖黃色虛箭頭)去保留該詞後面的詞的重要資訊,然後基於這些重要資訊進行預測該詞。雙向RNN模型如下:

用公式表示雙向RNN過程如下:

另外,雙向RNN需要儲存兩個方向的權重矩陣,所以需要的記憶體約為RNN的兩倍。

 

三、深層RNN(DRNN)網路結構

深層RNN網路是在RNN模型多了幾個隱藏層,是因為考慮到當資訊量太大的

時候一次性儲存不下所有重要資訊,通過多個隱藏層可以儲存更多的重要資訊,正如我們看電視劇的時候也可能重複看同一集記住更多關鍵劇情。同樣的,我們也可以在雙向RNN模型基礎上加多幾層隱藏層得到深層雙向RNN模型。

注:每一層迴圈體中引數是共享的,但是不同層之間的權重矩陣是不同的。

四、Keras對RNN的支援

在Keras同樣對RNN模型進行了封裝,並且呼叫起來十分方便,我們將會在下一節搭建RNN模型來呈現使用Keras搭建是多麼方便。

Keras在layers包的recurrent模組中實現了RNN相關層模型的支援,並在wrapper模型中實現雙向RNN包裝器。

 

recurrent模組中的RNN模型包括RNN、LSTM、GRU等模型(後兩個模型將在後面Keras系列文章講解):

1.RNN:全連線RNN模型

SimpleRNN(units,activation=’tanh’,dropout=0.0,recurrent_dropout=0.0, return_sequences=False)

2.LSTM:長短記憶模型

LSTM(units,activation=’tanh’,dropout=0.0,recurrent_dropout=0.0,return_sequences=False)

3.GRU:門限迴圈單元

GRU(units,activation=’tanh’,dropout=0.0,recurrent_dropout=0.0,return_sequences=False)

4.引數說明:

units: RNN輸出的維度

activation: 啟用函式,預設為tanh

dropout: 0~1之間的浮點數,控制輸入線性變換的神經元失活的比例

recurrent_dropout:0~1之間的浮點數,控制迴圈狀態的線性變換的神經元失活比例

return_sequences: True返回整個序列,用於stack兩個層,False返回輸出序列的最後一個輸出,若模型為深層模型時設為True

input_dim: 當使用該層為模型首層時,應指定該值

input_length: 當輸入序列的長度固定時,該引數為輸入序列的長度。當需要在該層後連線Flatten層,然後又要連線Dense層時,需要指定該引數

 

wrapper模組實現雙向RNN模型

  1. 雙向RNN包裝器

Bidirectional(layer, merge_mode=’concat’, weights=None)

引數說明:

layer: SimpleRNN、LSTM、GRU等模型結構,確定是哪種RNN的雙向模型

Merge_mode: 前向和後向RNN輸出的結合方式,為sum,mul,concat,ave和None之一,若為None,則不結合,以列表形式返回,若是上文說到的拼接則為concat

 

五、使用Keras RNN、BRNN模型、DBRNN模型進行實踐

本次實踐同樣使用上一篇文章中使用到的Imdb資料集進行情感分析。對於該資料集的預處理在本篇文章中就不再介紹,若想了解可閱讀上一篇文章。

Keras在實現迴圈神經網路很方便,已經將其封裝好,只需要呼叫相應的層就可以搭建該模型,接下來簡單的搭建上述三種模型。

搭建一層的RNN模型,只需要在模型中加入SImpleRNN層,並設定該層的輸出即可,其他模型的搭建都和上篇文章中講解的一樣,相當方便。

BRNN模型需要使用wrappers包的Bidirecitional模組實現雙向RNN模型,並且要將return_sequences引數設定為True,因為如上文所述需要將前、後向的重要資訊拼接起來,所以需要將整個序列返回,而不是隻返回最後一個預測詞。

並且上文提到的是將前後向的進行拼接,所以使用的是’concat’,也可以使用sum對前後向結果求和或者其他對結果進行相應的操作。

DBRNN模型的搭建也很方便,比如在這裡我們要搭建一個兩層的DBRNN模型,只需要再加一層SimpleRNN即可。要注意的是,如果要搭建多層DBRNN模型,除了最後一層SimpleRNN外,其他的SimpleRNN層都需要將return_sequences引數設定為True。

 

可能讀者會認為雖然Keras搭建模型很方便,但是這會導致新手對於模型的輸入輸出欠缺理解。同樣的,Keras也考慮到了這一點,因此Keras中有model.summary()的內建函式,通過這個函式就可以知道我們搭建的模型的輸入輸出和引數等資訊,便於我們理解模型和debug。下圖給出上圖搭建的DBRNN的summary。

模型的損失函式,優化器和評價指標如下:

在訓練模型之前,介紹Keras中一種優化模型效果且可以加快模型學習速度的方法:EarlyStopping。

EarlyStopping介紹

EarlyStopping是Callbacks的一種,callbacks用於指定在每個epoch開始和結束的時候進行哪種特定操作,即用於提前停止訓練的callbacks。之所以要提前停止訓練,是因為繼續訓練會導致測試集上的準確率下降。那繼續訓練導致測試準確率下降的原因筆者猜測可能是1. 過擬合 2. 學習率過大導致不收斂 3. 使用正則項的時候,Loss的減少可能不是因為準確率增加導致的,而是因為權重大小的降低。

EarlyStopping的使用

一般是在model.fit函式中呼叫callbacks,fit函式中有一個引數為callbacks。注意這裡需要輸入的是list型別的資料,所以通常情況只用EarlyStopping的話也要是[EarlyStopping()]

keras.callbacks.EarlyStopping(monitor=’val_loss’, patience=0, verbose=0, mode=’auto’)

引數說明:

monitor:需要監視的量,如’val_loss’, ‘val_acc’, ‘acc’, ‘loss’。

patience:能夠容忍多少個epoch內都沒有improvement。

verbose:資訊展示模式

mode:‘auto’,‘min’,‘max’之一,在min模式下,如果檢測值停止下降則中止訓練。在max模式下,當檢測值不再上升則停止訓練。例如,當監測值為val_acc時,模式應為max,當檢測值為val_loss時,模式應為min。在auto模式下,評價準則由被監測值的名字自動推斷。

可以看到在第13次訓練完成後,驗證集的準確率下降後就停止了繼續訓練,這樣可以既可以加快訓練模型速度,也可以使得在驗證集的準確率不再下降。

 

最後我們使用三種訓練好的模型進行預測測試集,得到在RNN和DBRNN上模型的準確率在0.85左右,在BRNN模型在0.87左右。讀者可以通過調參進一步提高模型的準確率。

完整程式碼下載:

https://github.com/hongweijun811/wjgit

至此,我們應該對RNN模型以及Keras實現RNN模型有了一定的瞭解。下一篇文章我們將會對RNN模型的改進模型LSTM模型進行詳細講解。歡迎持續關注我們的Keras系列文章!

 

 

本篇文章出自http://www.tensorflownews.com,對深度學習感興趣,熱愛Tensorflow的小夥伴,歡迎關注我們的網站!


相關文章