這周在看循環神經網絡,發現一個博客,裏面的推導過程極其詳細,藉此記錄重點
詳細推導
強烈介意手推一遍,雖然可能會花一點時間,但便於理清思路。
語言模型
RNN是在自然語言處理領域中最先被用起來的,比如,RNN可以作爲語言模型來建模。
什麼是語言模型?
語言模型:給定一個一句話前面的部分,預測接下來最有可能的一個詞是什麼。
語言模型可以用在語音轉文本(STT)上,也可以用在圖像到文本的識別中(OCR)。
使用RNN之前,語言模型主要採用N-Gram,即先對句子切詞,再在語料庫中搜索前n個詞進行預測,這樣想法沒有實用性,因爲根本沒有用到有用的信息,並且該模型還會佔用海量的存儲空間。
所以,RNN出現,理論上RNN可以往前看(往後看)任意多個詞。
循環神經網絡
基本神經網絡
如上圖左,一個簡單的循環神經網絡由一個輸入層、一個隱藏層和一個輸出層組成。
其中,x 是一個向量,代表輸入層的值;s 是一個向量,代表隱藏層的值;o 是一個向量,代表輸出層的值。
U 是輸入層到隱藏層的權重矩陣,V 是隱藏層到輸出層的權重矩陣,權重矩陣W 是隱藏層上一次的值作爲這一次的輸入的權重。循環神經網絡與普通的全連接神經網絡不同的地方也就在於W 。
如上圖右,可表示循環神經網絡的計算方式:
otst=g(Vst)(式1)=f(Uxt+Wst−1)(式2)(1)(2)
其中,
式1是輸出層的計算公式,輸出層是一個全連接層,即每一個節點都與隱藏層的每個節點相連,g代表激活函數,
V 是輸出層的權重矩陣。
式2是隱藏層的計算公式,它是一個循環層,f是激活函數,U 是輸入x 的權重矩陣,W 是上次值st−1 作爲這次輸入的權重矩陣。
雙向循環神經網絡
對於語言模型來說,很多時候光看前面的詞是不夠的,還需要看後面的詞。普通的基本循環神經網絡對此無法建模,因此,我們需要雙向循環神經網絡。
從上圖可知,雙向循環神經網絡的隱藏層要保存兩個值,一個A 參與正向計算,另一個值A′ 參與反向計算。最後的輸出值y2 取決於A2 和A′2 。仿照式1和試2,雙向循環神經網絡的計算方法如下:
otsts′t=g(Vst+V′s′t)=f(Uxt+Wst−1)=f(U′xt+W′s′t+1)(3)(4)(5)
可以看出:正向計算時,隱藏層的值
st 與
st−1 有關;反向計算時,隱藏層的值
s′t 和
s′t−1 有關。正向計算和反向計算
不共享權重,也就是說
U 和
U′ 、
W 和
W′ 、
V 和
V′ 都是不同的權重矩陣。
深度循環神經網絡
之前介紹的RNN都是隻有一個隱藏層,當堆疊兩個以上隱藏層時,就得到了深度循環神經網絡
把第i個隱藏層的值表示爲s(i)t 、s′(i)t ,則深度循環神經網絡的計算方式可以表示爲:
ots(i)ts′(i)t...s(1)ts′(1)t=g(V(i)s(i)t+V′(i)s′(i)t)=f(U(i)s(i−1)t+W(i)st−1)=f(U′(i)s′(i−1)t+W′(i)s′t+1)=f(U(1)xt+W(1)st−1)=f(U′(1)xt+W′(1)s′t+1)(6)(7)(8)(9)(10)(11)
循環神經網絡的訓練
循環神經網絡的訓練算法:BPTT
BPTT算法是針對循環層的訓練算法,基本原理和BP算法一樣,包含三個步驟:
前向計算每個神經元的輸出值;
反向計算每個神經元的誤差項δj 值,它是誤差函數E對神經元j的加權輸入netj 的偏導數;
計算每個權重的梯度。
最後再用隨機梯度下降算法更新權重。
循環層如下圖所示:
1. 前向計算
使用式2對循環層進行前向計算:
st=f(Uxt+Wst−1)
上式中,
st 、
xt 、
st−1 都是向量,U、V是矩陣,向量的下標表示時刻。
2. 誤差項的計算
BTPP算法將第l 層的t時刻的誤差項δlt 值沿兩個方向傳播,一個方向是傳遞到上一層網絡,得到δl−1t 值,這部分只與U有關;另一方向是沿時間線傳遞到初始t1 時刻,得到δl1 值,這部分只與W有關。
我們用向量nett 表示神經元在t時刻的加權輸入,因爲:
nettst−1=Uxt+Wst−1=f(nett−1)(12)(13)
因此(詳細推導此處略過,詳情見鏈接):
∂nett∂nett−1=∂nett∂st−1∂st−1∂nett−1=Wdiag[f′(nett−1)]=⎡⎣⎢⎢⎢⎢⎢⎢w11f′(nett−11)w21f′(nett−11)wn1f′(nett−11)w12f′(nett−12)w22f′(nett−12)..wn2f′(nett−12).........w1nf(nett−1n)w2nf(nett−1n)wnnf′(nett−1n)⎤⎦⎥⎥⎥⎥⎥⎥(14)(15)(16)
上式描述了將δ沿時間往前傳遞一個時刻的規律,根據這個規律,可以求得任意時刻k的誤差項
δk :
δTk=====∂E∂netk∂E∂nett∂nett∂netk∂E∂nett∂nett∂nett−1∂nett−1∂nett−2...∂netk+1∂netkWdiag[f′(nett−1)]Wdiag[f′(nett−2)]...Wdiag[f′(netk)]δltδTt∏i=kt−1Wdiag[f′(neti)](式3)(17)(18)(19)(20)(21)
式3是將誤差項沿時間反向傳播的算法。
循環層將誤差項反向傳遞到上一層網絡,與普通的全連接層完全一樣。
(δl−1t)T===∂E∂netl−1t∂E∂netlt∂netlt∂netl−1t(δlt)TUdiag[f′l−1(netl−1t)](式4)(22)(23)(24)
式4就是將誤差項傳遞到上一層的算法。
3. 權重梯度的計算
首先,我們計算誤差函數E對權重矩陣W的梯度∂E∂W .
上圖展示了前兩步已經計算得到的值,包括每個時刻t循環層的輸出值st 以及誤差項δt 。
梯度計算算法:只要知道了任意一個時刻的誤差項δt ,以及上一個時刻循環層的輸出值st−1 ,就可以按照下面的公式求出權重矩陣在t時刻的梯度∇WtE :
∇WtE=⎡⎣⎢⎢⎢⎢⎢⎢δt1st−11δt2st−11..δtnst−11δt1st−12δt2st−12δtnst−12.........δt1st−1nδt2st−1nδtnst−1n⎤⎦⎥⎥⎥⎥⎥⎥(式5)
我們求得了權重矩陣W在t時刻的梯度
∇WtE ,最終的梯度
∇WE 是各個時刻的梯度
之和(至於爲什麼是“和”,詳細推導見鏈接):
∇WE==∑i=1t∇WiE⎡⎣⎢⎢⎢⎢⎢⎢δt1st−11δt2st−11..δtnst−11δt1st−12δt2st−12δtnst−12.........δt1st−1nδt2st−1nδtnst−1n⎤⎦⎥⎥⎥⎥⎥⎥+...+⎡⎣⎢⎢⎢⎢⎢⎢δ11s01δ12s01..δ1ns01δ11s02δ12s02δ1ns02.........δ11s0nδ12s0nδ1ns0n⎤⎦⎥⎥⎥⎥⎥⎥(式6)(25)(26)
式6就是計算循環層權重矩陣W的梯度的公式。
RNN的梯度爆炸和消失問題
不幸的是,前面提到的幾種RNNs都不能很好的處理較長的序列。原因是RNN在訓練中很容易發生梯度爆炸和梯度消失,這導致訓練梯度不能在較長序列中一直傳遞下去,從而使RNN無法捕捉到長距離的影響。(具體原因見鏈接)
處理梯度爆炸:設置一個梯度閾值,當梯度超過這個閾值時可以直接截取。
處理梯度消失:
合理的初始化權重值。初始化權重,使每個神經元儘可能不要取極大值或極小值,以躲開梯度消失的區域。
使用ReLU代替Sigmoid和tanh作爲激活函數。
使用其他結構的RNNs,如長短時記憶網絡(LTSM)和Gated Recurrent Unit(GRU)。