RNN递归神经网络

一、代码步骤

1.导入相应的包

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

2.数据集导入以及其他参数制定

#载入数据集
mnist=input_data.read_data_sets("MNIST_data/",one_hot=True)

#输入图片是28*28
#图片不是28*28嘛,那样的话,每次输入28个像素,需要输入28次,这就是下面两个变量的意思
n_inputs=28#输入一行,一行有28个数据
max_time=28#一共28行
lstm_size=100#100个隐层单元
n_classes=10#10个分类
batch_size=50#每批次50个样本
n_batch=mnist.train.num_examples//batch_size#计算一共有多少个批次

#这里的none表示第一个维度可以是任意的长度
x=tf.placeholder(tf.float32,[None,784])
#正确的标签
y=tf.placeholder(tf.float32,[None,10])

#初始化权值
weights=tf.Variable(tf.truncated_normal([lstm_size,n_classes],stddev=0.1))#[100,10]
#初始化偏置值
biases=tf.Variable(tf.constant(0.1,shape=[n_classes]))

3.定义RNN网络

#定义RNN网络
def RNN(X,weights,biases):
    #inputs=[batch_size,max_time,n_inputs]
    inputs=tf.reshape(X,[-1,max_time,n_inputs])#50*784  =》50*28*28
    #定义LSTM基本CELL   基础的LSTM循环网络单元
    #__init__(

#     num_units,
#
#     forget_bias=1.0,
#
#     state_is_tuple=True,
#
#     activation=None,
#
#     reuse=None,
#
#     name=None,
#
#     dtype=None
#
# )
#     num_units: int类型,LSTM单元中的神经元数量,即输出神经元数量
#     forget_bias: float类型,偏置增加了忘记门。从CudnnLSTM训练的检查点(checkpoin)
#     恢复时,必须手动设置为0.0。
#     state_is_tuple: 如果为True,则接受和返回的状态是c_state和m_state的2 - tuple;如果为False,则他们沿着列轴连接。后一种即将被弃用。
#     activation: 内部状态的激活函数。默认为tanh
#     reuse: 布尔类型,描述是否在现有范围中重用变量。如果不为True,并且现有范围已经具有给定变量,则会引发错误。
#     name: String类型,层的名称。具有相同名称的层将共享权重,但为了避免错误,在这种情况下需要reuse = True.
#     dtype: 该层默认的数据类型。默认值为None表示使用第一个输入的类型。在call之前build被调用则需要该参数。
    lstm_cell=tf.nn.rnn_cell.BasicLSTMCell(lstm_size)#n_neurons=lstm_size=100
    #final_state[0]是cell state
    #final_state[1]是hidden_state 与最后的输出有关


    #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
# )

    # inputs:[50*28*28]即[batch_size,step,input_size]
    #按照规定,outputs是最后一层的输出,即为[batch_size,step,n_neurons]n_neurons是神经元的个数
    #按照规定,final_state是每一层的最后一个step的输出,其实本程序只是用了一个隐藏层,因为是LSTM长短时记忆网络,所以因此我们的states包含1个LSTMStateTuple,
    # 每一个表示每一层的最后一个step的输出,这个输出有两个信息,一个是h表示短期记忆信息,一个是c表示长期记忆信息。尺寸为[batch_size,n_neurons]
    #所以,ouputs是[50,28,100],final_state每个LSTMStateTuple都包含c,h两个矩阵,都是[50*100]
    #给大家举例看一个形状:这里的[batch_size,step,n_neurons]是[4,2,5]   h c的尺寸分别是[4,5]
    #outputs_val:
    # [[[1.2949290e-04 0.0000000e+00 2.7623639e-04 0.0000000e+00 0.0000000e+00]
    #   [9.4675866e-05 0.0000000e+00 2.0214770e-04 0.0000000e+00 0.0000000e+00]]
    #
    # [[4.3100454e-06 4.2123037e-07 1.4312843e-06 0.0000000e+00 0.0000000e+00]
    # [0.0000000e+00
    # 0.0000000e+00
    # 0.0000000e+00
    # 0.0000000e+00
    # 0.0000000e+00]]
    #
    # [[0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]
    #  [0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]]
    #
    # [[0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]
    #  [0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]]]
    #
    # states_val:
    # (LSTMStateTuple(
    #     c=array([[0., 0., 0.04676079, 0.04284539, 0.],
    #              [0., 0., 0.0115245, 0., 0.],
    #              [0., 0., 0., 0., 0.],
    #              [0., 0., 0., 0., 0.]],
    #             dtype=float32),
    #     h=array([[0., 0., 0.00035096, 0.04284406, 0.],
    #              [0., 0., 0.00142574, 0., 0.],
    #              [0., 0., 0., 0., 0.],
    #              [0., 0., 0., 0., 0.]],
    #             dtype=float32)),
    #  LSTMStateTuple(
    #      c=array([[0.0000000e+00, 1.0477135e-02, 4.9871090e-03, 8.2785974e-04,
    #                0.0000000e+00],
    #               [0.0000000e+00, 2.3306280e-04, 0.0000000e+00, 9.9445322e-05,
    #                5.9535629e-05],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00]], dtype=float32),
    #      h=array([[0.00000000e+00, 5.23016974e-03, 2.47756205e-03, 4.11730434e-04,
    #                0.00000000e+00],
    #               [0.00000000e+00, 1.16522635e-04, 0.00000000e+00, 4.97301044e-05,
    #                2.97713632e-05],
    #               [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
    #                0.00000000e+00],
    #               [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
    #                0.00000000e+00]], dtype=float32)),
    #  LSTMStateTuple(
    #      c=array([[1.8937115e-04, 0.0000000e+00, 4.0442235e-04, 0.0000000e+00,
    #                0.0000000e+00],
    #               [8.6200516e-06, 8.4243663e-07, 2.8625946e-06, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00]], dtype=float32),
    #      h=array([[9.4675866e-05, 0.0000000e+00, 2.0214770e-04, 0.0000000e+00,
    #                0.0000000e+00],
    #               [4.3100454e-06, 4.2123037e-07, 1.4312843e-06, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00]], dtype=float32))
    #  - --------------------
    #  版权声明:本文为CSDN博主「小T是我」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
    # 原文链接:https: // blog.csdn.net / junjun150013652 / article / details / 81331448
    outputs,final_state=tf.nn.dynamic_rnn(lstm_cell,inputs,dtype=tf.float32)
    #所以final_state[1]代表的就是LSTMStateTuple里的h,final_state[0]代表的是c
    results=tf.matmul(final_state[1],weights)+biases#返回[50,10]
    return results

