深度學(xué)習(xí)_循環(huán)神經(jīng)網(wǎng)絡(luò)RNN與LSTM

1. 循環(huán)神經(jīng)網(wǎng)絡(luò)RNN

1) 什么是RNN?

循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)是一種節(jié)點(diǎn)定向連接成環(huán)的人工神經(jīng)網(wǎng)絡(luò)底瓣。具體應(yīng)用有語(yǔ)音識(shí)別,手寫(xiě)識(shí)別,翻譯等.

2) 什么時(shí)候使用RNN丙笋?

FNN(前饋神經(jīng)網(wǎng)絡(luò)谢澈,如BP,CNN等)效果已經(jīng)不錯(cuò)了御板,RNN還需要更大量的計(jì)算锥忿,為什么要用RNN呢?如果訓(xùn)練N次怠肋,每次和每次都沒(méi)什么關(guān)系敬鬓,那就不需要RNN,但如果每個(gè)后一次都可能和前一次訓(xùn)練相關(guān)笙各,比如說(shuō)翻譯:一個(gè)句子里面N個(gè)詞钉答,一個(gè)詞為一次訓(xùn)練(train instance),一個(gè)詞的意思很可能依賴它的上下文杈抢,也就是其前次或后次訓(xùn)練数尿,這個(gè)時(shí)候就需要RNN.

3) RNN與FNN有何不同?


如圖所示惶楼,左邊的是前饋神經(jīng)網(wǎng)絡(luò)右蹦,數(shù)據(jù)按黑箭頭方向從輸入層經(jīng)過(guò)隱藏層流入輸出層,向前流動(dòng)歼捐,因此叫做前饋網(wǎng)絡(luò).右圖中何陆,隱藏層中的數(shù)據(jù)除了傳向輸出層,還和下次輸入一起訓(xùn)練后續(xù)的隱藏層豹储,不再是單向甲献,而是包含了循環(huán),則構(gòu)成了循環(huán)神經(jīng)網(wǎng)絡(luò).下圖是將各個(gè)時(shí)間點(diǎn)畫(huà)在同一圖上颂翼,左邊前饋FNN的展開(kāi)圖晃洒,右邊是RNN的展開(kāi)圖.



簡(jiǎn)單地說(shuō),它只是在隱藏層處加了一個(gè)"循環(huán)"朦乏,但實(shí)際上問(wèn)題沒(méi)這么簡(jiǎn)單.之前說(shuō)過(guò)(詳見(jiàn):深度學(xué)習(xí)_BP神經(jīng)網(wǎng)絡(luò))球及,輸入層向隱藏層傳數(shù)據(jù)時(shí),根據(jù)權(quán)重U計(jì)算(為簡(jiǎn)化說(shuō)明省略偏置)呻疹,隱藏層向輸出層傳數(shù)據(jù)時(shí)吃引,根據(jù)權(quán)重V計(jì)算(之前文檔用字體w1,w2表示),循環(huán)神經(jīng)網(wǎng)絡(luò)又加了參數(shù)W刽锤,用于控制隱藏層的權(quán)重.看起來(lái)好像只是多了一次矩陣乘法和加法镊尺,但實(shí)際上RNN計(jì)算要比前饋網(wǎng)絡(luò)復(fù)雜很多.原因我們看紅色箭頭,它標(biāo)記的是誤差反向傳播并思,也就是根據(jù)實(shí)際結(jié)果y和輸出層的預(yù)測(cè)結(jié)果o計(jì)算出的誤差傳回網(wǎng)絡(luò)以調(diào)整權(quán)重UVW.由于每個(gè)隱藏層都依賴前一隱藏層的結(jié)果庐氮,因此誤差不只要從隱藏層傳回輸入層,還要一層一層傳回上一隱藏層.它使用計(jì)算變得很復(fù)雜宋彼,且無(wú)法并行.
于是又有了下圖中的變種弄砍,使用實(shí)際輸出y仙畦,和下個(gè)x一次訓(xùn)練下一隱藏層,因?yàn)閥中信息并不像h中那么豐富音婶,因此可能效果會(huì)差一些.這里只是循環(huán)神經(jīng)網(wǎng)絡(luò)的幾種情況慨畸,其它就不一一列舉了,總的來(lái)說(shuō)循環(huán)神經(jīng)網(wǎng)絡(luò)并無(wú)定式衣式,主要指數(shù)據(jù)的流向中包含循環(huán).


