RNN 本身就是一個深度類神經網路,而原因在於它的架構中可捕捉序列資料間的相依和連續性。因為 RNN 是一個深層類神經網路,自然也有許多深度網路會遭遇的訓練問題,而最主要的問題,則是使用梯度最佳化演算法時,常遭遇的 vanishing gradient 或 exploding gradient 問題。
Vanishing gradient 和 exploding gradient 問題是源自於當類神經網路的架構增加,上層的誤差梯度無法傳遞到下層來更新所有的權重參數。Exploding gradient,是當誤差的 gradient 是一個相當大的數值,再經過 chain rule 往下層傳遞時,不斷乘上相當大的數值,造成一個發散的結果梯度值,因為超過處理器的浮點數精度可以容納的數值範圍,而造成軟體回傳 NaN 的情況。
相反的,vanishing gradient 則是與 exploding gradient 相反的狀況,指的是誤差梯度在上層的網路中為零的狀態,而造成梯度消失的問題。
這兩個問題在 RNN 的架構更為嚴重,其原因在於許多的序列資料都仰賴長距離的依賴關係,如以下的例子所解釋:
Exploding gradient 可以用 gradient clipping 的方式,把 gradient 限制在一固定的數值範圍內。而 vanishing gradient 則需要靠不同的技巧來解決。在 RNN 中則是利用一種特別的單元來控制流進或流出的資訊。這個單元被稱為 Long-Short Term Memory Unit(LSTM)。這個單元還有個簡易版的版本,也經常地在 RNN 的架構中使用,而被稱為 Gated Recurrent Unit(GRU)。
為了解釋這些特殊 RNN 單元的構造,我們需要先將之前繪製的 RNN 架構放大來看,下面就是一個標準的 RNN 單元的結構,可以對照著公式來看。
一個標準的 RNN 單元,代表了一個序列中的位置,而其架構包含了一個該位置的輸入單元,x<t>,一個代表該位置的狀態單元,a<t>,和一個輸出單元,y<t>。
其中該位置的狀態單元是由該位置的輸入單元和前一位置的狀態單元計算出來。而該位置輸出單元,並非由該位置的輸入單元直接計算,而是由該位置的狀態單元所計算出來,方能捕捉序列的相依性。
而 LSTM 和 GRU 單元與標準的 RNN 單元最大的不同,則是多了一個 memory cell。這個 memory cell 負責記憶流入當下位置的資訊。另外,在這個 cell 單元外有不同的閘門,就如電器的開關一樣,各自負責有多少的資訊可以流入或流出 memory cell 中。
大致以敘述抽象的方式瞭解了 memory cell 的架構後,接著我們先以簡化版的 LSTM RNN 單元,也就是 GRU 單元來解說:
在課程中,GRU 單元又分成兩個版本,一個是僅有一閘門,這個閘門被稱呼為更新閘門,在下圖的投影片截圖中以 來表示,其作用是用來控制在後續的序列輸入中,是否要更新 memory cell 所記憶的內容。
另外一個較為複雜的 GRU 則是具有兩個閘門,除了最簡單的更新閘門結構,多了一個相關閘門。這個相關閘門在下圖中則以 來表示。這個閘門主要是控制,過去累積的 memory cell 資訊該有多少流入目前序列位置中的 memory cell。
這類的閘門,就和一個 neural network layer 一樣,先對輸入做線性轉換,最後再以非線性的函式來輸出。在此 sigmoid 函式是最常見的非線性函式選擇,因為這個函式會將位於兩端極值的輸入(這在處理長序列的 RNN 是常見的),以 0 或 1 輸出,就如閘門開關一樣,通常都處於 on 和 off 的兩種狀態。
有了閘門的概念後,接下來我們需要來看看 memory cell 的架構。在 GRU 中,這個 memory cell 的輸出,c<t>,將會替換在原本的 RNN 單元中計算狀態單元輸出,a<t>的部份。以下,我們稱呼 memory cell 的輸出為記憶狀態輸出。
而關於 memory cell 如何計算其輸出,首先使用一個新的變數,稱為候選記憶狀態輸出,在GRU 的圖示中,以 表示。而候選記憶狀態輸出,則和標準 RNN 單元中狀態單元輸出的計算方式相同,只是把狀態單元輸出都替換成記憶狀態輸出。
其次,則加入了新的運算元,來計算記憶狀態的輸出。這個新的運算元會用前所述的更新閘門作為權重,將目前輸入資訊的候選記憶狀態輸出和前一位置的記憶狀態輸出,c<t-1>,做線性相加。換句話說,候選記憶狀態與前一位置的記憶狀態輸出,如何貢獻於當前位置的記憶狀態輸出,則由更新閘門控制。
而這些架構倒底是怎麼作用的呢?我們可以用課程的例子來說明:
可以看到在最下面的例句中:“The cat, which already ate ......was full”。在訓練良好的 GRU RNN 網路,會記憶主詞 cat,且不會更新直到相依動詞出現。而完整的 GRU 架構,也就是多了另外一個相關閘門的架構,則可見下圖:
可以從公式中看到,相關閘門的功用在於控制前一位置的記憶狀態輸出的對候選記憶狀態輸出的貢獻。
而 LSTM 單元,雖然在文獻中比 GRU 出現的早,但在結構上卻比 GRU 複雜得多。首先,在 GRU 中將狀態輸出以記憶狀態輸出替換的部分還原。可由 LSTM 的圖解中看到,原本在 GRU 中一個管線的部分,在 LSTM 則保留了原先在標準 RNN 單元的線路,另外增加了 memory cell 的線路,而呈現兩個管線的架構。在某些文獻中,會將在標準 RNN 單元裡的狀態單元線路,成為短期記憶線路,而新增的memory cell 的線路,則為長期記憶線路。
在 LSTM 中,使用了三個不同的閘門,除了也在 GRU 中使用的更新閘門,然而在計算 memory cell 的輸出上,則另外使用了遺忘閘門,在圖中投影片的部分則以 來表示。可以看到在 GRU 中僅有一個自由參數的記憶狀態輸出,現在則為兩個自由參數來控制。藉由使用兩個自由參數來控制,可以避免 GRU 中,若更新閘門的輸出值較大,而相對抑制了前一位置的記憶狀態輸出的貢獻。
另外一個閘門則是針對狀態輸出,a<t>,在狀態輸出中,原先利用現在位置的輸入和前一位置的狀態輸出,a<t-1>來決定輸出的數值,現在則利用一個輸出閘門,以 記憶狀態輸出,c<t>,來決定狀態輸出的數值。