1.RNN
RNNs的目的使用來處理序列數據。在傳統的神經網絡模型中,是從輸入層到隱含層再到輸出層,層與層之間是全連接的,每層之間的節點是無連接的。但是這種普通的神經網絡對於很多問題卻無能無力。例如,你要預測句子的下一個單詞是什麼,一般需要用到前面的單詞,因爲一個句子中前後單詞並不是獨立的。RNNs之所以稱爲循環神經網路,即一個序列當前的輸出與前面的輸出也有關。具體的表現形式爲網絡會對前面的信息進行記憶並應用於當前輸出的計算中,即隱藏層之間的節點不再無連接而是有連接的,並且隱藏層的輸入不僅包括輸入層的輸出還包括上一時刻隱藏層的輸出。理論上,RNNs能夠對任何長度的序列數據進行處理。但是在實踐中,爲了降低複雜性往往假設當前的狀態只與前面的幾個狀態相關。
2.雙向RNN
Bidirectional RNNs(雙向循環神經網絡)的改進之處便是,假設當前的輸出(第t步的輸出)不僅僅與前面的序列有關,並且還與後面的序列有關。例如:預測一個語句中缺失的詞語那麼就需要根據上下文來進行預測。Bidirectional RNNs是一個相對較簡單的RNNs,是由兩個RNNs上下疊加在一起組成的。輸出由這兩個RNNs的隱藏層的狀態決定的。如下圖所示:
3.LSTM
LSTM 全稱叫 Long Short Term Memory networks,它和傳統 RNN 唯一的不同就在與其中的神經元(感知機)的構造不同。傳統的 RNN 每個神經元和一般神經網絡的感知機沒啥區別,但在 LSTM 中,每個神經元是一個“記憶細胞”,細胞裏面有一個“輸入門”(input gate), 一個“遺忘門”(forget gate), 一個“輸出門”(output gate),俗稱“三重門”。
LSTM 同樣是這樣的結構,但是重複的模塊擁有一個不同的結構。不同於 單一神經網絡層,整體上除了h在隨時間流動,細胞狀態c也在隨時間流動,細胞狀態c就代表着長期記憶。
4.GRU
GRUs也是一般的RNNs的改良版本,主要是從以下兩個方面進行改進。一是,序列中不同的位置處的單詞(已單詞舉例)對當前的隱藏層的狀態的影響不同,越前面的影響越小,即每個前面狀態對當前的影響進行了距離加權,距離越遠,權值越小。二是,在產生誤差error時,誤差可能是由某一個或者幾個單詞而引發的,所以應當僅僅對對應的單詞weight進行更新。GRUs的結構如下圖所示。GRUs首先根據當前輸入單詞向量word vector已經前一個隱藏層的狀態hidden state計算出update gate和reset gate。再根據reset gate、當前word vector以及前一個hidden state計算新的記憶單元內容(new memory content)。當reset gate爲1的時候,new memory content忽略之前的所有memory content,最終的memory是之前的hidden state與new memory content的結合。
https://www.jianshu.com/p/9dc9f41f0b29
https://blog.csdn.net/u011304078/article/details/81158370
https://blog.csdn.net/zhaojc1995/article/details/80572098
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
tf.set_random_seed(1)
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# hyperparameters
lr = 0.001
training_iters = 100000
batch_size = 128
n_inputs = 28 # shape 28*28
n_steps = 28 # time steps
n_hidden_unis = 128 # neurons in hidden layer
n_classes = 10 # classes 0-9
# tf Graph input
x = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
y = tf.placeholder(tf.float32, [None, n_classes])
# Define weights
weights = {
# (28,128)
'in': tf.Variable(tf.random_normal([n_inputs, n_hidden_unis])),
# (128,10)
'out': tf.Variable(tf.random_normal([n_hidden_unis, n_classes]))
}
biases = {
# (128,)
'in': tf.Variable(tf.constant(0.1, shape=[n_hidden_unis, ])),
# (10,)
'out': tf.Variable(tf.constant(0.1, shape=[n_classes, ]))
}
def RNN(X, weights, biases):
# hidden layer for input to cell
# X(128 batch, 28 steps, 28 inputs) => (128*28, 28)
X = tf.reshape(X, [-1, n_inputs])
# ==>(128 batch * 28 steps, 28 hidden)
X_in = tf.matmul(X, weights['in'])+biases['in']
# ==>(128 batch , 28 steps, 28 hidden)
X_in = tf.reshape(X_in,[-1, n_steps, n_hidden_unis])
# cell
lstm_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden_unis, forget_bias=1.0, state_is_tuple=True)
# lstm cell is divided into two parts(c_state, m_state)
_init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32)
outputs, states = tf.nn.dynamic_rnn(lstm_cell, X_in, initial_state=_init_state, time_major=False)
# hidden layer for output as the final results
results = tf.matmul(states[1], weights['out']) + biases['out'] # states[1]->m_state states[1]=output[-1]
# outputs = tf.unstack(tf.transpose(outputs,[1,0,2]))
# results = tf.matmul(outputs[-1], weights['out']) + biases['out']
return results
pred = RNN(x, weights, biases)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
train_op = tf.train.AdamOptimizer(lr).minimize(cost)
correct_pred = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
step = 0
while step * batch_size < training_iters:
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
batch_xs = batch_xs.reshape([batch_size, n_steps, n_inputs])
sess.run([train_op], feed_dict={
x: batch_xs,
y: batch_ys
})
if step % 20 ==0:
print (sess.run(accuracy, feed_dict={
x: batch_xs,
y: batch_ys
}))
step += 1