RNN以及LSTM簡介

轉載地址

https://blog.csdn.net/zhaojc1995/article/details/80572098

本文部分參考和摘錄了以下文章,在此由衷感謝以下作者的分享!
https://zhuanlan.zhihu.com/p/28054589
https://blog.csdn.net/qq_16234613/article/details/79476763
http://www.cnblogs.com/pinard/p/6509630.html
https://zhuanlan.zhihu.com/p/28687529
http://www.cnblogs.com/pinard/p/6509630.html
https://zhuanlan.zhihu.com/p/26892413
https://zhuanlan.zhihu.com/p/21462488?refer=intelligentunit


RNN(Recurrent Neural Network)是一類用於處理序列數據的神經網絡。首先我們要明確什麼是序列數據,摘取百度百科詞條:時間序列數據是指在不同時間點上收集到的數據,這類數據反映了某一事物、現象等隨時間的變化狀態或程度。這是時間序列數據的定義,當然這裏也可以不是時間,比如文字序列,但總歸序列數據有一個特點——後面的數據跟前面的數據有關係。

RNN的結構及變體

我們從基礎的神經網絡中知道,神經網絡包含輸入層、隱層、輸出層,通過激活函數控制輸出,層與層之間通過權值連接。激活函數是事先確定好的,那麼神經網絡模型通過訓練“學“到的東西就蘊含在“權值“中。
基礎的神經網絡只在層與層之間建立了權連接,RNN最大的不同之處就是在層之間的神經元之間也建立的權連接。如圖。
這裏寫圖片描述

這是一個標準的RNN結構圖,圖中每個箭頭代表做一次變換,也就是說箭頭連接帶有權值。左側是摺疊起來的樣子,右側是展開的樣子,左側中h旁邊的箭頭代表此結構中的“循環“體現在隱層。
在展開結構中我們可以觀察到,在標準的RNN結構中,隱層的神經元之間也是帶有權值的。也就是說,隨着序列的不斷推進,前面的隱層將會影響後面的隱層。圖中O代表輸出,y代表樣本給出的確定值,L代表損失函數,我們可以看到,“損失“也是隨着序列的推薦而不斷積累的。
除上述特點之外,標準RNN的還有以下特點:
1、權值共享,圖中的W全是相同的,U和V也一樣。
2、每一個輸入值都只與它本身的那條路線建立權連接,不會和別的神經元連接。

以上是RNN的標準結構,然而在實際中這一種結構並不能解決所有問題,例如我們輸入爲一串文字,輸出爲分類類別,那麼輸出就不需要一個序列,只需要單個輸出。如圖。
這裏寫圖片描述
同樣的,我們有時候還需要單輸入但是輸出爲序列的情況。那麼就可以使用如下結構:
這裏寫圖片描述

還有一種結構是輸入雖是序列,但不隨着序列變化,就可以使用如下結構:
這裏寫圖片描述

原始的N vs N RNN要求序列等長,然而我們遇到的大部分問題序列都是不等長的,如機器翻譯中,源語言和目標語言的句子往往並沒有相同的長度。
下面我們來介紹RNN最重要的一個變種:N vs M。這種結構又叫Encoder-Decoder模型,也可以稱之爲Seq2Seq模型。
這裏寫圖片描述
從名字就能看出,這個結構的原理是先編碼後解碼。左側的RNN用來編碼得到c,拿到c後再用右側的RNN進行解碼。得到c有多種方式,最簡單的方法就是把Encoder的最後一個隱狀態賦值給c,還可以對最後的隱狀態做一個變換得到c,也可以對所有的隱狀態做變換。
這裏寫圖片描述

除了以上這些結構以外RNN還有很多種結構,用於應對不同的需求和解決不同的問題。還想繼續瞭解可以看一下下面這個博客,裏面又介紹了幾種不同的結構。但相同的是循環神經網絡除了擁有神經網絡都有的一些共性元素之外,它總要在一個地方體現出“循環“,而根據“循環“體現方式的不同和輸入輸出的變化就形成了多種RNN結構。

https://blog.csdn.net/qq_16234613/article/details/79476763

標準RNN的前向輸出流程

上面介紹了RNN有很多變種,但其數學推導過程其實都是大同小異。這裏就介紹一下標準結構的RNN的前向傳播過程。
這裏寫圖片描述

再來介紹一下各個符號的含義:x是輸入,h是隱層單元,o爲輸出,L爲損失函數,y爲訓練集的標籤。這些元素右上角帶的t代表t時刻的狀態,其中需要注意的是,因策單元h在t時刻的表現不僅由此刻的輸入決定,還受t時刻之前時刻的影響。V、W、U是權值,同一類型的權連接權值相同。

有了上面的理解,前向傳播算法其實非常簡單,對於t時刻:

h(t)=ϕ(Ux(t)+Wh(t1)+b)h(t)=ϕ(Ux(t)+Wh(t−1)+b)

其中ϕ()ϕ()爲激活函數,一般來說會選擇tanh函數,b爲偏置。