2. LSTM

經(jīng)常聽(tīng)到LSTM神經(jīng)網(wǎng)絡(luò)如何如何寸士,其實(shí)LSTM不是一種網(wǎng)絡(luò),而是一種對(duì)RNN隱藏層的改進(jìn)算法(改進(jìn)算法有很多碴卧,這個(gè)因?yàn)樾Ч萌蹩ǎ员容^著名)
LSTM(Long short-term memory)是長(zhǎng)短期記憶的簡(jiǎn)寫(xiě).


引自:《深度學(xué)習(xí)》"花書(shū)"

如果不斷用隱藏層去計(jì)算下一時(shí)間隱藏層,當(dāng)計(jì)算隱藏層的特征向量大于1時(shí)螟深,經(jīng)過(guò)N次迭代后值就會(huì)越來(lái)越大谐宙,最終發(fā)生爆炸烫葬,如果小于1界弧,最后越來(lái)越小,導(dǎo)致消失.換句話說(shuō)搭综,過(guò)去會(huì)給我們啟發(fā)垢箕,所以不能忘記過(guò)去,但如果每時(shí)每刻都被過(guò)去影響兑巾,就像滾雪球一樣条获,最后也會(huì)悲劇.最好是把重點(diǎn)記住蒋歌,然后在開(kāi)始新篇章的時(shí)候更多地忘記過(guò)去.
更直觀的說(shuō)帅掘,原來(lái)在輸入層和隱藏層間是仿射變換加激活函數(shù),現(xiàn)在用輸入門堂油,遺忘門輸出門和狀態(tài)層來(lái)代替隱藏單元的生成算法.其中每個(gè)門都有非線性變換.這幾個(gè)門的關(guān)系修档,詳見(jiàn)代碼:

input_gate = tf.sigmoid(tf.matmul(i, ix) + tf.matmul(o, im) + ib)  #輸入門
forget_gate = tf.sigmoid(tf.matmul(i, fx) + tf.matmul(o, fm) + fb)  #遺忘門
update = tf.tanh(tf.matmul(i, cx) + tf.matmul(o, cm) + cb)  #更新
state = forget_gate * state + input_gate * update # 更新?tīng)顟B(tài), 遺忘門控制是否忘記舊時(shí)狀態(tài)
output_gate = tf.sigmoid(tf.matmul(i, ox) +  tf.matmul(o, om) + ob) #輸出門
return output_gate * tf.tanh(state), state #返回輸出值

3. 程序

1) 說(shuō)明

與前篇的BP網(wǎng)絡(luò)和CNN網(wǎng)絡(luò)一樣,這次使用的仍然是MNIST手寫(xiě)數(shù)據(jù)識(shí)別.在練習(xí)了純Python和Keras框架之后府框, 此次使用更低層的TensorFlow代碼實(shí)現(xiàn)RNN.也順便了解一個(gè)高級(jí)工具都封裝了什么吱窝?
每個(gè)圖片仍然是28x28像素,前饋網(wǎng)絡(luò)把28x28共748個(gè)像素值作為一個(gè)輸入x數(shù)據(jù)傳入輸入層迫靖,而RNN把每張圖當(dāng)成一個(gè)序列院峡,序列有28個(gè)元素(一行為一個(gè)元素),以每行的28個(gè)點(diǎn)為輸入x傳入輸入層.簡(jiǎn)單地說(shuō)就是切成一行一行訓(xùn)練系宜,每行與下一行有一定聯(lián)系.
下圖是時(shí)序圖(為簡(jiǎn)化邏輯照激,此處只畫(huà)了一個(gè)隱藏層),相對(duì)最一般的RNN盹牧,下圖是一個(gè)變種:整個(gè)序列(28行)的輸入對(duì)應(yīng)同一個(gè)輸出y(手寫(xiě)對(duì)應(yīng)的數(shù)字).


