十 | 門控循環神經網絡LSTM與GRU(附python演練)

歡迎你們關注咱們的網站和系列教程:http://panchuang.net/ ,學習更多的機器學習、深度學習的知識!

目錄:git

  • 門控循環神經網絡簡介
  • 長短時間記憶網絡(LSTM)
  • 門控制循環單元(GRU)
  • TensorFlow實現LSTM和GRU
  • 參考文獻
1、門控循環神經網絡

門控循環神經網絡在簡單循環神經網絡的基礎上對網絡的結構作了調整,加入了門控機制,用來控制神經網絡中信息的傳遞。門控機制能夠用來控制記憶單元中的信息有多少須要保留,有多少須要丟棄,新的狀態信息又有多少須要保存到記憶單元中等。這使得門控循環神經網絡能夠學習跨度相對較長的依賴關係,而不會出現梯度消失和梯度爆炸的問題。若是從數學的角度來理解,通常結構的循環神經網絡中,網絡的狀態和之間是非線性的關係,而且參數W在每一個時間步共享,這是致使梯度爆炸和梯度消失的根本緣由。門控循環神經網絡解決問題的方法就是在狀態和之間添加一個線性的依賴關係,從而避免梯度消失或梯度爆炸的問題。網絡

2、長短時間記憶網絡(LSTM)機器學習

長短時間記憶網絡(Long Short-term Memory,簡稱LSTM)的結構如圖1所示,LSTM[1]的網絡結構看上去很複雜,但實際上若是將每一部分拆開來看,其實也很簡單。在通常的循環神經網絡中,記憶單元沒有衡量信息的價值量的能力,所以,記憶單元對於每一個時刻的狀態信息等同視之,這就致使了記憶單元中每每存儲了一些無用的信息,而真正有用的信息卻被這些無用的信息擠了出去。LSTM正是從這一點出發作了相應改進,和通常結構的循環神經網絡只有一種網絡狀態不一樣,LSTM中將網絡的狀態分爲內部狀態和外部狀態兩種。LSTM的外部狀態相似於通常結構的循環神經網絡中的狀態,即該狀態既是當前時刻隱藏層的輸出,也是下一時刻隱藏層的輸入。這裏的內部狀態則是LSTM特有的。函數

在LSTM中有三個稱之爲「門」的控制單元,分別是輸入門(input gate)、輸出門(output gate)和遺忘門(forget gate),其中輸入門和遺忘門是LSTM可以記憶長期依賴的關鍵。輸入門決定了當前時刻網絡的狀態有多少信息須要保存到內部狀態中,而遺忘門則決定了過去的狀態信息有多少須要丟棄。最後,由輸出門決定當前時刻的內部狀態有多少信息須要輸出給外部狀態。學習

圖1 單個時間步的LSTM網絡結構示意圖 測試

從上圖咱們能夠看到,一個LSTM單元在每一個時間步都會接收三個輸入,當前時刻的輸入,來自上一時刻的內部狀態以及上一時刻的外部狀態。其中,和同時做爲三個「門」的輸入。爲Logistic函數,。

接下來咱們將分別介紹LSTM中的幾個「門」結構。首先看一下輸入門,如圖2所示:優化

從上圖咱們能夠看到,一個LSTM單元在每一個時間步都會接收三個輸入,當前時刻的輸入,來自上一時刻的內部狀態以及上一時刻的外部狀態。其中,和同時做爲三個「門」的輸入。爲Logistic函數,。網站

接下來咱們將分別介紹LSTM中的幾個「門」結構。首先看一下輸入門,如圖2所示:.net

圖2 LSTM的輸入門結構示意圖翻譯

LSTM中也有相似於RNN(這裏特指前面介紹過的簡單結構的循環神經網絡)的前向計算過程,如圖2,若是去掉輸入門部分,剩下的部分其實就是RNN中輸入層到隱藏層的結構,「tanh」能夠看做是隱藏層的激活函數,從「tanh」節點輸出的值爲:

上式中,參數的下標「c」表明這是「tanh」節點的參數,同理,輸入門參數的下標爲「i」,輸出門參數的下標爲「o」,遺忘門參數的下標爲「f」。上式與簡單結構循環神經網絡中隱藏層的計算公式同樣。在LSTM中,咱們將「tanh」節點的輸出稱爲候選狀態。

輸入門是如何實現其控制功能的?輸入門的計算公式以下:

因爲爲Logistic函數,其值域爲,所以輸入門的值就屬於。LSTM將「tanh」節點的輸出(即候選狀態)乘上輸入門的值後再用來更新內部狀態。若是的值趨向於0的話,那麼候選狀態就只有極少許的信息會保存到內部狀態中,相反的,若是的值趨近於1,那麼候選狀態就會有更多的信息被保存。輸入門就是經過這種方法來決定保存多少中的信息,值的大小就表明了新信息的重要性,不重要的信息就不會被保存到內部狀態中。