t時刻的輸出就更爲簡單:

o(t)=Vh(t)+co(t)=Vh(t)+c

最終模型的預測輸出爲:

yˆ(t)=σ(o(t))y^(t)=σ(o(t))

其中σσ爲激活函數,通常RNN用於分類,故這裏一般用softmax函數。

RNN的訓練方法——BPTT

BPTT(back-propagation through time)算法是常用的訓練RNN的方法,其實本質還是BP算法,只不過RNN處理時間序列數據,所以要基於時間反向傳播,故叫隨時間反向傳播。BPTT的中心思想和BP算法相同,沿着需要優化的參數的負梯度方向不斷尋找更優的點直至收斂。綜上所述,BPTT算法本質還是BP算法,BP算法本質還是梯度下降法,那麼求各個參數的梯度便成了此算法的核心。
這裏寫圖片描述

再次拿出這個結構圖觀察,需要尋優的參數有三個,分別是U、V、W。與BP算法不同的是,其中W和U兩個參數的尋優過程需要追溯之前的歷史數據,參數V相對簡單隻需關注目前,那麼我們就來先求解參數V的偏導數。

L(t)V=L(t)o(t)o(t)V∂L(t)∂V=∂L(t)∂o(t)⋅∂o(t)∂V

這個式子看起來簡單但是求解起來很容易出錯,因爲其中嵌套着激活函數函數,是複合函數的求道過程。

RNN的損失也是會隨着時間累加的,所以不能只求t時刻的偏導。

L=t=1nL(t)L=∑t=1nL(t)
LV=t=1nL(t)o(t)o(t)V∂L∂V=∑t=1n∂L(t)∂o(t)⋅∂o(t)∂V

W和U的偏導的求解由於需要涉及到歷史數據,其偏導求起來相對複雜,我們先假設只有三個時刻,那麼在第三個時刻 L對W的偏導數爲:

L(3)W=L(3)o(3)o(3)h(3)h(3)W+L(3)o(3)o(3)h(3)h(3)h(2)h(2)W+L(3)o(3)o(3)h(3)h(3)h(2)h(2)h(1)h(1)W∂L(3)∂W=∂L(3)∂o(3)∂o(3)∂h(3)∂h(3)∂W+∂L(3)∂o(3)∂o(3)∂h(3)∂h(3)∂h(2)∂h(2)∂W+∂L(3)∂o(3)∂o(3)∂h(3)∂h(3)∂h(2)∂h(2)∂h(1)∂h(1)∂W

相應的,L在第三個時刻對U的偏導數爲:
L(3)U=L(3)o(3)o(3)h(3)h(3)U+L(3)o(3)o(3)h(3)h(3)h(2)h(2)U+L(3)o(3)o(3)h(3)h(3)h(2)h(2)h(1)h(1)U∂L(3)∂U=∂L(3)∂o(3)∂o(3)∂h(3)∂h(3)∂U+∂L(3)∂o(3)∂o(3)∂h(3)∂h(3)∂h(2)∂h(2)∂U+∂L(3)∂o(3)∂o(3)∂h(3)∂h(3)∂h(2)∂h(2)∂h(1)∂h(1)∂U

可以觀察到,在某個時刻的對W或是U的偏導數,需要追溯這個時刻之前所有時刻的信息,這還僅僅是一個時刻的偏導數,上面說過損失也是會累加的,那麼整個損失函數對W和U的偏導數將會非常繁瑣。雖然如此但好在規律還是有跡可循,我們根據上面兩個式子可以寫出L在t時刻對W和U偏導數的通式:

L(t)W=k=0tL(t)o(t)o(t)h(t)(j=k+1th(j)h(j1))h(k)W∂L(t)∂W=∑k=0t∂L(t)∂o(t)∂o(t)∂h(t)(∏j=k+1t∂h(j)∂h(j−1))∂h(k)∂W
L(t)U=k=0tL(t)o(t)o(t)h(t)(j=k+1th(j)h(j1))h(k)U∂L(t)∂U=∑k=0t∂L(t)∂o(t)∂o(t)∂h(t)(∏j=k+1t∂h(j)∂h(j−1))∂h(k)∂U

整體的偏導公式就是將其按時刻再一一加起來。

前面說過激活函數是嵌套在裏面的,如果我們把激活函數放進去,拿出中間累乘的那部分:

j=k+1thjhj1=j=k+1ttanhWs∏j=k+1t∂hj∂hj−1=∏j=k+1ttanh′⋅Ws
或是
j=k+1thjhj1=j=k+1tsigmoidWs∏j=k+1t∂hj∂hj−1=∏j=k+1tsigmoid′⋅Ws

我們會發現累乘會導致激活函數導數的累乘,進而會導致“梯度消失“和“梯度爆炸“現象的發生。

至於爲什麼,我們先來看看這兩個激活函數的圖像。
這是sigmoid函數的函數圖和導數圖。
這裏寫圖片描述
這是tanh函數的函數圖和導數圖。
這裏寫圖片描述
它們二者是何其的相似,都把輸出壓縮在了一個範圍之內。他們的導數圖像也非常相近,我們可以從中觀察到,sigmoid函數的導數範圍是(0,0.25],tach函數的導數範圍是(0,1],他們的導數最大都不大於1。

