这里不介绍RNN与RNN的特殊情形LSTM,因为内容过多。

一、相关函数介绍

 

1、创建Cell:

tf.nn.rnn_cell.BasicRNNCell(num_units)

  • num_units:创建的神经元个数。

 

2、创建由 RNNCellcell指定的递归神经网络,执行inputs的完全动态展开(即对单个Cell执行动态展开):

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 )

  • cell:RNNCell的一个实例.。
  • inputs:RNN输入.如果time_major == False(默认),则是一个shape为[batch_size, max_time, ...]的Tensor,或者这些元素的嵌套元组.如果time_major == True,则是一个shape为[max_time, batch_size, ...]的Tensor,或这些元素的嵌套元组.这也可能是满足此属性的Tensors(可能是嵌套的)元组.前两个维度必须匹配所有输入,否则秩和其他形状组件可能不同.在这种情况下,在每个时间步输入到cell将复制这些元组的结构,时间维度(从中获取时间)除外.在每个时间步输入到个cell将是一个Tensor或(可能是嵌套的)Tensors元组,每个元素都有维度[batch_size, ...]。
  • sequence_length:(可选)大小为[batch_size]的int32/int64的向量.超过批处理元素的序列长度时用于复制状态和零输出.所以它更多的是正确性而不是性能.。
  • initial_state:(可选)RNN的初始状态.如果cell.state_size是整数,则必须是具有适当类型和shape为[batch_size, cell.state_size]的Tensor.如果cell.state_size是一个元组,则应该是张量元组,在cell.state_size中为s设置shape[batch_size, s]。
  • dtype:(可选)初始状态和预期输出的数据类型.如果未提供initial_state或RNN状态具有异构dtype,则是必需的。
  • parallel_iterations:(默认值:32).并行运行的迭代次数.适用于那些没有任何时间依赖性并且可以并行运行的操作.该参数用于交换空间的时间.远大于1的值会使用更多内存但占用更少时间,而较小值使用较少内存但计算时间较长。
  • swap_memory:透明地交换推理中产生的张量,但是需要从GPU到CPU的支持.这允许训练通常不适合单个GPU的RNN,具有非常小的(或没有)性能损失。
  • time_major:inputs和outputsTensor的形状格式.如果是true,则这些 Tensors的shape必须为[max_time, batch_size, depth].如果是false,则这些Tensors的shape必须为[batch_size, max_time, depth].使用time_major = True更有效,因为它避免了RNN计算开始和结束时的转置.但是,大多数TensorFlow数据都是batch-major,因此默认情况下,此函数接受输入并以batch-major形式发出输出。
  • scope:用于创建子图的VariableScope;默认为“rnn”.

注意:这里要注意传入的参数inputs的shape。函数返回结果为一个tuple:(outputs, state)。

outputs:

  • 对应Cell的输出h(非Cell状态细胞状态C),记录的是所有批次所有序列所有神经元的输出。
  • 如果time_major == False(默认),这将是shape为[batch_size, max_time, cell.output_size]Tensor。如果time_major == True,这将是shape为[max_time, batch_size, cell.output_size]Tensor。cell。batch_size:批次数;max_time:序列集的序列个数,cell.output_size即循环网络神经元的个数,由inputs的神经元个数决定。
  • 假设我们有时间序列的循环神经网络,100批次,50个时间点,100个神经元,则默认shape情况下根据batch_size、max_time切片可以得到特定批次、特定时间点的cell.output_size神经元的输出,如outoputs[0,24,99]表示1批次25时间点的数据传入后Cell的输出h(x)。

state:

  • 记录最后一个序列传入之后计算得到的输出,一般情况下state的形状为 [batch_size, cell.output_size ]。
  • 但当输入的cell为BasicLSTMCell时,state的形状为[2,batch_size, cell.output_size ],其中2也对应着LSTM中的cell state和hidden state。如,state[0]:表示最后一个序列传入后的Cell_state,即最后一个序列传入后的细胞状态。state[1]:表示最后一个序列传后的hidden_state,即最后一个序列传后的Cell的输出。

更具体的可以查看:

二、代码示例

 



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

# 读取数据
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)

# 由于mnist数据是28*28的数据,所以可以看成28个序列,每个序列为1*28的数据,这样就构造了一个序列数据
n_input = 1 * 28  # 输入序列集中列数据属性数
max_time = 28  # 每次输入序列数据的序列个数
lstm_size = 100  # lstm的隐藏层的神经元个数为100
n_class=10 #手写字最终分为0-9一共10类
batch_size = 50  # 批次个数为50
n_batch = mnist.train.num_examples // batch_size  # 计算有几个批次

#输入与标签占位符
x=tf.placeholder(tf.float32,[None,784])
y=tf.placeholder(tf.float32,[None,10])

#权重与偏置,这里是最后估计值的y'=Wh+b
weights = tf.Variable(tf.random_normal([lstm_size, n_class]))
biases = tf.Variable(tf.constant(0.1),[n_class])

#定义一个RNN网络
def RNN(x,weights,biases):

    #输入x转化为固定形式数据
    inputs=tf.reshape(x,[-1,max_time,n_input])

    #定义基本的lstm的cell
    lstm_cell=tf.contrib.rnn.BasicLSTMCell(lstm_size)
    
    #定义动态的rnn网络
    outputs,final_state=tf.nn.dynamic_rnn(cell=lstm_cell,inputs=inputs,dtype=tf.float32,time_major=False)

    #计算估计值,这里不用激活函数,因为loss函数会调用softmax进行处理
    result=tf.matmul(final_state[1],weights)+biases

    return result

#计算拟合值
prediction=RNN(x,weights,biases)

#定义交叉熵损失函数
cross_entropy=tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction)

#使用Adam梯度下降法训练模型
train=tf.train.AdamOptimizer(0.001,0.9,0.999).minimize(cross_entropy)

# 初始化
init = tf.global_variables_initializer()

# 结果存放在bool型列表汇总
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))

# 计算准确度,并加入到总结指令
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

with tf.Session() as sess:
    sess.run(init)

    # 训练20代
    for epoch in range(20):
        # 每代对数据进行一轮minibatch
        for batch in range(n_batch):
            batch_x, batch_y = mnist.train.next_batch(batch_size)  # 每个循环读取batch_size大小批次的数据
            sess.run(train, feed_dict={x: batch_x, y: batch_y})
            acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})  # 用测试数据计算准确度
            if batch % 99 == 0:
                print('第%d代%d批次,准确率为%.6f' % (epoch + 1, batch + 1, acc))