一、用LSTM單層的網絡來做分類的問題
用lstm對mnist的數據集進行分類

1 #!/usr/bin/python 2 # -*- coding: UTF-8 -*- 3 import tensorflow as tf 4 from tensorflow.examples.tutorials.mnist import input_data 5 import tensorflow.contrib as contrib 6 tf.set_random_seed(1) 7 8 ##導入數據 9 mnist = input_data.read_data_sets('../mnist_data',one_hot=True) 10 11 ##超參數 12 lr = 0.001 # learning rate 13 training_iters = 100000 # train step 上限 14 batch_size = 128 15 n_inputs = 28 # MNIST data input (img shape: 28*28) 16 n_steps = 28 # time steps 17 n_hidden_units = 128 # neurons in hidden layer 18 n_classes = 10 # MNIST classes (0-9 digits) 19 20 ## x,y placeholder 21 x = tf.placeholder(tf.float32,[None,n_steps,n_inputs]) 22 y = tf.placeholder(tf.float32,[None,n_classes]) 23 24 ## 對 weights biases 的初始值的定義 25 weights ={ 26 # shape (28, 128) 27 "in":tf.Variable(tf.truncated_normal([n_inputs,n_hidden_units])), 28 # shape (128, 10) 29 'out':tf.Variable(tf.truncated_normal([n_hidden_units,n_classes])) 30 } 31 biases ={ 32 # shape (128, ) 33 'in':tf.Variable(tf.constant(0.1,shape=[n_hidden_units,])), 34 # shape (10, ) 35 'out':tf.Variable(tf.constant(0.1,shape=[n_classes,])) 36 } 37 # 定義 RNN 的主體結構(input_layer, cell, output_layer) 38 def RNN(X,weights,biases): 39 # 原始的 X 是 3 維數據, 我們需要把它變成 2 維數據才能使用 weights 的矩陣乘法 40 # X ==> (128 batches * 28 steps, 28 inputs) 41 X = tf.reshape(X,[-1,n_inputs]) 42 # X_in = W*X + b 43 X_in = tf.matmul(X,weights['in'])+biases['in'] 44 # X_in ==> (128 batches, 28 steps, 128 hidden) 換回3維 45 X_in = tf.reshape(X_in,[-1,n_steps,n_hidden_units]) 46 47 # 使用 basic LSTM Cell. 48 lstm_cell = contrib.rnn.BasicLSTMCell(num_units=n_hidden_units,forget_bias=1.0,state_is_tuple=True) 49 init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32) 50 ## 如果 inputs 為 (batches, steps, inputs) ==> time_major=False; 如果 inputs 為 (steps, batches, inputs) ==> time_major=True; 51 outputs, final_state = tf.nn.dynamic_rnn(cell=lstm_cell,inputs=X_in,initial_state=init_state,time_major=False) 52 53 ###最后是 output_layer 和 return 的值. 因為這個例子的特殊性, 有兩種方法可以求得 results. 54 ### 方法一: 直接調用final_state 中的 h_state (final_state[1]) 來進行運算 55 results = tf.matmul(final_state[1],weights['out'])+biases['out'] 56 ## 調用最后一個 outputs (在這個例子中,和上面的final_state[1]是一樣的) 57 # 把 outputs 變成 列表 [(batch, outputs)..] * steps 58 # outputs = tf.unstack(tf.transpose(outputs, [1, 0, 2])) 59 # results = tf.matmul(outputs[-1], weights['out']) + biases['out'] # 選取最后一個 output 60 return results 61 62 63 64 # 定義好了 RNN 主體結構后, 我們就可以來計算 cost 和 train_op 65 pred = RNN(x, weights, biases) 66 cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred,labels=y)) 67 train_op = tf.train.AdamOptimizer(lr).minimize(cost) 68 # train_op = tf.train.AdadeltaOptimizer(lr).minimize(cost) ## 這出錯了啦!!!!!! 69 70 correct_pred = tf.equal(tf.argmax(pred,1),tf.argmax(y,1)) 71 accuracy = tf.reduce_mean(tf.cast(correct_pred,tf.float32)) 72 73 init_op = tf.global_variables_initializer() 74 with tf.Session() as sess: 75 sess.run(init_op) 76 step = 0 77 while step * batch_size < training_iters: 78 batch_xs,batch_ys = mnist.train.next_batch(batch_size) 79 batch_xs = batch_xs.reshape([batch_size,n_steps,n_inputs]) 80 sess.run([train_op],feed_dict={x:batch_xs,y:batch_ys}) 81 82 if step % 20 ==0: 83 print(sess.run(accuracy,feed_dict={x:batch_xs,y:batch_ys})) 84 step += 1
上例中,使用到關於LSTM的方法主要是
1) tensorflow.contrib.rnn.BasicLSTMCell
cell: RNNCell的對象. inputs: RNN的輸入,當time_major == False (default) 的時候,必須是形狀為 [batch_size, max_time, ...] 的tensor,
要是 time_major == True 的話, 必須是形狀為 [max_time, batch_size, ...] 的tensor. 前面兩個維度應該在所有的輸入里面都應該匹配. sequence_length: 可選,一個int32/int64類型的vector,他的尺寸是[batch_size]. 對於最后結果的正確性,
這個還是非常有用的.因為給他具體每一個序列的長度,能夠精確的得到結果,排除了之前為了把所有的序列弄成一樣的長度padding造成的不准確. initial_state: 可選,RNN的初始狀態. 要是cell.state_size 是一個整形,那么這個參數必須是一個形狀為 [batch_size, cell.state_size] 的tensor.
要是cell.state_size 是一個tuple, 那么這個參數必須是一個tuple,其中元素為形狀為[batch_size, s] 的tensor,s為cell.state_size 中的各個相應size. dtype: 可選,表示輸入的數據類型和期望輸出的數據類型.當初始狀態沒有被提供或者RNN的狀態由多種形式構成的時候需要顯示指定. parallel_iterations: 默認是32,表示的是並行運行的迭代數量(Default: 32).
有一些沒有任何時間依賴的操作能夠並行計算,實際上就是空間換時間和時間換空間的折中,當value遠大於1的時候,
會使用的更多的內存但是能夠減少時間,當這個value值很小的時候,會使用小一點的內存,但是會花更多的時間. swap_memory: Transparently swap the tensors produced in forward inference but needed for back prop from GPU to CPU.
This allows training RNNs which would typically not fit on a single GPU, with very minimal (or no) performance penalty. time_major: 規定了輸入和輸出tensor的數據組織格式,如果 true, tensor的形狀需要是[max_time, batch_size, depth].
若是false, 那么tensor的形狀為[batch_size, max_time, depth].
要是使用time_major = True 的話,會更加高效率一點,因為避免了在RNN計算的開始和結束的時候對於矩陣的轉置 ,
然而,大多數的tensorflow數據格式都是采用的以batch為主的格式,所以這里也默認采用以batch為主的格式. scope: 子圖的scope名稱,默認是”rnn”
import tensorflow as tf import numpy as np inputs = tf.placeholder(np.float32, shape=(32,40,5)) # 32 是 batch_size lstm_cell_1 = tf.contrib.rnn.BasicLSTMCell(num_units=128) print("output_size:",lstm_cell_1.output_size) ## 128 print("state_size:",lstm_cell_1.state_size) ## LSTMStateTuple(c=128, h=128) output,state=tf.nn.dynamic_rnn( cell=lstm_cell_1, inputs=inputs, dtype=tf.float32 ) print("output.shape:",output.shape) ##(32,40,128) print("len of state tuple",len(state)) ## 2 print("state.h.shape:",state.h.shape) ## (32,128) print("state.c.shape:",state.c.shape) ##(32,128)
其實在運用時,很簡單,如在 mnist的例子中,使用如下:
# X_in ==> (128 batches, 28 steps, 128 hidden) 換回3維 X_in = tf.reshape(X_in,[-1,n_steps,n_hidden_units]) # 使用 basic LSTM Cell. lstm_cell = contrib.rnn.BasicLSTMCell(num_units=n_hidden_units,forget_bias=1.0,state_is_tuple=True) init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32) ## 如果 inputs 為 (batches, steps, inputs) ==> time_major=False; 如果 inputs 為 (steps, batches, inputs) ==> time_major=True; outputs, final_state = tf.nn.dynamic_rnn(cell=lstm_cell,inputs=X_in,initial_state=init_state,time_major=False)
------
參考:
TensorFlow學習(十三):構造LSTM超長簡明教程