這就會導致一個問題,在上面式子累乘的過程中,如果取sigmoid函數作爲激活函數的話,那麼必然是一堆小數在做乘法,結果就是越乘越小。隨着時間序列的不斷深入,小數的累乘就會導致梯度越來越小直到接近於0,這就是“梯度消失“現象。其實RNN的時間序列與深層神經網絡很像,在較爲深層的神經網絡中使用sigmoid函數做激活函數也會導致反向傳播時梯度消失,梯度消失就意味消失那一層的參數再也不更新,那麼那一層隱層就變成了單純的映射層,毫無意義了,所以在深層神經網絡中,有時候多加神經元數量可能會比多家深度好。

你可能會提出異議,RNN明明與深層神經網絡不同,RNN的參數都是共享的,而且某時刻的梯度是此時刻和之前時刻的累加,即使傳不到最深處那淺層也是有梯度的。這當然是對的,但如果我們根據有限層的梯度來更新更多層的共享的參數一定會出現問題的,因爲將有限的信息來作爲尋優根據必定不會找到所有信息的最優解。

之前說過我們多用tanh函數作爲激活函數,那tanh函數的導數最大也才1啊,而且又不可能所有值都取到1,那相當於還是一堆小數在累乘,還是會出現“梯度消失“,那爲什麼還要用它做激活函數呢?原因是tanh函數相對於sigmoid函數來說梯度較大,收斂速度更快且引起梯度消失更慢。

還有一個原因是sigmoid函數還有一個缺點,Sigmoid函數輸出不是零中心對稱。sigmoid的輸出均大於0,這就使得輸出不是0均值,稱爲偏移現象,這將導致後一層的神經元將上一層輸出的非0均值的信號作爲輸入。關於原點對稱的輸入和中心對稱的輸出,網絡會收斂地更好。

RNN的特點本來就是能“追根溯源“利用歷史數據,現在告訴我可利用的歷史數據竟然是有限的,這就令人非常難受,解決“梯度消失“是非常必要的。解決“梯度消失“的方法主要有:
1、選取更好的激活函數
2、改變傳播結構

關於第一點,一般選用ReLU函數作爲激活函數,ReLU函數的圖像爲:
這裏寫圖片描述
ReLU函數的左側導數爲0,右側導數恆爲1,這就避免了“梯度消失“的發生。但恆爲1的導數容易導致“梯度爆炸“,但設定合適的閾值可以解決這個問題。還有一點就是如果左側橫爲0的導數有可能導致把神經元學死,不過設置合適的步長(學習旅)也可以有效避免這個問題的發生。

關於第二點,LSTM結構可以解決這個問題。

總結一下,sigmoid函數的缺點:
1、導數值範圍爲(0,0.25],反向傳播時會導致“梯度消失“。tanh函數導數值範圍更大,相對好一點。
2、sigmoid函數不是0中心對稱,tanh函數是,可以使網絡收斂的更好。


LSTM

下面來了解一下LSTM(long short-term memory)。長短期記憶網絡是RNN的一種變體,RNN由於梯度消失的原因只能有短期記憶,LSTM網絡通過精妙的門控制將短期記憶與長期記憶結合起來,並且一定程度上解決了梯度消失的問題。
由於已經存在了一篇寫得非常好的博客,我在這裏就直接轉載過來,再在其中夾雜點自己的理解。原文連接如下。

作者:朱小虎Neil 鏈接:https://www.jianshu.com/p/9dc9f41f0b29 來源:簡書

在此感謝原作者!

長期依賴(Long-Term Dependencies)問題

RNN 的關鍵點之一就是他們可以用來連接先前的信息到當前的任務上,例如使用過去的視頻段來推測對當前段的理解。如果 RNN 可以做到這個,他們就變得非常有用。但是真的可以麼?答案是,還有很多依賴因素。

有時候,我們僅僅需要知道先前的信息來執行當前的任務。例如,我們有一個語言模型用來基於先前的詞來預測下一個詞。如果我們試着預測 “the clouds are in the sky” 最後的詞,我們並不需要任何其他的上下文 —— 因此下一個詞很顯然就應該是 sky。在這樣的場景中,相關的信息和預測的詞位置之間的間隔是非常小的,RNN 可以學會使用先前的信息。

這裏寫圖片描述

不太長的相關信息和位置間隔

但是同樣會有一些更加複雜的場景。假設我們試着去預測“I grew up in France… I speak fluent French”最後的詞。當前的信息建議下一個詞可能是一種語言的名字,但是如果我們需要弄清楚是什麼語言,我們是需要先前提到的離當前位置很遠的 France 的上下文的。這說明相關信息和當前預測位置之間的間隔就肯定變得相當的大。

不幸的是,在這個間隔不斷增大時,RNN 會喪失學習到連接如此遠的信息的能力。
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章