#RNN 循環神經網絡 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data tf.set_random_seed(1) # set random seed # 導入數據 mnist = input_data.read_data_sets('MNIST_data', one_hot=True) # hyperparameters lr = 0.001 # learning rate training_iters = 1000000 # train step 上限 循環次數 batch_size = 128 n_inputs = 28 # MNIST data input (img shape: 28*28) 指圖片一行有28個像素,RNN每次提取一行 n_steps = 28 # time steps 指圖片有28行,所以RNN需要提取28次 n_hidden_units = 128 # neurons in hidden layer n_classes = 10 # MNIST classes (0-9 digits) # x y placeholder x = tf.placeholder(tf.float32, [None, n_steps, n_inputs]) y = tf.placeholder(tf.float32, [None, n_classes]) # 對 weights biases 初始值的定義 weights = { # shape (28, 128) 'in': tf.Variable(tf.random_normal([n_inputs, n_hidden_units])), # shape (128, 10) 'out': tf.Variable(tf.random_normal([n_hidden_units, n_classes])) } biases = { # shape (128, ) 'in': tf.Variable(tf.constant(0.1, shape=[n_hidden_units, ])), # shape (10, ) 'out': tf.Variable(tf.constant(0.1, shape=[n_classes, ])) } def RNN(X, weights, biases): #hidden layer for input to cell ############################## #X(128batch,28steps,28inputs) ==>(128*28,28inputs) X = tf.reshape(X,[-1,n_inputs]) #X_in ==> (128batch * 28steps,128hidden) X_in = tf.matmul(X,weights['in'])+biases['in'] # X_in ==> (128batch , 28steps,128hidden) X_in = tf.reshape(X_in,[-1,n_steps,n_hidden_units]) #cell ############################# lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden_units, forget_bias=1.0,state_is_tuple=True) # forget_bias=1.0不忘記任何的輸入 # lstm cell is divided into two parts(c_state,m_state) c_state為主線,m_state為分線 # (可以理解為c_state為之前一直留下來的記憶,m_state為當前產生的記憶) _init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32) # 初始化全零 state _init_state會生成一個元組(c_state,m_state) # rnn計算時會保留每一步的計算結果在state中,就是lstm的記憶 outputs, final_state = tf.nn.dynamic_rnn(lstm_cell, X_in, initial_state=_init_state,time_major=False) # time_major=False 因為28steps在第二個維度(128batch , 28steps,128hidden),若在第一個維度(28steps,128batch,128hidden),time_major=True # final_state是最后的state,而outputs是每一步的結果 # X_in 為輸入層傳過來的值[128,28,128] ''' BasicLSTMCell代表每一個lstm單元(即每個時刻的處理單元) 第一個參數代表單個lstm單元中隱藏層的大小 因為每個時刻的輸入也是一個向量,所以lstm隱藏層單元不是只有一個。 lstm中處理的全部都是向量,沒有單獨的數字 ''' ''' tf.nn.dynamic_rnn( cell, inputs, sequence_length=None, initial_state=None, dtype=None, parallel_iterations=None, swap_memory=False, time_major=False, scope=None ) 參數說明:tf.nn.dynamic_rnn(lstm_cell, X_in, initial_state=init_state, time_major=False) cell:RNNCell 實例。 inputs:RNN輸入。如果time_major==False(默認),必須要是形如[batch_size,max_time]的張量,或者這些元素的嵌套元組。 如果time_major == True,必須是形如[max_time, batch_size, ...]的張量, 或者這些元素的嵌套元組. 這也可能是一個滿足這個屬性的(可能嵌套的)張量元組. 前兩個維度必須匹配所有輸入,否則排名和其他形狀組件可能會有所不同. 在這種情況下,每個時間步的單元輸入將復制這些元組的結構,除了時間維(從中獲取時間)。 在每個時間步的單元格輸入將是張量或(可能嵌套的)張量元組,每個張量元素的尺寸為[batch_size,...]。 sequence_length:(可選)一個int32 / int64向量,大小為[batch_size]。 用於在批量元素的序列長度超過時復制通過狀態和零輸出輸出。所以它比正確性更重要。 initial_state:(可選)RNN的初始狀態。 如果cell.state_size是一個整數,則它必須是形如 [batch_size,cell.state_size]的張量。 如果cell.state_size是一個元組,它應該是一個在cell.state_size中具有形狀[batch_size,s]的張量元組。 dtype:(可選)初始狀態和預期輸出的數據類型。 如果未提供initial_state或RNN狀態具有異構dtype,則為必需。 parallel_iterations:(默認:32)。 並行運行的迭代次數。 那些沒有任何時間依賴性並且可以並行運行的操作將會是。 此參數為空間換取時間。 值>> 1使用更多的內存,但花費的時間更少,而更小的值使用更少的內存,但計算需要更長的時間。 swap_memory:透明地交換前向推理中產生的張量,但是需要GPU支持back prop。 這允許對通常不適合單個GPU的RNN進行訓練,並且性能損失非常小(或沒有)。 time_major:輸入和輸出張量的形狀格式,如果time_major == True,則這些張量必須為[max_time,batch_size,depth]。 如果為false,則這些張量必須為[batch_size,max_time,depth]。 使用time_major = True可以提高效率,因為它避免了RNN計算開始和結束時的轉置。 但是,大多數TensorFlow數據都是批處理主數據,所以默認情況下,此功能接受輸入並以批處理主要形式發出輸出。 scope:用於創建子圖的VariableScope; 默認為“rnn”。 返回值: output:RNN輸出張量。如果time_major == False (default),輸出張量形如[batch_size, max_time, cell.output_size]。 ast_states是由(c,h)組成的tuple,均為[batch,列數]。 ''' #hidden layer for output as the final results 輸出隱藏層 ############################################## #第一種計算results的方法 #使用final_state[1]的原因,final_state包含兩個state(c_state,m_state),final_state[1]為分線劇情的結果 #results = tf.matmul(final_state[1], weights['out']) + biases['out'] #final_state[1]指分線(m_state)的結果=outputs[-1] #第二種計算results的方法 把 outputs 變成 列表 [(batch, outputs)..] * steps outputs = tf.unstack(tf.transpose(outputs, [1, 0, 2])) results = tf.matmul(outputs[-1], weights['out']) + biases['out'] # 選取最后一個 output,為分類結果 return results pred = RNN(x, weights, biases) cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=pred)) 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.initialize_all_variables() # tf 馬上就要廢棄這種寫法 # 替換成下面的寫法: 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