圖片.png
2) 代碼
# -*- coding: utf-8 -*-

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import numpy as np

# 在MINIST_data目錄下載 mnist數(shù)據(jù)
mnist = input_data.read_data_sets("MINIST_data/", one_hot=True)

# RNN學(xué)習(xí)時(shí)使用的參數(shù)
learning_rate = 0.001 # 學(xué)習(xí)率
training_iters = 100000 # 訓(xùn)練實(shí)例數(shù)
batch_size = 120 # 批大小
display_step = 10 # 訓(xùn)練10批顯示一次

n_input = 28 # 每28個(gè)作為一個(gè)輸入層的節(jié)點(diǎn)數(shù)(行中點(diǎn))
n_steps = 28 # 28個(gè)連續(xù)序列(列)
n_hidden = 128 # 隱含層的節(jié)點(diǎn)數(shù)
n_classes = 10 # 輸出的節(jié)點(diǎn)數(shù)实抡,0~9個(gè)數(shù)字欠母,這里一共有10個(gè)

x = tf.placeholder("float", [None, n_steps, n_input]) # 構(gòu)建輸入節(jié)點(diǎn)
istate = tf.placeholder("float", [None, 2 * n_hidden]) # 構(gòu)建隱藏節(jié)點(diǎn),一個(gè)存節(jié)點(diǎn)吆寨,一個(gè)存狀態(tài)
y = tf.placeholder("float", [None, n_classes]) # 構(gòu)建輸出節(jié)點(diǎn)

# 隨機(jī)初始化各層的權(quán)值和偏置
weights = {
'hidden': tf.Variable(tf.random_normal([n_input, n_hidden])), # 輸入到隱藏
'out': tf.Variable(tf.random_normal([n_hidden, n_classes])) # 隱藏到輸出
}
biases = {
'hidden': tf.Variable(tf.random_normal([n_hidden])),
'out': tf.Variable(tf.random_normal([n_classes]))
}

# 建立RNN模型赏淌,_X是批訓(xùn)練數(shù)據(jù),_istate為隱藏節(jié)點(diǎn)
def RNN(_X, _istate, _weights, _biases):
    _X = tf.transpose(_X, [1, 0, 2]) # 把batch_size,n_steps,n_input順序變?yōu)閚_steps,batch_size,n_input
    _X = tf.reshape(_X, [-1, n_input]) # 再轉(zhuǎn)換為n_steps*batch_size, n_input
    # 兩個(gè)隱藏層:第一層直接計(jì)算啄清,第二層用LSTM
    _X = tf.matmul(_X, _weights['hidden']) + _biases['hidden'] # 計(jì)算隱藏層的節(jié)點(diǎn),此時(shí)X從輸入節(jié)點(diǎn)轉(zhuǎn)為隱藏節(jié)點(diǎn)
    lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0,state_is_tuple=False) # 定義lstm
    _X = tf.split(_X, n_steps, 0) # 序列切片六水,每片是一個(gè)(batch_size, n_hidden)
    outputs, states = tf.nn.static_rnn(lstm_cell, _X, initial_state=_istate) # 計(jì)算lstm rnn,states存狀態(tài)
    return tf.matmul(outputs[-1], _weights['out']) + _biases['out'] #計(jì)算輸出層

pred = RNN(x, istate, weights, biases)

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y)) # 損失函數(shù)為交叉熵
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost) # 優(yōu)化方法為Adam

