一、循環神經網絡簡介
循環神經網絡,英文全稱:Recurrent Neural Network,或簡單記為RNN。需要注意的是,遞歸神經網絡(Recursive Neural Network)的簡寫也是RNN,但通常RNN指循環神經網絡。循環神經網絡是一類用於處理序列數據的神經網絡。它與其他神經網絡的不同是,RNN可以更好的去處理序列的信息,即認准了前后的輸入之間存在關系。在NLP中,去理解一整句話,孤立的理解組成這句話的詞顯然是不夠的,我們需要整體的處理由這些詞連接起來的整個序列。
如:(1) 我餓了,我要去食堂___。(2) 我飯卡丟了,我要去食堂___。很顯然,第一句話是想表明去食堂就餐,而第二句則很有可能因為剛吃過飯,發現飯卡不見了,去食堂尋找飯卡。而在此之前,我們常用的語言模型是N-Gram,無論何種語境,可能去食堂大概率匹配的是“吃飯”而不在乎之前的信息。RNN就解決了N-Gram的缺陷,它在理論上可以往前(后)看任意多個詞。
此文是我在學習RNN中所做的筆記,參考資料在文末提及。
二、循環神經網絡分類
a.簡單的MLP神經網絡
簡單的MLP三層網絡模型,x、o為向量,分別表示輸入層、輸出層的值;U、V為矩陣,U是輸入層到隱藏層的權重矩陣,V是隱藏層到輸出層的權重矩陣。
b.循環神經網絡
與簡單的MLP神經網絡不容的是,循環神經網絡的隱藏層的值s不僅取決於當前的這次輸入x,還取決於上一次隱藏層的值s。權重就在W就是隱藏層上一次的值作為這一次輸入的輸入的權重。將上圖展開:
由上圖可知以下公式,其中 V 是輸出層權重矩陣,g 是激活函數;U 是輸入x的權重矩陣,W 是上一次的值 st-1 作為這一次的輸入的權重矩陣,f 是激活函數。
反復帶入,即可得到:
可見,循環神經網絡的輸出值 ot 受之前的輸出值 xt 、xt-1、xt-2 所影響。
c. 雙向循環神經網絡
雙向循環神經網絡的計算方法:
從上面三個公式可以看出: 正向計算時,隱藏層的值與 st 和 st-1 有關,而反向計算時,隱藏層的值與 s't 和 s't+1 有關;最終的輸出取決於正向與反向計算的加和。
d、深度循環神經網絡
此前介紹的循環神經網絡只有一個輸入層、一個循環層和一個輸出層。與全連接神經網絡以及卷積神經網絡一樣,可以把它推廣到任意多個隱藏層的情況,得到深層循環神經網絡。深度循環神經網絡包含多個隱藏層(上圖為了表示清楚,只列舉了2層),並且也繼承了雙向循環神經網絡的特點。由之前的公式類推,我們可以得到深度循環神經網絡的計算方式:
深層神經網絡有3個方案:第一種叫做 Deep Input-to-Hidden Function,它在循環層之前加入多個普通的全連接層,將輸入向量進行多層映射之后再送入循環層進行處理。第二種方案是 Deep Hidden-to-Hidden Transition,它使用多個循環層,這和前饋神經網絡類似,唯一不同的是計算隱含層輸出的時候需要利用本隱含層上一時刻的值。第三種方案是 Deep Hidden-to-Output Function,它在循環層到輸出層之間加入多個全連接層,這與第一種情況類似。上面公式展示的應為第二種情況。
由於循環層一般用 tanh 作為激活函數,層次過多之后會導致梯度消失問題。后面會提及。
三、網絡的訓練及BPTT
循環神經網絡的輸入是序列數據,每個訓練樣本是一個時間序列,包含多個相同維度的向量。網絡的參數如何通過訓練確定?這里就要使用解決循環神經網絡訓練問題的 Back Propagation Through Time 算法,簡稱BPTT。
循環神經網絡的每個訓練樣本是一個時間序列,同一個訓練樣本前后時刻的輸入值之間有關聯,每個樣本的序列長度可能不相同。訓練時先對這個序列中的每個時刻的輸入值進行正向傳播,再通過反向傳播計算出參數的梯度值並更新參數。
它包含三個步驟:(1)正向計算每個神經元的輸出值;(2)反向計算每個神經元的誤差項 δj ,它是誤差函數 E 對神經元 j 的加權輸入 netj 的偏導數;(3)計算每個權重的梯度;(4)用隨機梯度下降算法更新權重。具體的算法推導我會在之后的筆記整理中總結。
四、梯度爆炸、梯度消失
循環神經網絡在進行反向傳播時也面臨梯度消失或者梯度爆炸問題,這種問題表現在時間軸上。如果輸入序列的長度很長,人們很難進行有效的參數更新。通常來說梯度爆炸更容易處理一些。因為梯度爆炸時,我們的程序會收到NaN的錯誤。我們也可以設置一個梯度閾值,當梯度超過這個閾值的時候可以直接截取。
梯度消失更難檢測,而且也更難處理一些。總的來說,我們有三種方法應對梯度消失問題:
(1)合理的初始化權重值。初始化權重,使每個神經元盡可能不要取極大或極小值,以多開梯度消失的區域。
(2) 使用 ReLu 代替 sigmoid 和 tanh 作為激活函數。
(3) 使用其他結構的RNNs,比如長短時記憶網絡(LTSM)和 門控循環單元 (GRU),這是最流行的做法。
五、練手項目
可以參考github上比較出名的char_RNN的代碼來提高自己的興趣。該項目就是通過訓練語料來自己寫詩、歌、文。
下圖是我的訓練結果:
(1) 一首詩,這首通過RNN訓練寫出的詩還是不錯的。“秋”與“春”是對應的,描繪的是詩人在秋日,欣賞的山中風景。不禁感嘆,自己的青春已去,自己也已經白首,吟唱着這首詩(編不下去了…)。
(2) 通過自己找的《三體》全集,來訓練出的小說片段。可以看到,只能模仿句式,不能有准確表達,所以邏輯不通的,但是形式是很像劉慈欣的寫法了。