再來看遺忘門,如圖3所示:

圖3 LSTM的遺忘門結構示意圖

遺忘門的計算公式以下:

和輸入門是一樣的方法,經過f_t的值來控制上一時刻的內部狀態c_(t-1)有多少信息須要「遺忘」。當f_t的值越趨近於0,被遺忘的信息越多。一樣的原理,咱們來看「輸出門」,如圖4所示。輸出門的計算公式以下:

當o_t的值月接近於1,則當前時刻的內部狀態c_t就會有更多的信息輸出給當前時刻的外部狀態h_t。

圖4 LSTM的輸出門結構示意圖

以上就是LSTM的整個網絡結構以及各個「門」的計算公式。經過選擇性的記憶和遺忘狀態信息,使的LSTM要比通常的循環神經網絡可以學習更長時間間隔的依賴關係。根據不一樣的需求,LSTM還有着不少不一樣的變體版本,這些版本的網絡結構大同小異,但都在其特定的應用中表現出色。

3、門控制循環單元(GRU)

門控制循環單元(gated recurrent unit,GRU)網絡是另外一種基於門控制的循環神經網絡,GRU[2]的網絡結構相比LSTM要簡單一些。GRU將LSTM中的輸入門和遺忘門合併成了一個門,稱爲更新門(update gate)。在GRU網絡中,沒有LSTM網絡中的內部狀態和外部狀態的劃分,而是經過直接在當前網絡的狀態h_t和上一時刻網絡的狀態h_(t-1)之間添加一個線性的依賴關係,來解決梯度消失和梯度爆炸的問題。

圖5 單個時間步的GRU網絡結構示意圖

在GRU網絡中,更新門用來控制當前時刻輸出的狀態h_t中要保留多少歷史狀態h_(t-1),以及保留多少當前時刻的候選狀態h ̃_t。更新門的計算公式以下:

如圖5所示,更新門的輸出分別和歷史狀態h_(t-1)以及候選狀態h ̃_t進行了乘操做,其中和h ̃_t相乘的是1-z_t。最終當前時刻網絡的輸出爲:

重置門的做用是決定當前時刻的候選狀態是否須要依賴上一時刻的網絡狀態以及須要依賴多少。從圖5能夠看到,上一時刻的網絡狀態h_t先和重置門的輸出r_t相乘以後,再做爲參數用於計算當前時刻的候選狀態。重置門的計算公式以下:

r_t的值決定了候選狀態h ̃_t對上一時刻的狀態h_(t-1)的依賴程度,候選狀態h ̃_t的計算公式以下:

其實當z_t的值爲0且r_t的值爲1時,GRU網絡中的更新門和重置門就再也不發揮做用了,而此時的GRU網絡就退化成了簡單循環神經網絡,由於此時有:

4、TensorFlow實現LSTM和GRU

前面介紹了LSTM和GRU的理論知識,這一小節裏咱們使用TensorFlow來實現一個LSTM模型。爲了方便,這裏咱們使用前面介紹過的mnist數據集。可能讀者對於在循環神經網絡中使用圖像數據會有一點疑惑,由於一般狀況下圖像數據通常都是使用卷積神經網絡來訓練。事實的確是這樣,因爲卷積神經網絡和循環神經網絡的結構不一樣,也就使得它們各自有不一樣的適用場景,但這不表明卷積神經網絡只能用來處理時序數據,一樣也不能認爲循環神經網絡不能用來處理圖像數據,只要在輸入數據的格式上稍做調整便可,就像上一章中咱們使用卷積神經網絡網絡來處理文本數據同樣。

mnist數據集咱們在第三章中就已經使用過,這裏就再也不多作介紹了,直接上代碼:

1	from tensorflow.examples.tutorials.mnist import input_data
2	import tensorflow as tf
3	from tensorflow.contrib import rnn
4
5	batch_size = 100      # batch的大小
6	time_step = 28        # LSTM網絡中的時間步(每一個時間步處理圖像的一行)
7	data_length = 28      # 每一個時間步輸入數據的長度(這裏就是圖像的寬度)
8	learning_rate = 0.01  # 學習率

 

咱們首先導入須要的包,而後定義了神經網絡中的一些相關參數。其中第6行代碼定義了LSTM中的時間步的長度,因爲咱們mnist數據集的圖像大小爲28X28,因此咱們將一行像素做爲一個輸入,這樣咱們就須要有28個時間步。第7行代碼定義了每一個時間步輸入數據的長度(每一個時間步的輸入是一個向量),即一行像素的長度。

