tf.dynamic_rnn
tensorflow 的dynamic_rnn,我们用一个小例子来说明其用法,假设你的RNN的输入input是[2,3,4],其中2是batch_size,3是文本最大长度,一般叫num_steps或者seq_length,4是embedding_size。我们假设第二个文本长度只有2,剩下的1个是使用0-padding方法填充的。dynamic_rnn返回的是两个参数:outputs,last_states,其中outputs是[2,3,4],也就是每一个迭代隐状态的输出,它包括了训练中所有隐层状态,而last_states是由(c,h)组成的tuple,大小均为[batch,hidden_size]也就是[2,2]。
到这里并没有什么不同,但是dynamic有个参数:sequence_length,这个参数用来指定每个example的长度,比如上面的例子中,我们令 sequence_length为[3,2],表示第一个example有效长度为3,第二个example有效长度为2,当我们传入这个参数的时候,对于第二个batch,TensorFlow对于2以后的padding就不计算了,其last_states将重复第2步的last_states直至第3步,而outputs中超过第2步的结果将会被置零。
具体看代码和输出:
import tensorflow as tf import numpy as np # 产生2个batch数据,句子length为3,embedding大小为4 X = np.random.randn(2, 3, 4) # 第二个batch长度为2 X[1,2:] = 0 X_lengths = [3, 2] print(X) # cell = tf.contrib.rnn.BasicLSTMCell(num_units=64, state_is_tuple=True) cell=tf.nn.rnn_cell.BasicLSTMCell(num_units=2,state_is_tuple=True) outputs, last_states = tf.nn.dynamic_rnn( cell=cell, dtype=tf.float64, sequence_length=X_lengths, inputs=X) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) o=sess.run(outputs) s=sess.run(last_states) print('output\n',o) print('last_o\n',o[:,-1,:])# 从output中取最后一次输出 print('--------------------') print('s\n',s) print('s.c\n',s.c) # 这是门控单元的权重,这里不需要 print('s.h\n',s.h) #s.h就是最后一次输出的状态
产生以下输出:
首先能看到第二个句子最后一行全是0,说明句子长度为2,后面的0相当于pading上的。
然后经过LSTM产生两个输出,output和state
在output中,发现第二个句子经过训练后,最后产生的状态全是0,但是在state中用s.h能找到其最后一次输出不是0,而是与output中最后一次不是0的一致,如下面加上高亮的几个数,这些输出是一样的。所以如果想用dynamic_rnn得到输出后,只需要最后一次的状态输出,直接调用s.h即可。