练习利用LSTM实现手写数字分类任务
MNIST数据集中图片大小为28*28.
按照行进行展开成28维的特征向量。
考虑到这28个的向量之间存在着顺序依赖关系,我们可以将他们看成是一个长为28的输入序列,将其输入到LSTM中,LSTM可以从中提取到序列特征,再将此序列特征用一层全联接作为分类器,分类器输出10种分类类别。
综合代码
import tensorflow as tf
import numpy as np
from tensorflow.contrib.layers import fully_connectedimport input_data
mnist = input_data.read_data_sets('MNIST_data/',one_hot = True)
#one_hot = True 独热编码,类似[0,0,0,1,0,0,0,0,0,0]这种形式,等价于class=3n_inputs = 28 #表示输入神经元的个数
n_steps = 28 #表示序列长度
n_neurons = 150 #表示LSTM中隐藏层和输出层神经元呢个数
n_outputs = 10 #是最终分类器输出的类别数,mnist数据集是10分类任务learning_rate = 0.01 #优化方法的学习率X = tf.placeholder(tf.float32,[None,n_steps,n_inputs])
Y_labels = tf.placeholder(tf.int32,[None,n_outputs])basic_cell = tf.contrib.rnn.BasicLSTMCell(n_neurons,forget_bias = 1.0, state_is_tuple = True)
#获取一层LSTM网络,参数1是每个cell的输出神经元个数,参数2是遗忘的偏置,参数3表示双状态outneurons, states = tf.nn.dynamic_rnn(basic_cell,X,dtype = tf.float32)
#outneurons得到了输出序列logits = fully_connected(tf.transpose(outneurons,perm = [1,0,2])[-1], n_outputs,activation_fn = None)
#在这里由于outneurons的维度为[batch_size,n_steps,n_inputs]的形式,而我们只需要最后一个cell对于所有batch的输出,因此把前两个维度调换一下,再取用[-1]取到最后一个cell对于所有batch的输出。shape为[batch_size,n_inputs]
#将其接到一层全连接网络作为分类器得到logitscross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels = Y_labels,logits = logits)
loss = tf.reduce_mean(cross_entropy)
#对logits用softmax做归一化,计算其对于样本labels的交叉熵的和,取均值作为损失函数lossoptimizer = tf.train.AdamOptimizer(learning_rate = learning_rate)
trainop = optimizer.minimize(loss)
#申请一个优化器,用来最后小化损失函数losscorrect = tf.equal(tf.argmax(logits,1),tf.argmax(Y_labels,1))
#分析正确率accuracy = tf.reduce_mean(tf.cast(correct,tf.float32))batch_size = 64
init = tf.global_variables_initializer()
with tf.Session() as sess:init.run()for i in range(10000):x_batch, y_batch = mnist.train.next_batch(batch_size)x_batch = x_batch.reshape([-1,n_steps,n_inputs])sess.run(trainop,feed_dict = {X : x_batch,Y_labels : y_batch})if i % 200 == 0:print('train accuracy =',sess.run(accuracy,feed_dict = {X : x_batch,Y_labels : y_batch}))X_test = mnist.test.images.reshape((-1,n_steps,n_inputs))Y_test = mnist.test.labelsprint('test accuracy =',sess.run(accuracy,feed_dict = {X : X_test,Y_labels : Y_test}))
评估
实验表明求得得准确率可达到99%。
疑问
我将BasicLSTMCell换成BasicRNNCell就无法训练,这是为什么呢?难道跟LSTM有遗忘们相关吗?