9	# 下載mnist數據集,當前目錄有已下載的數據集的話,就直接讀取,
10	mnist = input_data.read_data_sets("data", one_hot=True, reshape=False, validation_size=1000)
11
12	# 定義相關數據的佔位符
13	X_ = tf.placeholder(tf.float32, [None, 28, 28, 1])  # 輸入數據
14	Y_ = tf.placeholder(tf.int32, [None, 10])          # mnist數據集的類標
15	# dynamic_rnn的輸入數據(batch_size, max_time, ...)
16	inputs = tf.reshape(X_, [-1, time_step, data_length])
17	# 驗證集
18	validate_data = {X_: mnist.validation.images, Y_: mnist.validation.labels}
19	# 測試集
20	test_data = {X_: mnist.test.images, Y_: mnist.test.labels}

 

第10行代碼用來加載mnist數據集,並經過參數「validation_size」指定了驗證集的大小。第16行代碼用來將mnist數據集的格式轉換成「dynamic_rnn」函數接受的數據格式「[batch_size, max_time, data_length]」。

21	# 定義一個兩層的LSTM模型
22	lstm_layers = rnn.MultiRNNCell([rnn.BasicLSTMCell(num_units=num)
for num in [100, 100]], state_is_tuple=True)
23	# 定義一個兩層的GRU模型
24	# gru_layers = rnn.MultiRNNCell([rnn.GRUCell(num_units=num)
#                                  for num in [100, 100]], state_is_tuple=True)
25
26	outputs, h_ = tf.nn.dynamic_rnn(lstm_layers, inputs, dtype=tf.float32)
27	# outputs, h_ = tf.nn.dynamic_rnn(gru_layers, inputs, dtype=tf.float32)
28
29	output = tf.layers.dense(outputs[:, -1, :], 10)  # 獲取LSTM網絡的最後輸出狀態
30
31	# 定義交叉熵損失函數和優化器
32	loss = tf.losses.softmax_cross_entropy(onehot_labels=Y_, logits=output)  # compute cost
33	train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)
34
35	# 計算準確率
36	accuracy = tf.metrics.accuracy(
labels=tf.argmax(Y_, axis=1), predictions=tf.argmax(output, axis=1))[1]
37
38	# 初始化變量
39	sess = tf.Session()
40	init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
41	sess.run(init)

 

在上面的代碼中,咱們定義了一個兩層的LSTM網絡結構,並使用了交叉熵損失函數和「Adam」優化器。LSTM多層網絡結構的定義和咱們前面使用過的多層神經網絡的定義方法同樣,只是將「BasicRNNCell」類換成了「BasicLSTMCel」類。

42	for step in range(3000):
43	    # 獲取一個batch的訓練數據
44	    train_x, train_y = mnist.train.next_batch(batch_size)
45	    _, loss_ = sess.run([train_op, loss], {X_: train_x, Y_: train_y})
46
47	# 在驗證集上計算準確率
48	if step % 50 == 0:
49	    val_acc = sess.run(accuracy, feed_dict=validate_data)
50	    print('train loss: %.4f' % loss_, '| val accuracy: %.2f' % val_acc)
51
52	# 計算測試集上的準確率
53	test_acc = sess.run(accuracy, feed_dict=test_data)
54	print('test loss: %.4f' % test_acc)

 

在上面的整個代碼中,咱們使用的參數都是比較隨意的進行選擇的,沒有進行任何的優化,最終在測試集上的結果能達到96%左右,固然這確定不是LSTM網絡處理mnist數據集所能達到的最好的效果,有興趣的讀者能夠試着去調整網絡的結構和參數,看是否能達到更高的準確率。
TensorFlow中實現LSTM和GRU的切換很是簡單,在上面的代碼中,將第22和26行代碼註釋掉,而後取消第24和27行代碼的註釋,實現的就是GRU。
本文介紹了門控循環神經網絡LSTM以及GRU的原理及其tensorflow代碼實現,但願能讓你們對經常使用到的LSTM及GRU可以有更好的理解。下一篇,咱們將介紹RNN循環神經網絡的應用部分,分析RNN循環神經網絡是怎樣用在文本分類,序列標註以及機器翻譯上的,以及其存在的不足與改進方法。

5、 參考文獻
[1]Sepp Hochreiter: Long Short-term Memory .1997
[2]Kazuki Irie, Zoltán Tüske, TamerAlkhouli, Ralf Schlüter, Hermann Ney:LSTM, GRU, Highway and a Bit of Attention:An Empirical Overview for Language Modeling in Speech Recognition. INTERSPEECH2016: 3519-3523

歡迎你們關注咱們的網站和系列教程:http://panchuang.net/ ,學習更多的機器學習、深度學習的知識!

相關文章
相關標籤/搜索