摘自https://www.cnblogs.com/pinard/p/6519110.html
一、RNN回顧
略去上面三層,即o,L,y,則RNN的模型可以簡化成如下圖的形式:
二、LSTM模型結構:
整體模型:
由於RNN梯度消失的問題,大牛們對於序列索引位置t的隱藏結構做了改進,可以說通過一些技巧讓隱藏結構復雜了起來,來避免梯度消失的問題,這樣的特殊RNN就是我們的LSTM。由於LSTM有很多的變種,這里我們以最常見的LSTM為例講述。LSTM的結構如下圖:
記憶細胞:
從上圖中可以看出,在每個序列索引位置t時刻向前傳播的除了和RNN一樣的隱藏狀態h(t),還多了另一個隱藏狀態,如圖中上面的長橫線。這個隱藏狀態我們一般稱為細胞狀態(Cell State),記為C(t)。如下圖所示:
門控結構:
除了細胞狀態,LSTM圖中還有了很多奇怪的結構,這些結構一般稱之為門控結構(Gate)。LSTM在在每個序列索引位置t的門一般包括遺忘門,輸入門和輸出門三種。下面我們就來研究上圖中LSTM的遺忘門,輸入門和輸出門以及細胞狀態。
-
遺忘門:是控制是否遺忘的,在LSTM中即以一定的概率控制是否遺忘上一層的隱藏細胞狀態。遺忘門子結構如下圖所示:
-
輸入門:負責處理當前序列位置的輸入,它的子結構如下圖:
LSTM之細胞狀態更新:
在研究LSTM輸出門之前,我們要先看看LSTM之細胞狀態。前面的遺忘門和輸入門的結果都會作用於細胞狀態C(t)。我們來看看從細胞狀態C(t−1)如何得到C(t)。如下圖所示:
我們把舊狀態與ft相乘,丟棄掉我們確定需要丟棄的信息。接着加上it∗Ct~。這就是新的候選值,根據我們決定更新每個狀態的程度進行變化。
-
輸出門:有了新的隱藏細胞狀態C(t),我們就可以來看輸出門了,子結構如下:
三、LSTM的前向傳播
四、LSTM反向傳播算法
總結:
五、簡單的LSTM代碼實現:
# 定義一個 LSTM 結構,LSTM 中使用的變量會在該函數中自動被聲明 lstm = tf.contrib.rnn.BasicLSTMCell(lstm_hidden_size) # 將 LSTM 中的狀態初始化為全 0 數組,batch_size 給出一個 batch 的大小 state = lstm.zero_state(batch_size, tf.float32) # 定義損失函數 loss = 0.0 # num_steps 表示最大的序列長度 for i in range(num_steps): # 在第一個時刻聲明 LSTM 結構中使用的變量,在之后的時刻都需要服用之前定義好的變量 if i>0: tf.get_variable_scope().reuse_variables() # 每一步處理時間序列中的一個時刻。將當前輸入(current_input)和前一時刻狀態(state)傳入定義的 LSTM 結構就可以得到當前 LSTM 結構的輸出 lstm_output 和更新后的狀態 state lstm_output, state = lstm(current_input, state) # 將當前時刻 LSTM 結構的輸出傳入一個全連接層得到最后的輸出 final_output = fully_connected(lstm_output) # 計算當前時刻輸出的損失 loss += calc_loss(final_output, expected_output)