一、导入数据集
1 import tensorflow as tf 2 import numpy as np 3 #清除默认图形堆栈并重置全局默认图形,tf.reset_default_graph函数只适用于当前线程. 4 #当一个tf.Session或者tf.InteractiveSession激活时调用这个函数会导致未定义的行为. 5 #调用此函数后使用任何以前创建的tf.Operation或tf.Tensor对象将导致未定义的行为. 6 tf.reset_default_graph() 7 from tensorflow.examples.tutorials.mnist import input_data 8 9 #mnist是一个轻量级的类,它以numpy数组的形式存储着训练,校验,测试数据集 one_hot表示输出二值化后的10维 10 mnist = input_data.read_data_sets('MNIST-data',one_hot=True) 11 print('Training data shape:',mnist.train.images.shape) #Training data shape: (55000, 784) 12 print('Test data shape:',mnist.test.images.shape) #Test data shape: (10000, 784) 13 print('Validation data shape:',mnist.validation.images.shape) #Validation data shape: (5000, 784) 14 print('Training label shape:',mnist.train.labels.shape) #Training label shape: (55000, 10)
二、定义参数
1 n_input = 28 #LSTM单元输入节点的个数 2 n_steps = 28 #序列长度 3 n_hidden = 128 #LSTM单元输出节点个数(即隐藏层个数) 4 n_classes = 10 #类别 5 #定义占位符 6 #batch_size:表示一次的批次样本数量batch_size n_steps:表示时间序列总数 n_input:表示一个时序具体的数据长度 即一共28个时序,一个时序送入28个数据进入LSTM网络 7 input_x = tf.placeholder(dtype=tf.float32,shape=[None,n_steps,n_input]) 8 input_y = tf.placeholder(dtype=tf.float32,shape=[None,n_classes])
三、①、构建单层静态LSTM网络
1 def single_layer_static_lstm(input_x,n_steps,n_hidden): 2 ''' 3 返回静态单层LSTM单元的输出,以及cell状态 4 args: 5 input_x:输入张量 形状为[batch_size,n_steps,n_input] 6 n_steps:时序总数 7 n_hidden:LSTM单元输出的节点个数 即隐藏层节点数 8 ''' 9 ''' 10 #把输入input_x按列拆分,并返回一个有n_steps个张量组成的list 如batch_sizex28x28的输入拆成[(batch_size,28),((batch_size,28))....] 11 #如果是调用的是静态rnn函数,需要这一步处理 即相当于把序列作为第一维度 12 ''' 13 input_x1 = tf.unstack(input_x,num=n_steps,axis=1)#① 14 '''可以看做隐藏层''' 15 lstm_cell = tf.contrib.rnn.BasicLSTMCell(num_units=n_hidden,forget_bias=1.0)#② 16 '''静态rnn函数传入的是一个张量list 每一个元素都是一个(batch_size,n_input)大小的张量 ''' 17 hiddens,states = tf.contrib.rnn.static_rnn(cell=lstm_cell, inputs=input_x1, dtype=tf.float32)#③ 18 19 return hiddens,states
②、构建单层静态GRU网络
1 def single_layer_static_gru(input_x,n_steps,n_hidden): 2 ''' 3 返回静态单层GRU单元的输出,以及cell状态 4 5 args: 6 input_x:输入张量 形状为[batch_size,n_steps,n_input] 7 n_steps:时序总数 8 n_hidden:gru单元输出的节点个数 即隐藏层节点数 9 ''' 10 ''' 11 #把输入input_x按列拆分,并返回一个有n_steps个张量组成的list 如batch_sizex28x28的输入拆成[(batch_size,28),((batch_size,28))....] 12 #如果是调用的是静态rnn函数,需要这一步处理 即相当于把序列作为第一维度 13 ''' 14 input_x1 = tf.unstack(input_x,num=n_steps,axis=1) 15 16 '''可以看做隐藏层''' 17 gru_cell = tf.contrib.rnn.GRUCell(num_units=n_hidden) 18 '''静态rnn函数传入的是一个张量list 每一个元素都是一个(batch_size,n_input)大小的张量 ''' 19 hiddens,states = tf.contrib.rnn.static_rnn(cell=gru_cell,inputs=input_x1,dtype=tf.float32) 20 21 return hiddens,states
③、构建单层动态LSTM网络
1 def single_layer_dynamic_lstm(input_x,n_steps,n_hidden): 2 ''' 3 返回动态单层LSTM单元的输出,以及cell状态 4 5 args: 6 input_x:输入张量 形状为[batch_size,n_steps,n_input] 7 n_steps:时序总数 8 n_hidden:LSTM单元输出的节点个数 即隐藏层节点数 9 ''' 10 #可以看做隐藏层 11 lstm_cell = tf.contrib.rnn.BasicLSTMCell(num_units=n_hidden,forget_bias=1.0) 12 #动态rnn函数传入的是一个三维张量,[batch_size,n_steps,n_input] 输出也是这种形状 13 hiddens,states = tf.nn.dynamic_rnn(cell=lstm_cell,inputs=input_x,dtype=tf.float32) 14 15 #注意这里输出需要转置 转换为时序优先的 16 hiddens = tf.transpose(hiddens,[1,0,2]) 17 return hiddens,states
④、构建单层动态GRU网络
1 def single_layer_dynamic_gru(input_x,n_steps,n_hidden): 2 ''' 3 返回动态单层GRU单元的输出,以及cell状态 4 5 args: 6 input_x:输入张量 形状为[batch_size,n_steps,n_input] 7 n_steps:时序总数 8 n_hidden:gru单元输出的节点个数 即隐藏层节点数 9 ''' 10 11 #可以看做隐藏层 12 gru_cell = tf.contrib.rnn.GRUCell(num_units=n_hidden) 13 #动态rnn函数传入的是一个三维张量,[batch_size,n_steps,n_input] 输出也是这种形状 14 hiddens,states = tf.nn.dynamic_rnn(cell=gru_cell,inputs=input_x,dtype=tf.float32) 15 16 17 #注意这里输出需要转置 转换为时序优先的 18 hiddens = tf.transpose(hiddens,[1,0,2]) 19 return hiddens,states
四、初始化
1 #调用单层静态LSTM网络 2 hiddens,states = single_layer_static_lstm(input_x,n_steps,n_hidden) 3 #取LSTM最后一个时序的输出,然后经过全连接网络得到输出值 4 output = tf.contrib.layers.fully_connected(inputs=hiddens[-1],num_outputs=n_classes,activation_fn = tf.nn.softmax) 5 #设置对数似然损失函数 6 #代价函数 J =-(Σy.logaL)/n 表示逐元素乘 7 cost = tf.reduce_mean(-tf.reduce_sum(input_y*tf.log(output),axis=1)) 8 #求解 9 learning_rate = 1e-4 #学习率 10 train = tf.train.AdamOptimizer(learning_rate).minimize(cost) 11 #预测结果评估 12 #tf.argmax(output,1) 按行统计最大值得索引 13 correct = tf.equal(tf.argmax(output,1),tf.argmax(input_y,1)) #返回一个数组 表示统计预测正确或者错误 14 accuracy = tf.reduce_mean(tf.cast(correct,tf.float32)) #求准确率
五、训练以及测试
1 with tf.Session() as sess: 2 #使用会话执行图 3 sess.run(tf.global_variables_initializer()) #初始化变量 4 batch_size = 128 #小批量大小 5 training_step = 5000 #迭代次数 6 display_step = 200 #显示步数 7 #开始迭代 使用Adam优化的随机梯度下降法 8 for i in range(training_step): 9 x_batch,y_batch = mnist.train.next_batch(batch_size = batch_size) 10 #Reshape data to get 28 seq of 28 elements 11 x_batch = x_batch.reshape([-1,n_steps,n_input]) 12 13 #开始训练 14 train.run(feed_dict={input_x:x_batch,input_y:y_batch}) 15 if (i+1) % display_step == 0: 16 #输出训练集准确率 17 training_accuracy,training_cost = sess.run([accuracy,cost],feed_dict={input_x:x_batch,input_y:y_batch}) 18 print('Step {0}:Training set accuracy {1},cost {2}.'.format(i+1,training_accuracy,training_cost)) 19 20 21 #全部训练完成做测试 分成200次,一次测试50个样本 22 #输出测试机准确率 如果一次性全部做测试,内容不够用会出现OOM错误。所以测试时选取比较小的mini_batch来测试 23 for i in range(200): 24 x_batch,y_batch = mnist.test.next_batch(batch_size = 50) 25 #Reshape data to get 28 seq of 28 elements 26 x_batch = x_batch.reshape([-1,n_steps,n_input]) 27 test_accuracy,test_cost = sess.run([accuracy,cost],feed_dict={input_x:x_batch,input_y:y_batch}) 28 test_accuracy_list.append(test_accuracy) 29 test_cost_list.append(test_cost) 30 if (i+1)% 20 == 0: 31 print('Step {0}:Test set accuracy {1},cost {2}.'.format(i+1,test_accuracy,test_cost)) 32 print('Test accuracy:',np.mean(test_accuracy_list))
六、训练模型保存
1 saver = tf.train.Saver() 2 saver.save(sess, './model/rnn_model.ckpt')
七、调用模型
1 saver = tf.train.Saver() 2 save_path = tf.train.latest_checkpoint('./model/') 3 with tf.Session() as sess: 4 saver.restore(sess=sess, save_path=save_path) 5 feeds = {x:images,y:labels} 6 preds = sess.run(accr, feed_dict=feeds)