correct_pred = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) # 計(jì)算錯(cuò)誤數(shù)
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32)) # 計(jì)算錯(cuò)誤率

init = tf.global_variables_initializer()

sess = tf.InteractiveSession()
sess.run(init)
step = 1
while step * batch_size < training_iters:
    batch_xs, batch_ys = mnist.train.next_batch(batch_size) # 隨機(jī)抽取訓(xùn)練數(shù)據(jù)
    batch_xs = batch_xs.reshape((batch_size, n_steps, n_input))
    # 用feed_dict傳入數(shù)據(jù):輸入,輸出辣卒,隱藏層, 數(shù)據(jù)由placeholder定義, 運(yùn)行optimizer
    sess.run(optimizer, feed_dict={x: batch_xs, y: batch_ys, istate: np.zeros((batch_size, 2 * n_hidden))})
    if step % display_step == 0: # 每display_step次批處理顯示一次, 通過(guò)run運(yùn)行accuracy,cost
        acc = sess.run(accuracy, feed_dict={x: batch_xs, y: batch_ys, istate: np.zeros((batch_size, 2 * n_hidden))})
        loss = sess.run(cost, feed_dict={x: batch_xs, y: batch_ys, istate: np.zeros((batch_size, 2 * n_hidden))})
        print("Iter " + str(step * batch_size) + ", Minibatch Loss= " + "{:.6f}".format(loss) + ", Training Accuracy= " + "{:.5f}".format(acc))
    step += 1
print("Optimization Finished!")

test_len = 256
test_data = mnist.test.images[:test_len].reshape((-1, n_steps, n_input))
test_label = mnist.test.labels[:test_len]
print("Testing Accuracy:", sess.run(accuracy, feed_dict={x: test_data, y: test_label, istate: np.zeros((test_len, 2 * n_hidden))}))

3) 分析

TensorFlow涉及了更多具體計(jì)算掷贾,比如格式轉(zhuǎn)換,矩陣乘法等等荣茫,不像Keras從外面基本看不到具體的步驟的動(dòng)作和結(jié)果.
從代碼中很容易明白為什么說(shuō)TensorFlow是一個(gè)"框架"想帅,程序的前50行,具體數(shù)據(jù)還沒(méi)出現(xiàn)啡莉,程序就指定了數(shù)據(jù)的結(jié)構(gòu)和流向港准,在接下來(lái)的sess部分,tf 才真正開(kāi)始運(yùn)算咧欣,把數(shù)據(jù)切塊"喂"給框架浅缸,使其運(yùn)行.它和一般程序調(diào)函數(shù),確實(shí)不太一樣.
這里比較不容易理解的是數(shù)據(jù)怎么從feed_dict轉(zhuǎn)入了RNN函數(shù).在pred = RNN(x, istate, weights, biases)被運(yùn)行時(shí)魄咕,其實(shí)里面并沒(méi)有真正的數(shù)據(jù)在做轉(zhuǎn)換和乘法衩椒,這里定義的是數(shù)據(jù)的流程.此時(shí)的x,istate里面還沒(méi)有數(shù)據(jù)哮兰,而只是定義了數(shù)據(jù)形式毛萌,并告訴TensorFlow該數(shù)據(jù)需要如何處理.在后面feed_dict處理時(shí)才傳入了真正的數(shù)據(jù),并通過(guò)run()間接地調(diào)用了RNN(). sess.run()調(diào)用函數(shù)時(shí)喝滞,函數(shù)的各個(gè)參數(shù)都是從當(dāng)前環(huán)境里取的.我理解這里的placeholder意思有點(diǎn)像C中定義的數(shù)據(jù)結(jié)構(gòu).

4. 問(wèn)題與解答

1) RNN的隱藏層是一個(gè)還是多個(gè)阁将?

