【theano-windows】学习笔记二十——LSTM理论及实现
前言
上一篇學習了RNN,也知道了在沿著時間線對上下文權重求梯度的時候,可能會導致梯度消失或者梯度爆炸,然后我們就得學習一波比較常見的優化方法之LSTM
國際慣例,參考網址:
LSTM Networks for Sentiment Analysis
Understanding LSTM Networks
簡介
傳統的循環神經網絡RNN在梯度反傳階段,梯度信號經常被上下文連接權重矩陣乘很多次(與時間戳的數目一直),這就意味著轉移矩陣的權重大小對學習過程有很大的影響。
如果權重很小(權重矩陣的最大特征值小于1),就會導致梯度消失,梯度信號變得很小,學習就會變得很慢或者停止學習了。這使得對具有長時依賴數據的學習變得困難。反之,如果權重很大(權重值大于1),就會導致梯度信號很大,造成學習發散,這通常稱為梯度爆炸。
LSTM模型主要就是引入了記憶單元來減輕這些問題,一個記憶單元包含四個主要成分:輸入門,自連接,遺忘門,輸出門。自連接權重是1,不受任何外部干擾,記憶單元的狀態從一個時間戳到另一個時間戳保持常量。門是為了模擬記憶單元間自身與環境的交互。輸入門允許輸入信改變記憶單元的狀態或者阻止它。輸出門允許記憶單元的狀態影響到其它單元或者是組織它。遺忘門模擬記憶單元自身的循環連接,允許單元記住或者忘記之前的狀態。
理論
下圖對比的是傳統RNN與具有記憶單元的LSTM的拓撲結構:
可以發現LSTM與RNN的區別在于后者多了一條線,上行線是記憶信息按時間傳遞,下行線是與RNN相同的隱層信息按時間傳遞。
這個記憶細胞的連接看著挺復雜的,雖然暫時看到記住了,但是過段時間肯定忘記,這個得理解性記憶,看看每一部分都代表什么吧,看樣子這個記憶單元主要包含三個連接部分,如下圖紅圈所示:
接下來就對這些紅圈分別理解,接下來的博文是對第二篇參考博客的翻譯與理解,看原文請直接戳前言。
第一部分
ft=σ(Wfxt+Ufht?1+bf)ft=σ(Wfxt+Ufht?1+bf)
決定即將通過記憶單元的信息是什么,通過一個由sigmoid層構成的遺忘門決定,此門接收的輸入包含原始數據的輸入與上一時刻的隱狀態,計算結果即:
比如語言建模中,想基于之前所有的狀態預測下一個詞,記憶狀態可能包括主語的性別,這樣才能使用正確的代詞(他/她),當新的主語出現,我們可能要忘記之前的主語性別。第二部分
it=σ(Wixt+Uiht?1+bi)it=σ(Wixt+Uiht?1+bi)
決定什么信息可以被存儲在記憶單元中,分為兩個部分:
①一個sigmoid層稱為輸入門決定將更新什么值;
②tanh層計算新的候選值向量Ct^Ct^,這個值可以被加到狀態中。下一步就是將這兩個值結合起來更新狀態
Ct^=tanh(Wcxt+Ucht?1+bc)Ct^=tanh?(Wcxt+Ucht?1+bc)
如果按照語言建模的例子,這部分做的就是,我們想將新的主語性別加入到單元狀態中,去替代想忘記的舊的主語的性別。結合第一部分和第二部分
Ct=it?Ct^+ft×Ct?1Ct=it?Ct^+ft×Ct?1
我們已經計算了想傳遞什么,以及是否去忘記它,怎么去更新狀態。
假設舊的記憶狀態是Ct?1Ct?1,想要更新到CtCt,之前我們已經計算了去做什么,現在我們只需要做它就行了,方法就是將ftft與舊狀態相乘即可忘記那些早想忘記的事情。
之后將it×Ct^it×Ct^加進去,這是新的候選值,并且依據對于每個狀態我們所決定的更新量去縮放它。
這就相當于在語言模型中,我們確實丟失了舊主語的性別信息,并且新增了我們在上一步已經決定添加的新信息。第三部分
otht=σ(Woxt+Uoht?1+bo)=ot×tanh(Ct)ot=σ(Woxt+Uoht?1+bo)ht=ot×tanh?(Ct)
最后就是決定我們要輸出啥。這個輸出單元狀態,但是需要被過濾一下。首先使用sigmoid決定哪一部分單元狀態需要被輸出,然后將單元狀態通過tanh(將值歸一化到-1至1),使用sigmoid遺忘門的輸出乘以它,因此就僅僅會輸出我們想要的那部分。
還是語言建模的例子,一旦見到一個主語,就想輸出相關的動詞相關的信息,比如是單數還是復數,這樣我們可以知道所連接 的動詞形式。
總結一波,假如面試的時候,面試官讓你畫LSTM的結構圖,怎么下手?
①首先一個框,豎著兩條線分別代表輸入輸出,再橫著兩條線,一條是隱層的自連接,一條是記憶單元的信息傳遞。就相當于先畫個RNN,然后橫著添一條記憶線就行。
②畫第一個單元:決定需要傳遞的信息,連接輸入和隱層,使用sigmoid激活
③畫第二個單元:更新記憶單元狀態,連接輸入和隱層,分別使用sigmoid和tanh激活
④連接第一二個單元:第一個單元的輸出與歷史細胞狀態做乘積,第二個單元的sigmoid和tanh做乘積,然后與前一個單元做加和
⑤畫第三個單元:確定輸出,依舊是連接輸入和隱層,使用sigmoid激活得到otot,將第一二部分更新的狀態值使用tanh歸一化一下與otot相乘即可得到隱層輸出。
其實整個流程就是:決定更新啥,更新狀態,確定輸出。
實例
主要有官方提供的兩個實例以及自己修改的將LSTM套入到上一篇RNN博客的序列預測中。官方實例戳這里,基本無需配置,下載那幾個文件就能用了,文末我也會放網盤。
另一個實例是我自己將上一篇RNN的博客中代碼替換成LSTM的理論進行序列預測,原始的Elman-RNN的循環代碼如下:
def step(x_t,h_tm1):h_t=self.activation(T.dot(x_t,self.W_in)+ T.dot(h_tm1,self.W)+self.bh)y_t=T.dot(h_t,self.W_out)+self.byreturn h_t,y_t [self.h,self.y_pred],_=theano.scan(step,sequences=self.input,outputs_info=[self.h0,None])改成LSTM就是:
#針對LSTM對RNN做相關改進def step(x_t,h_tm1,C_tm1):preact=T.dot(x_t,self.W_in)+ T.dot(h_tm1,self.W)+self.bhf_t=T.nnet.sigmoid(preact)i_t=T.nnet.sigmoid(preact)hatC_t=T.tanh(preact)C_t=i_t*hatC_t+f_t*C_tm1 o_t=T.nnet.sigmoid(preact)h_t=o_t*T.tanh(C_t)y_t=T.dot(h_t,self.W_out)+self.byreturn h_t,C_t,y_t [self.h,self.C_t,self.y_pred],_=theano.scan(step,sequences=self.input,outputs_info=[self.h0,self.C0,None])但是比較奇怪的是,實驗效果竟然比RNN差點,不知道為什么,難道還要改其它地方?或者此處改的有問題,python渣躲墻角持續檢查代碼.png
后記
沒啥說的,貼代碼吧:
官方代碼鏈接:https://pan.baidu.com/s/1cxTyVWBVM9L3iuGz_OkLZQ 密碼:ntp0
本博文代碼:鏈接:https://pan.baidu.com/s/1IBy8ue8lT3cjXOEnQUf_8Q 密碼:k0zw
總結
以上是生活随笔為你收集整理的【theano-windows】学习笔记二十——LSTM理论及实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网易吃鸭手游《风云岛行动》2.14不删档
- 下一篇: 第五人格冒险家皮肤大全 冒险家哪个皮肤好