为什么会有tf.nn.dynamic_rnn和tf.nn.static_rnn,首先理解time_step是干什么的。
举例说明:
batch_size=1000
,time_steps=25
,input_size=300
。batch_size=6000
,time_steps=28
,input_size=28
,我们可以理解为把图片图片分成28份,每份shape=(1, 28)。在tensorflow中,可以通过tf.nn.rnn_cell.BasicLSTMCell
构建LSTM,最常使用的参数是num_units
,表示的是LSTM中隐含状态的维度。
lstm_cell=tf.nn.rnn_cell.BasicLSTMCell(num_units=hidden_size)
LSTM的输入不仅有数据输入,还有前一个时刻的状态输入,因此需要初始化输入状态。
initial_state=lstm_cell.zero_state(batch_size,dtype=tf.float32)
构建多层LSTM,其中hidden_layer_num为LSTM的层数
cell = tf.nn.rnn_cell.MultiRNNCell([lstm_cell]*hidden_layer_num)
构建LSTM完整代码如下:
import tensorflow as tf
import numpy as np
batch_size=2
hidden_size=64
num_steps=10
input_dim=8
input=np.random.randn(batch_size,num_steps,input_dim)
input[1,6:]=0
x=tf.placeholder(dtype=tf.float32,shape=[batch_size,num_steps,input_dim],name='input_x')
lstm_cell=tf.nn.rnn_cell.BasicLSTMCell(num_units=hidden_size)
initial_state=lstm_cell.zero_state(batch_size,dtype=tf.float32)
outputs=[]
with tf.variable_scope('RNN'):
for i in range(num_steps):
if i > 0 :
# print(tf.get_variable_scope())
tf.get_variable_scope().reuse_variables()
output=lstm_cell(x[:,i,:],initial_state)
outputs.append(output)
从上面可以看出,要想获得num_steps后的output结果,需要for循环进行迭代。此时可以通过dynamic_rnn和static_rnn两个函数进行简化,让他们去做循环的工作。
tf.nn.static_rnn(
cell,
inputs,
initial_state=None,
dtype=None,
sequence_length=None,
scope=None
)
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
)
总结:基础的RNNCell有一个很明显的问题:对于单个的RNNCell,使用它的call函数进行运算时,只是在序列时间上前进了一个step。比如使用x1、h0得到h1,通过x2、h1得到h2等。这样的话,如果序列长度为10,就要调用10次call函数,比较麻烦。对此,TensorFlow提供了一个tf.nn.dynamic_rnn和tf.nn.static_rnn函数,使用该函数就相当于调用了n次call函数。即通过{h0,x1, x2, …., xn}直接得{h1,h2…,hn}。
dynamic_rnn | static_rnn | |
---|---|---|
input shape | 【batch_size,time_step(序列长度),input-dim】 | 【time_steps,batch_size,input_dim】 |
output shape | 【batch_size,n_steps,n_hidden】 | 【n_steps,batch_size,n_hidden |
time_step是否可以不同 | 可以 | 不可以 |
其中,需要注意
特别注意:对应dyanmic_rnn里有个参数是time_major,如果设置对应为true,则我们对应输入为【time_step,batch_size,input_dim】,对应输出也是如此;而如果设置为false,则对应我们如下的代码不需要改动
。#在此假设输入的mnist数据X_in对应为【batch_size,time_steps,input_dim】,则对应lstm的构建为
cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden_units,forget_bias=1.0,state_is_tuple=True)
init_state = cell.zero_state(batch_size,dtype=tf.float32)
outputs,final_state = tf.nn.dynamic_rnn(cell,X_in,initial_state=init_state,time_major=False)
#对应若是要取最后的数据,则需要进行转置,将n_steps维度提到前面来
outputs = tf.transpose(outputs,[1,0,2])
last_output = outputs[-1]
需要是一个list
,也就是说是一个【】形式,每个list对应的都是一个time_steps(序列)。输出shape对应为【n_steps,batch_size,n_hidden】,因此对应输出最后一个output[-1]
即为我们需要的值。'''还有一种方法,可以转换为list(忽略其中的加入输入层部分)
_X = tf.transpose(_X, [1, 0, 2]) # permute n_steps and batch_size
_X = tf.reshape(_X, [-1, n_inputs]) # (n_steps*batch_size, n_input)
_X = tf.matmul(_X, weights['in']) + biases['in']
lstm_cell =tf.nn.rnn_cell.BasicLSTMCell(n_hidden_unis, forget_bias=1.0) _init_state=lstm_cell.zero_state(batch_size,dtype=tf.float32)
_X = tf.split(_X, n_step,0 ) # n_steps * (batch_size, n_hidden) #得到我们对应想要的list
##上方的axis 默认是为0的 所以可写可不写
outputs, states =tf.nn.static_rnn(lstm_cell, _X, initial_state=_init_state)
'''
input=tf.unstack(x ,time_steps,1)
lstm_layer=rnn.BasicLSTMCell(num_units,forget_bias=1)
outputs,_=rnn.static_rnn(lstm_layer,input,dtype="float32")