隱藏層可以是一個(gè),也可以是多個(gè)(多層循環(huán)網(wǎng)絡(luò))囤躁,比如說(shuō)可以有三個(gè)隱藏層h1,h2,h3冀痕,其中h2將結(jié)果轉(zhuǎn)給下一個(gè)實(shí)例的訓(xùn)練,還可以是雙向的(一個(gè)傳向前一時(shí)間點(diǎn)狸演,一個(gè)傳向后一時(shí)間點(diǎn)言蛇,即雙向循環(huán)網(wǎng)絡(luò)),一般為了簡(jiǎn)化宵距,例子里都有單層的.

2) RNN中反向傳播梯度是怎么進(jìn)行的腊尚?

對(duì)于訓(xùn)練序列來(lái)說(shuō),如果序列中每個(gè)時(shí)間點(diǎn)的輸入x都有對(duì)應(yīng)的輸出y满哪,總損失就是所有時(shí)間步的損失之和.如果像MNIST中整個(gè)序列對(duì)應(yīng)一個(gè)結(jié)果婿斥,則使用該結(jié)果與預(yù)測(cè)的誤差.具體方法還是梯度下降劝篷,只是計(jì)算隱藏層與隱藏層之間權(quán)重的方法需要按時(shí)間往前推.

5. 參考

1) TensorFlow學(xué)習(xí)筆記(8):基于MNIST數(shù)據(jù)的循環(huán)神經(jīng)網(wǎng)絡(luò)RNN

https://segmentfault.com/a/1190000008346992

2) 解讀tensorflow之rnn

http://weibo.com/p/23041853dd83fd0102x6wc?sudaref=www.baidu.com&display=0&retcode=6102&sudaref=passport.weibo.com

3) TensorFlow遇到的問(wèn)題匯總(持續(xù)更新中......)

http://www.cnblogs.com/hunttown/p/6866586.html

4) 利用 Keras 下的 LSTM 進(jìn)行情感分析

http://blog.csdn.net/william_2015/article/details/72978387

5) 基于Theano的深度學(xué)習(xí)(Deep Learning)框架Keras學(xué)習(xí)隨筆-02-Example

http://blog.csdn.net/niuwei22007/article/details/49053771

6) 循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN, Recurrent Neural Networks)介紹

http://blog.csdn.net/heyongluoyao8/article/details/48636251

7) 零基礎(chǔ)入門深度學(xué)習(xí)(6) - 長(zhǎng)短時(shí)記憶網(wǎng)絡(luò)(LSTM)

https://www.zybuluo.com/hanbingtao/note/581764

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市民宿,隨后出現(xiàn)的幾起案子娇妓,更是在濱河造成了極大的恐慌,老刑警劉巖活鹰,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哈恰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡志群,警方通過(guò)查閱死者的電腦和手機(jī)着绷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锌云,“玉大人荠医,你說(shuō)我怎么就攤上這事∩O眩” “怎么了彬向?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)石洗。 經(jīng)常有香客問(wèn)我幢泼,道長(zhǎng)紧显,這世上最難降的妖魔是什么讲衫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮孵班,結(jié)果婚禮上涉兽,老公的妹妹穿的比我還像新娘。我一直安慰自己篙程,他們只是感情好枷畏,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著虱饿,像睡著了一般拥诡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上氮发,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天渴肉,我揣著相機(jī)與錄音,去河邊找鬼爽冕。 笑死仇祭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的颈畸。 我是一名探鬼主播乌奇,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼没讲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了礁苗?” 一聲冷哼從身側(cè)響起爬凑,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎试伙,沒(méi)想到半個(gè)月后贰谣,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迁霎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年吱抚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片考廉。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秘豹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昌粤,到底是詐尸還是另有隱情既绕,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布涮坐,位于F島的核電站凄贩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏袱讹。R本人自食惡果不足惜疲扎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捷雕。 院中可真熱鬧椒丧,春花似錦、人聲如沸救巷。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)浦译。三九已至棒假,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間精盅,已是汗流浹背帽哑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留渤弛,地道東北人祝拯。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親佳头。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鹰贵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容