TensorFlow利用单向RNN实现手写数字识别

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/BigDream123/article/details/99993452
#coding:utf-8
import  tensorflow as tf
from  tensorflow.examples.tutorials.mnist import  input_data
from tensorflow.contrib import  rnn

mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)

train_rate=0.001
# 学习速率,超参数
train_step=1000
batch_size=1280
#  每批样本数,rnn也可以使用随机梯度下降进行训练,一批批的灌数据进去,而不是每一次把整个数据集都灌进去
display_step=100

sequence_length=28
# 每个样本序列的长度
frame_size=28
# 序列里面每一个分量的大小,因为每个分量都是一行像素,而一行像素有28个像素点

hidden_num=100
# 隐层神经元个数

n_classes=10
# 类别数

#定义输入,输出
x=tf.placeholder(dtype=tf.float32,shape=[None,sequence_length*frame_size],name="inputx")
y=tf.placeholder(dtype=tf.float32,shape=[None,n_classes],name="expected_y")

#定义权值
weights=tf.Variable(tf.truncated_normal(shape=[hidden_num,n_classes]))
bias=tf.Variable(tf.zeros(shape=[n_classes]))

# 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)
# 将单向的rnn沿时间序列展开
# 参数:
# cell:需要传入tf.nn.rnn_cell空间下的某一类rnn的实例
# 在本实践中我们传入了tf.nn.rnn_cell.BasicRNNCell(hidden_num),一个包含hidden_num个隐层单元的基本RNN单元。
# 如果 time_major == False (default)
# input的形状必须为 [batch_size, sequence_length, frame_size]
# 如果 time_major == True
# input输入的形状必须为 [sequence_length, batch_size, frame_size]
# batch_size是批大小,sequence_length是每个序列的大小,而frame_size是序列里面每个分量的大小
# sequence_length:序列的长度,如果指定了这个参数,那么tf会对长度不够的输入在尾部填0。
# initial_state:初始化状态 (可选), 需要是一个[batch_size, cell.state_size]形状的tensor.一般初始化为0。
# 函数返回:
# 一个 outputs, state的tuple:
# 其中:
# outputs: RNN输出tensor:
# 如果 time_major == False (default),outputs的形状为:[batch_size, sequence_length, hidden_num]
# 如果 time_major == True,outputs的形状: [sequence_length, batch_size, cell.output_size].其中cell是刚刚传入的第一个参数的cell.
# state: 最后的状态. 是[batch_size, cell.state_size]. 的形状。

# 这里还补充一点,就是叫dynamic的原因
# 就是输入数据的time_step不一定要相同,如果长短不一,会自动跟短的补0,但是处理时候,不会处理0,在0前面就截止了
# 这就是dynamic对比static的好处.


# 简单RNN
# tf.nn.rnn_cell.BasicRNNCell(num_units,activation=None,reuse=None):
# 参数:
# num_units: int,隐层个数。
# activation: 非线性激活函数 默认: tanh.
# reuse: (optional) 不理

# LSTM RNN
# tf.nn.rnn_cell.BasicLSTMCell(num_units,forget_bias=1.0,state_is_tuple=True,activation=None,reuse=None)
# 参数:
# num_units: int, 隐层个数.
# forget_bias: float, 遗忘门的阈值.
# state_is_tuple: 
# If True, accepted and returned states are 2-tuples of the c_state and m_state. 
# If False, they are concatenated along the column axis. The latter behavior will soon be deprecated.
# activation:非线性激活函数,默认: tanh.
# reuse: 暂时不管



def RNN(x,weights,bias):
    x=tf.reshape(x,shape=[-1,sequence_length,frame_size])
    # 先把输入转换为dynamic_rnn接受的形状:batch_size,time_steps,input_size这样子的
    # 其中batch_size表示batch的大小。time_steps序列长度,input_size输入数据单个序列单个时间维度上固有的长度
    # 得到的outputs是time_steps步里所有的输出
    rnn_cell=tf.nn.rnn_cell.BasicRNNCell(hidden_num)
    # 生成hidden_num个隐层的RNN网络,rnn_cell.output_size等于隐层个数
    # state_size也是等于隐层个数,但是对于LSTM单元来说这两个size又是不一样的。

    init_state=tf.zeros(shape=[batch_size,rnn_cell.state_size])
    # 其实这是一个深度RNN网络,对于每一个长度为n的序列[x1,x2,x3,...,xn]的每一个xi,都会在深度方向跑一遍RNN,跑上hidden_num个隐层单元
    
    output,states=tf.nn.dynamic_rnn(rnn_cell,x,dtype=tf.float32)
    # 此时output就是一个[batch_size,time_steps,hidden_num]形状的tensor
    
    return tf.nn.softmax(tf.matmul(output[:,-1,:],weights)+bias,1)
    # 我们取出最后每一个序列的最后一个分量的输出output[:,-1,:],它的形状为[batch_size,hidden_num]
    # 也就是:[batch_size,hidden_num]所以它可以和weights相乘
    # 这就是2.5中weights的形状初始化为[hidden_num,n_classes]的原因。然后再经softmax归一化
    # return (batch_size,n_classes)
    
predy=RNN(x,weights,bias)
# 获得以x为输入,weights,bias为偏置的概率分布
# 返回结果是[batch_size,n_classes]的形状,表示batch里面的每个样本的预测输出
cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=predy,labels=y))
# 使用交叉熵计算残差
train=tf.train.AdamOptimizer(train_rate).minimize(cost)
# 定义优化器
correct_pred=tf.equal(tf.argmax(predy,1),tf.argmax(y,1))
accuracy=tf.reduce_mean(tf.to_float(correct_pred))
# 定义准确率

sess=tf.Session()
# 启动sess
sess.run(tf.initialize_all_variables())
# 初始化变量
step=1
testx,testy=mnist.test.next_batch(batch_size)

while step<train_step:
    batch_x,batch_y=mnist.train.next_batch(batch_size)
#    batch_x=tf.reshape(batch_x,shape=[batch_size,sequence_length,frame_size])
    _loss,__=sess.run([cost,train],feed_dict={x:batch_x,y:batch_y})
    if step % display_step ==0:
        
        acc,loss=sess.run([accuracy,cost],feed_dict={x:testx,y:testy})
        print("第{}步,准确率{},损失:{}".format(step,acc,loss))

    step+=1

猜你喜欢

转载自blog.csdn.net/BigDream123/article/details/99993452