編輯 | 安可
出品 | 磐創(chuàng)AI技術(shù)團隊
目錄:
前言
RNN知識結(jié)構(gòu)
簡單循環(huán)神經(jīng)網(wǎng)絡(luò)
RNN的基本結(jié)構(gòu)
RNN的運算過程和參數(shù)更新
RNN的前向運算
RNN的參數(shù)更新
一.前言
前饋神經(jīng)網(wǎng)絡(luò)不考慮數(shù)據(jù)之間的關(guān)聯(lián)性,網(wǎng)絡(luò)的輸出只和當(dāng)前時刻網(wǎng)絡(luò)的輸入相關(guān)。然而在解決很多實際問題的時候我們發(fā)現(xiàn),現(xiàn)實問題中存在著很多序列型的數(shù)據(jù),例如文本、語音以及視頻等。這些序列型的數(shù)據(jù)往往都是具有時序上的關(guān)聯(lián)性的,既某一時刻網(wǎng)絡(luò)的輸出除了與當(dāng)前時刻的輸入相關(guān)之外,還與之前某一時刻或某幾個時刻的輸出相關(guān)。而前饋神經(jīng)網(wǎng)絡(luò)并不能處理好這種關(guān)聯(lián)性,因為它沒有記憶能力,所以前面時刻的輸出不能傳遞到后面的時刻。
此外,我們在做語音識別或機器翻譯的時候,輸入和輸出的數(shù)據(jù)都是不定長的,而前饋神經(jīng)網(wǎng)絡(luò)的輸入和輸出的數(shù)據(jù)格式都是固定的,無法改變。因此,需要有一種能力更強的模型來解決這些問題。
在過去的幾年里,循環(huán)神經(jīng)網(wǎng)絡(luò)的實力已經(jīng)得到了很好的證明,在許多序列問題中,例如文本處理、語音識別以及機器翻譯等,循環(huán)神經(jīng)網(wǎng)絡(luò)都取得了顯著的成績。循環(huán)神經(jīng)網(wǎng)絡(luò)也正被越來越多的應(yīng)用到其它領(lǐng)域。
二. RNN知識結(jié)構(gòu)
在本章中,我們將會從最簡單的循環(huán)神經(jīng)網(wǎng)絡(luò)開始介紹,通過實例掌握循環(huán)神經(jīng)網(wǎng)絡(luò)是如何解決序列化數(shù)據(jù)的,以及循環(huán)神經(jīng)網(wǎng)絡(luò)前向計算和參數(shù)優(yōu)化的過程及方法。在此基礎(chǔ)上我們會介紹幾種循環(huán)神經(jīng)網(wǎng)絡(luò)的常用結(jié)構(gòu),既雙向循環(huán)神經(jīng)網(wǎng)絡(luò)、深度循環(huán)神經(jīng)網(wǎng)絡(luò)以及遞歸神經(jīng)網(wǎng)絡(luò)。我們會使用TensorFlow實現(xiàn)循環(huán)神經(jīng)網(wǎng)絡(luò),掌握使用TensorFlow搭建簡單循環(huán)神經(jīng)網(wǎng)絡(luò)的方法。
此外,我們還會學(xué)習(xí)一類結(jié)構(gòu)更為復(fù)雜的循環(huán)神經(jīng)網(wǎng)絡(luò)——門控循環(huán)神經(jīng)網(wǎng)絡(luò),包括長短期記憶網(wǎng)絡(luò)(LSTM)和門控制循環(huán)單元(GRU),這也是目前最常使用的兩種循環(huán)神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。最后我們還會介紹一種注意力模型:Attention-basedmodel,這是近兩年來的研究熱點。在下一章的項目實戰(zhàn)中,我們會使用到Attention-basedmodel以及前面提到的LSTM等模型解決一些實際的問題。
本章內(nèi)容結(jié)構(gòu)如下:
圖1 本章內(nèi)容結(jié)構(gòu)
三. 簡單循環(huán)神經(jīng)網(wǎng)絡(luò)
簡單循環(huán)網(wǎng)絡(luò)(simple recurrent networks,簡稱SRN)又稱為Elman network,是由Jeff Elman在1990年提出來的。Elman在Jordan network(1986)的基礎(chǔ)上進(jìn)行了創(chuàng)新,并且簡化了它的結(jié)構(gòu),最終提出了Elman network。Jordan network和Elman network的網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示。
圖2 Jordan network(左)和Elman network(右)
圖片引用自ResearchGate:https://www.researchgate.net/figure/A-recurrent-neural-network-as-proposed-by-Jordan-1986_fig5_277603865
從圖2中可以很直觀的看出,兩種網(wǎng)絡(luò)結(jié)構(gòu)最主要的區(qū)別在于記憶單元中保存的內(nèi)容不同。Jordan network的記憶單元中保存的是整個網(wǎng)絡(luò)最終的輸出,而Elmannetwork的記憶單元只保存中間的循環(huán)層,所以如果是基于Elman network的深層循環(huán)神經(jīng)網(wǎng)絡(luò),那么每一個循環(huán)的中間層都會有一個相應(yīng)的記憶單元。有興趣深究的讀者可以查閱Elman和Jordan的論文:https://crl.ucsd.edu/~elman/Papers/fsit.pdf,http://cseweb.ucsd.edu/~gary/PAPER-SUGGESTIONS/Jordan-TR-8604.pdf。
Jordan network和Elman network都可以擴展應(yīng)用到深度學(xué)習(xí)中來,但由于Elman network的結(jié)構(gòu)更易于擴展(Elman network的每一個循環(huán)層都是相互獨立的,因此網(wǎng)絡(luò)結(jié)構(gòu)的設(shè)計可以更加靈活。另外,當(dāng)Jordan network的輸出層與循環(huán)層的維度不一致時還需要額外的調(diào)整,而Elmannetwork則不存在該問題。),因此當(dāng)前主流的循環(huán)神經(jīng)網(wǎng)絡(luò)都是基于Elman network的,例如我們后面會介紹的LSTM等。所以,通常我們所說的循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN),默認(rèn)指的就是Elman network結(jié)構(gòu)的循環(huán)神經(jīng)網(wǎng)絡(luò)。本書中所提到的循環(huán)神經(jīng)網(wǎng)絡(luò),如果沒有特別注明,均指Elman network結(jié)構(gòu)的循環(huán)神經(jīng)網(wǎng)絡(luò)。
四. RNN的基本結(jié)構(gòu)
循環(huán)神經(jīng)網(wǎng)絡(luò)的基本結(jié)構(gòu)如下圖所示(注意:為了清晰,圖中沒有畫出所有的連接線。):
圖3 循環(huán)神經(jīng)網(wǎng)絡(luò)的基本結(jié)構(gòu)
關(guān)于循環(huán)神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)有很多種不同的圖形化描述,但是其所表達(dá)的含義都與圖1一致。將循環(huán)神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)與一般的全連接神經(jīng)網(wǎng)絡(luò)比較,我們會發(fā)現(xiàn)循環(huán)神經(jīng)網(wǎng)絡(luò)只是多了一個記憶單元,而這個記憶單元就是循環(huán)神經(jīng)網(wǎng)絡(luò)的關(guān)鍵所在。
從圖3我們可以看到,循環(huán)神經(jīng)網(wǎng)絡(luò)的記憶單元會保存時刻時循環(huán)層(既圖3中的隱藏層)的狀態(tài)
圖4所示,左邊部分是一個簡化的循環(huán)神經(jīng)網(wǎng)絡(luò)示意圖,右邊部分是將整個網(wǎng)絡(luò)按時間展開后的效果。在左邊部分中,x是神經(jīng)網(wǎng)絡(luò)的輸入,U是輸入層到隱藏層之間的權(quán)重矩陣,W是記憶單元到隱藏層之間的權(quán)重矩陣,V是隱藏層到輸出層之間的權(quán)重矩陣,s是隱藏層的輸出,同時也是要保存到記憶單元中,并與下一時刻的x一起作為輸入,o是神經(jīng)網(wǎng)絡(luò)的輸出。
從右邊的展開部分可以更清楚的看到,RNN每個時刻隱藏層的輸出都會傳遞給下一時刻,因此每個時刻的網(wǎng)絡(luò)都會保留一定的來自之前時刻的歷史信息,并結(jié)合當(dāng)前時刻的網(wǎng)絡(luò)狀態(tài)一并再傳給下一時刻。
圖4 循環(huán)神經(jīng)網(wǎng)絡(luò)及其按時間展開后的效果圖
圖片來源于Nature
理論上來說,RNN是可以記憶任意長度序列的信息的,即RNN的記憶單元中可以保存此前很長時刻網(wǎng)絡(luò)的狀態(tài),但是在實際的使用中我們發(fā)現(xiàn),RNN的記憶能力總是很有限,它通常只能記住最近幾個時刻的網(wǎng)絡(luò)狀態(tài),在本章的第4節(jié)里,我們會具體討論這個問題。
五. RNN的運算過程和參數(shù)更新
1. RNN的前向運算
在一個全連接的循環(huán)神經(jīng)網(wǎng)絡(luò)中,假設(shè)隱藏層只有一層。在時刻神經(jīng)網(wǎng)絡(luò)接收到一個輸入,則隱藏層的輸出為:
上式中,函數(shù)f(·)是隱藏層的激活函數(shù),在TensorFlow中默認(rèn)是tanh函數(shù)。參數(shù)U和W在前面介紹過,分別是輸入層到隱藏層之間的權(quán)重矩陣和記憶單元到隱藏層之間的權(quán)重矩陣,參數(shù)b1是偏置項。在神經(jīng)網(wǎng)絡(luò)剛開始訓(xùn)練的時候,記憶單元中沒有上一個時刻的網(wǎng)絡(luò)狀態(tài),這時候
在得到隱藏層的輸出后,神經(jīng)網(wǎng)絡(luò)的輸出為:
上式中,函數(shù)g(·)是輸出層的激活函數(shù),當(dāng)我們在做分類問題的時候,函數(shù)g(·)通常選為Softmax函數(shù)。參數(shù)V是隱藏層到輸出層的參數(shù)矩陣,參數(shù)b2是偏置項。
我們先看看TensorFlow源碼中關(guān)于RNN隱藏層部分的計算。這部分代碼在TensorFlow源碼中的位置是:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/python/ops/rnn_cell_impl.py。
在rnn_cell_impl.py文件中定義了一個抽象類RNNCell,其它實現(xiàn)RNN的類都會繼承這個類,例如BasicRNNCell、BasicLSTMCell以及GRUCell等。我們以BasicRNNCell類為例,所有繼承了RNNCell的類都需要實現(xiàn)一個call方法,BasicRNNCell類中的call方法的實現(xiàn)如下:
從上面的TensorFlow源碼里可以看到,TensorFlow隱藏層的計算結(jié)果即是該層的輸出,同時也作為當(dāng)前時刻的狀態(tài),作為下一時刻的輸入。第2、3行的注釋說明了“call”方法的功能:
這里有一個地方需要注意一下,這段代碼在實現(xiàn)
我們有四個矩陣:a、b、c和d:
假設(shè)我們想要計算,則有:
如果我們把矩陣a和b、c和d先分別拼接到一起,得到e和f兩個矩陣:
再來計算,會得到同樣的結(jié)果:
下面我們用一段代碼實現(xiàn)循環(huán)神經(jīng)網(wǎng)絡(luò)中完整的前向計算過程。
上面代碼里所使用的RNN結(jié)構(gòu)如下:
圖5 代碼中使用的RNN網(wǎng)絡(luò)結(jié)構(gòu)
在上面的示例代碼中,我們用了一個如圖5所示的簡單循環(huán)神經(jīng)網(wǎng)絡(luò)。該網(wǎng)絡(luò)結(jié)構(gòu)輸入層有兩個單元,隱藏層有兩個神經(jīng)元,輸出層一個神經(jīng)元,所有的激活函數(shù)均為tanh函數(shù)。在第四行代碼中我們定義了輸入數(shù)據(jù),總共三個time-step,每個time-step處理一個輸入。我們將程序運行過程中各個參數(shù)以及輸入和輸出的值以表格的形式展示如下(讀者可以使用下表的數(shù)據(jù)驗算一遍RNN的前向運算,以加深印象):
2. RNN的參數(shù)更新
循環(huán)神經(jīng)網(wǎng)絡(luò)中參數(shù)的更新主要有兩種方法:隨時間反向傳播(backpropagation through time,BPTT)和實時循環(huán)學(xué)習(xí)(real-time recurrent learning,RTRL)。這兩種算法都是基于梯度下降,不同的是BPTT算法是通過反向傳播的方式來更新梯度,而RTRL算法則是使用前向傳播的方式來更新梯度。目前,在RNN的訓(xùn)練中,BPTT是最常用的參數(shù)更新的算法。
BPTT算法和我們在前饋神經(jīng)網(wǎng)絡(luò)上使用的BP算法本質(zhì)上沒有任何區(qū)別,只是RNN中的參數(shù)存在時間上的共享,因此RNN中的參數(shù)在求梯度的時候,存在沿著時間的反向傳播。所以RNN中參數(shù)的梯度,是按時間展開后各級參數(shù)梯度的總和。
本此介紹了簡單RNN網(wǎng)絡(luò)的構(gòu)造原理,下一篇我們將會以實戰(zhàn)的形式介紹如何用TensorFlow實現(xiàn)RNN。