如何在TensorFlow中实现指定维度的基础LSTM网络及疑问解答
Hey Roman, let's walk through each of your questions using the TensorFlow code you provided—this will make things much clearer!
疑问1:为何要预设时间步数量?LSTM能否接受任意长度的序列?
The short answer: 预设时间步是因为你用了tf.contrib.rnn.static_rnn,这个API属于TensorFlow的静态RNN实现,它会在图构建阶段就固定每一个时间步的计算节点。你的代码里timesteps=18,所以它会预先创建18个LSTM步的计算图,自然要求输入序列的长度必须匹配这个预设值。
但LSTM本身完全可以处理任意长度的序列!你只需要换用动态RNN实现——也就是tf.nn.dynamic_rnn。它不需要提前固定时间步,而是在运行时根据输入序列的实际长度动态展开计算图,还支持同一个批次里的样本有不同的序列长度(配合sequence_length参数)。如果用dynamic_rnn,你甚至不需要tf.unstack这一步,直接把三维张量X喂进去就行。
疑问2:为何要按时间步拆分数据(使用unstack)?
这还是和static_rnn的API要求有关:它的输入必须是一个长度等于时间步的列表,列表里每个元素是对应单个时间步的输入张量(形状为[batch_size, num_input])。你的原始输入X是三维张量[None, timesteps, num_input](批次大小×时间步×特征数),所以tf.unstack(X, timesteps, 1)会沿着第二个维度(时间步维度)把它拆成18个二维张量,每个张量对应一个时间步的所有样本输入,刚好符合static_rnn的输入要求。
还是那句话,如果换成dynamic_rnn,这个拆分步骤完全可以省略——dynamic_rnn直接支持三维输入张量,内部会自动处理时间步的展开。
疑问3:如何解读‘outputs’和‘states’?
Let's break down what these two variables hold in your code:
outputs: 这是一个长度等于时间步数量的列表(你这里是18个元素)。每个元素对应一个时间步的LSTM隐层输出(h_t),形状为[batch_size, num_units](你的例子里就是[12,4])。把这些元素拼接起来,就得到了你想要的N×4隐层向量序列(N=18)。states: 这是LSTMCell返回的最终状态元组,格式为(c_state, h_state):c_state是LSTM的细胞状态(cell state),形状为[batch_size, num_units],它是LSTM内部用来长期记忆信息的载体,这里只返回最后一个时间步的细胞状态。h_state是最后一个时间步的隐层输出,和outputs列表的最后一个元素完全相同,形状也是[batch_size, num_units]。
注意:static_rnn不会返回所有时间步的细胞状态序列,如果需要获取每个时间步的c_t,你要么改用dynamic_rnn并自己跟踪状态,要么手动循环调用LSTMCell的__call__方法来收集每一步的细胞状态。
内容的提问来源于stack exchange,提问作者Roman

