DNN的特例CNN的模型和前向反向傳播算法,這些算法都是前向反饋的,模型的輸出和模型本身沒有關聯關係。今天我們就討論另一類輸出和模型間有反饋的神經網絡:循環神經網絡(Recurrent Neural Networks ,以下簡稱RNN),它廣泛的用於自然語言處理中的語音識別,手寫書別以及機器翻譯等領域。
RNN概述
在前面講到的DNN和CNN中,訓練樣本的輸入和輸出是比較的確定的。但是有一類問題DNN和CNN不好解決,就是訓練樣本輸入是連續的序列,且序列的長短不一,比如基於時間的序列:一段段連續的語音,一段段連續的手寫文字。這些序列比較長,且長度不一,比較難直接的拆分成一個個獨立的樣本來通過DNN/CNN進行訓練。
而對於這類問題,RNN則比較的擅長。那麼RNN是怎麼做到的呢?RNN假設我們的樣本是基於序列的。比如是從序列索引1到序列索引τ的。對於這其中的任意序列索引號t,它對應的輸入是對應的樣本序列中的x(t)。而模型在序列索引號t位置的隱藏狀態h(t),則由x(t)和在t−1位置的隱藏狀態h(t−1)共同決定。在任意序列索引號t,我們也有對應的模型預測輸出o(t)。通過預測輸出o(t)和訓練序列真實輸出y(t),以及損失函數L(t),我們就可以用DNN類似的方法來訓練模型,接着用來預測測試序列中的一些位置的輸出。
下面我們來看看RNN的模型。
RNN模型
RNN模型有比較多的變種,這裏介紹最主流的RNN模型結構如下:
上圖中左邊是RNN模型沒有按時間展開的圖,如果按時間序列展開,則是上圖中的右邊部分。我們重點觀察右邊部分的圖。
這幅圖描述了在序列索引號t附近RNN的模型。其中:
1)x ( t ) x^{(t)} x ( t ) 代表在序列索引號t時訓練樣本的輸入。同樣的,x ( t − 1 ) x^{(t-1)} x ( t − 1 ) 和x ( t + 1 ) x^{(t+1)} x ( t + 1 ) 代表在序列索引號t−1和t+1時訓練樣本的輸入。
2)h ( t ) h^{(t)} h ( t ) 代表在序列索引號t時模型的隱藏狀態。h ( t ) h^{(t)} h ( t ) 由x ( t ) x^{(t)} x ( t ) 和h ( t − 1 ) h^{(t-1)} h ( t − 1 ) 共同決定。
3)o ( t ) o^{(t)} o ( t ) 代表在序列索引號t時模型的輸出。o ( t ) o^{(t)} o ( t ) 只由模型當前的隱藏狀態h ( t ) h^{(t)} h ( t ) 決定。
4)L(t)代表在序列索引號t時模型的損失函數。
5)y(t)代表在序列索引號t時訓練樣本序列的真實輸出。
6)U,W,V這三個矩陣是我們的模型的線性關係參數,它在整個RNN網絡中是共享的,這點和DNN很不相同。 也正因爲是共享了,它體現了RNN的模型的“循環反饋”的思想。
RNN前向傳播算法
有了上面的模型,RNN的前向傳播算法就很容易得到了。
對於任意一個序列索引號t,我們隱藏狀態h ( t ) h^{(t)} h ( t ) 由x ( t ) x^{(t)} x ( t ) 和h ( t − 1 ) h^{(t-1)} h ( t − 1 ) 得到:
h ( t ) = σ ( z ( t ) ) = σ ( U x ( t ) + W h ( t − 1 ) + b ) h^{(t)} = \sigma(z^{(t)}) = \sigma(Ux^{(t)} + Wh^{(t-1)} +b ) h ( t ) = σ ( z ( t ) ) = σ ( U x ( t ) + W h ( t − 1 ) + b )
其中σ爲RNN的激活函數,一般爲tanh, b爲線性關係的偏倚。
序列索引號t時模型的輸出o(t)的表達式比較簡單:
o ( t ) = V h ( t ) + c o^{(t)} = Vh^{(t)} +c o ( t ) = V h ( t ) + c
在最終在序列索引號t時我們的預測輸出爲:
y ^ ( t ) = σ ( o ( t ) ) \hat{y}^{(t)} = \sigma(o^{(t)}) y ^ ( t ) = σ ( o ( t ) )
通常由於RNN是識別類的分類模型,所以上面這個激活函數一般是softmax。
通過損失函數L(t),比如對數似然損失函數,我們可以量化模型在當前位置的損失,即y ^ ( t ) \hat{y}^{(t)} y ^ ( t ) 和y ( t ) y^{(t)} y ( t ) 的差距。
RNN反向傳播算法推導
有了RNN前向傳播算法的基礎,就容易推導出RNN反向傳播算法的流程了。RNN反向傳播算法的思路和DNN是一樣的,即通過梯度下降法一輪輪的迭代,得到合適的RNN模型參數U,W,V,b,c。由於我們是基於時間反向傳播,所以RNN的反向傳播有時也叫做BPTT(back-propagation through time)。當然這裏的BPTT和DNN也有很大的不同點,即這裏所有的U,W,V,b,c在序列的各個位置是共享的,反向傳播時我們更新的是相同的參數。
爲了簡化描述,這裏的損失函數我們爲交叉熵損失函數,輸出的激活函數爲softmax函數,隱藏層的激活函數爲tanh函數。
對於RNN,由於我們在序列的每個位置都有損失函數,因此最終的損失L爲:
L = ∑ t = 1 τ L ( t ) L = \sum\limits_{t=1}^{\tau}L^{(t)} L = t = 1 ∑ τ L ( t )
其中V,c,的梯度計算是比較簡單的:
∂ L ∂ c = ∑ t = 1 τ ∂ L ( t ) ∂ c = ∑ t = 1 τ y ^ ( t ) − y ( t ) \frac{\partial L}{\partial c} = \sum\limits_{t=1}^{\tau}\frac{\partial L^{(t)}}{\partial c} = \sum\limits_{t=1}^{\tau}\hat{y}^{(t)} - y^{(t)} ∂ c ∂ L = t = 1 ∑ τ ∂ c ∂ L ( t ) = t = 1 ∑ τ y ^ ( t ) − y ( t )
∂ L ∂ V = ∑ t = 1 τ ∂ L ( t ) ∂ V = ∑ t = 1 τ ( y ^ ( t ) − y ( t ) ) ( h ( t ) ) T \frac{\partial L}{\partial V} =\sum\limits_{t=1}^{\tau}\frac{\partial L^{(t)}}{\partial V} = \sum\limits_{t=1}^{\tau}(\hat{y}^{(t)} - y^{(t)}) (h^{(t)})^T ∂ V ∂ L = t = 1 ∑ τ ∂ V ∂ L ( t ) = t = 1 ∑ τ ( y ^ ( t ) − y ( t ) ) ( h ( t ) ) T
但是W,U,b的梯度計算就比較的複雜了。從RNN的模型可以看出,在反向傳播時,在在某一序列位置t的梯度損失由當前位置的輸出對應的梯度損失和序列索引位置t+1時的梯度損失兩部分共同決定。對於W在某一序列位置t的梯度損失需要反向傳播一步步的計算。我們定義序列索引t位置的隱藏狀態的梯度爲:
δ ( t ) = ∂ L ∂ h ( t ) \delta^{(t)} = \frac{\partial L}{\partial h^{(t)}} δ ( t ) = ∂ h ( t ) ∂ L
這樣我們可以像DNN一樣從δ ( t + 1 ) \delta^{(t+1)} δ ( t + 1 ) 遞推δ ( t ) \delta^{(t)} δ ( t ) 。
δ ( t ) = ( ∂ o ( t ) ∂ h ( t ) ) T ∂ L ∂ o ( t ) + ( ∂ h ( t + 1 ) ∂ h ( t ) ) T ∂ L ∂ h ( t + 1 ) = V T ( y ^ ( t ) − y ( t ) ) + W T d i a g ( 1 − ( h ( t + 1 ) ) 2 ) δ ( t + 1 ) \delta^{(t)} =(\frac{\partial o^{(t)}}{\partial h^{(t)}} )^T\frac{\partial L}{\partial o^{(t)}} + (\frac{\partial h^{(t+1)}}{\partial h^{(t)}})^T\frac{\partial L}{\partial h^{(t+1)}} = V^T(\hat{y}^{(t)} - y^{(t)}) + W^Tdiag(1-(h^{(t+1)})^2)\delta^{(t+1)} δ ( t ) = ( ∂ h ( t ) ∂ o ( t ) ) T ∂ o ( t ) ∂ L + ( ∂ h ( t ) ∂ h ( t + 1 ) ) T ∂ h ( t + 1 ) ∂ L = V T ( y ^ ( t ) − y ( t ) ) + W T d i a g ( 1 − ( h ( t + 1 ) ) 2 ) δ ( t + 1 )
對於δ(τ),由於它的後面沒有其他的序列索引了,因此有:
δ ( τ ) = ( ∂ o ( τ ) ∂ h ( τ ) ) T ∂ L ∂ o ( τ ) = V T ( y ^ ( τ ) − y ( τ ) ) \delta^{(\tau)} =( \frac{\partial o^{(\tau)}}{\partial h^{(\tau)}})^T\frac{\partial L}{\partial o^{(\tau)}} = V^T(\hat{y}^{(\tau)} - y^{(\tau)}) δ ( τ ) = ( ∂ h ( τ ) ∂ o ( τ ) ) T ∂ o ( τ ) ∂ L = V T ( y ^ ( τ ) − y ( τ ) )
有了δ(t),計算W,U,b就容易了,這裏給出W,U,b的梯度計算表達式:
∂ L ∂ W = ∑ t = 1 τ d i a g ( 1 − ( h ( t ) ) 2 ) δ ( t ) ( h ( t − 1 ) ) T \frac{\partial L}{\partial W} = \sum\limits_{t=1}^{\tau}diag(1-(h^{(t)})^2)\delta^{(t)}(h^{(t-1)})^T ∂ W ∂ L = t = 1 ∑ τ d i a g ( 1 − ( h ( t ) ) 2 ) δ ( t ) ( h ( t − 1 ) ) T
∂ L ∂ b = ∑ t = 1 τ d i a g ( 1 − ( h ( t ) ) 2 ) δ ( t ) \frac{\partial L}{\partial b}= \sum\limits_{t=1}^{\tau}diag(1-(h^{(t)})^2)\delta^{(t)} ∂ b ∂ L = t = 1 ∑ τ d i a g ( 1 − ( h ( t ) ) 2 ) δ ( t )
∂ L ∂ U = ∑ t = 1 τ d i a g ( 1 − ( h ( t ) ) 2 ) δ ( t ) ( x ( t ) ) T \frac{\partial L}{\partial U} =\sum\limits_{t=1}^{\tau}diag(1-(h^{(t)})^2)\delta^{(t)}(x^{(t)})^T ∂ U ∂ L = t = 1 ∑ τ d i a g ( 1 − ( h ( t ) ) 2 ) δ ( t ) ( x ( t ) ) T
除了梯度表達式不同,RNN的反向傳播算法和DNN區別不大,因此這裏就不再重複總結了。
RNN小結
上面總結了通用的RNN模型和前向反向傳播算法。當然,有些RNN模型會有些不同,自然前向反向傳播的公式會有些不一樣,但是原理基本類似。
RNN雖然理論上可以很漂亮的解決序列數據的訓練,但是它也像DNN一樣有梯度消失時的問題,當序列很長的時候問題尤其嚴重。因此,上面的RNN模型一般不能直接用於應用領域。在語音識別,手寫書別以及機器翻譯等NLP領域實際應用比較廣泛的是基於RNN模型的一個特例LSTM,下一篇我們就來討論LSTM模型。