4.损失函数、优化器、准确率

#计算RNN的返回结果
prediction=RNN(x,weights,biases)
#损失函数
cross_entropy=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=prediction,labels=y))
#使用AdamOptimizer进行优化
train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#结果存放在一个布尔型列表中
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
#求准确率
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
#初始化
init=tf.global_variables_initializer()

5.开始训练

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(6):
        for batch in range(n_batch):
            batch_xs,batch_ys=mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})
        acc=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
        print("Iter "+str(epoch)+", Testing Accuracy= "+str(acc))

二、流程介绍

我们是分批次导入的数据,每批次导入50个样本,然后将样本reshape成为[50,28,28],即[batch_size,step,input_size],定义100个lstm神经元,即n_neurons=100。重点是下面这一句:

outputs,final_state=tf.nn.dynamic_rnn(lstm_cell,inputs,dtype=tf.float32)

关于tf.nn.dynamic_run()函数,

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
)
第一个参数是神经元,第二个参数是咱们输入的矩阵是50*28*28([batch_size,step,input_size]),这个函数的第一个返回值outputs是最后一层的输出,返回值格式为[batch_size,step,n_neurons]是[50,28,100],本次我们只用了一个隐藏层,所以就是这一层是输出,而final_state是每一层最后一个step的输出,本次只有一个隐藏层,所以只返回一个LSTMStateTuple,如果有多个层,则返回多个。而每个LSTMStateTuple则包括两个矩阵,h表示短期记忆信息,c表示长期记忆信息,每个矩阵的尺寸为[batch_size,n_neurons],即[50,100]。
    #给大家举例看一个形状:这里的[batch_size,step,n_neurons]是[4,2,5]   h c的尺寸分别是[4,5]
    #outputs_val:
    # [[[1.2949290e-04 0.0000000e+00 2.7623639e-04 0.0000000e+00 0.0000000e+00]
    #   [9.4675866e-05 0.0000000e+00 2.0214770e-04 0.0000000e+00 0.0000000e+00]]
    #
    # [[4.3100454e-06 4.2123037e-07 1.4312843e-06 0.0000000e+00 0.0000000e+00]
    # [0.0000000e+00
    # 0.0000000e+00
    # 0.0000000e+00
    # 0.0000000e+00
    # 0.0000000e+00]]
    #
    # [[0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]
    #  [0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]]
    #
    # [[0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]
    #  [0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]]]
    #
    # states_val:
    # (LSTMStateTuple(
    #     c=array([[0., 0., 0.04676079, 0.04284539, 0.],
    #              [0., 0., 0.0115245, 0., 0.],
    #              [0., 0., 0., 0., 0.],
    #              [0., 0., 0., 0., 0.]],
    #             dtype=float32),
    #     h=array([[0., 0., 0.00035096, 0.04284406, 0.],
    #              [0., 0., 0.00142574, 0., 0.],
    #              [0., 0., 0., 0., 0.],
    #              [0., 0., 0., 0., 0.]],
    #             dtype=float32)),
    #  LSTMStateTuple(
    #      c=array([[0.0000000e+00, 1.0477135e-02, 4.9871090e-03, 8.2785974e-04,
    #                0.0000000e+00],
    #               [0.0000000e+00, 2.3306280e-04, 0.0000000e+00, 9.9445322e-05,
    #                5.9535629e-05],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00]], dtype=float32),
    #      h=array([[0.00000000e+00, 5.23016974e-03, 2.47756205e-03, 4.11730434e-04,
    #                0.00000000e+00],
    #               [0.00000000e+00, 1.16522635e-04, 0.00000000e+00, 4.97301044e-05,
    #                2.97713632e-05],
    #               [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
    #                0.00000000e+00],
    #               [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
    #                0.00000000e+00]], dtype=float32)),
    #  LSTMStateTuple(
    #      c=array([[1.8937115e-04, 0.0000000e+00, 4.0442235e-04, 0.0000000e+00,
    #                0.0000000e+00],
    #               [8.6200516e-06, 8.4243663e-07, 2.8625946e-06, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00]], dtype=float32),
    #      h=array([[9.4675866e-05, 0.0000000e+00, 2.0214770e-04, 0.0000000e+00,
    #                0.0000000e+00],
    #               [4.3100454e-06, 4.2123037e-07, 1.4312843e-06, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00],
    #               [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
    #                0.0000000e+00]], dtype=float32))

所以在这里,final_state[1]是h,final_state[0]是c,返回的都是一个[50,100]的矩阵。

综上所述,outputs返回的是一个[50,28,100],final_state返回的是一个[50,100]的矩阵。

tf.matmul(final_state[1],weights)+biases返回的就是一个[50,10]的结果标签矩阵。每一行都是一个一维独热编码矩阵,只有分类结果为1,其他都为0,后面的代码就比较好理解了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CtrlZ1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值