最近在使用tensorflow搭建seq2seq模型,本来encoder层使用tf.nn.dynamic_rnn时是没有问题的,但是换成tf.nn.bidirectional_dynamic_rnn后,出现了如下错误:
TypeError: Tensor objects are only iterable when eager execution is enabled. To iterate over this tensor use tf.map_fn.
经过一番调研发现,错误的原因在于decoder层的tf.nn.dynamic_rnn(),这个函数有一个参数initial_state,当改成双向LSTM后,这个参数的传递值格式是错误的!
那为什么原来使用单向lstm的时候,states没有错,而换成双向lstm后就不对了呢?
原因:
我们定义lstm_cell时,有个参数是state_is_tuple,这个参数的默认值是True,接下来的分析也都基于这个参数是True来讨论。也就是说states本身就是个tuple,格式为(c,h),其中c代表传递值,h代表输出值,c/h的维度均为(batchsize, rnnsize)
我们的decoder中肯定是使用单向lstm tf.nn.dynamic_rnn(),它的参数initial_state需要的格式就是(c,h)
当我们的encoder使用 tf.nn.dynamic_rnn()时,它返回的states就是一个元组(c,h),这正是decoder需要的初始状态。
然而当我们的encoder使用tf.nn.bidirectional_dynamic_rnn时,它返回的states是二维元组,格式为((c_forward,h_forward),(c_back,h_back))
所以如果你想使用tf.concat()直接对前向和后向的state进行拼接时,格式就是错误的。
正确的做法:
先使用tf.concat()将前向和后向的c/h拼接, 再使用tf.contrib.rnn.LSTMStateTuple()函数将他们合成一个tensorflow tuple
output,states= tf.nn.bidirectional_dynamic_rnn(self.lstm_fw_cell, self.lstm_bw_cell, q_feature,sequence_length = self.sentence_length,dtype=tf.float32)
output = tf.concat(output,axis=-1)#batch,len,2*rnnsize
states_c = tf.concat([states[0][0],states[1][0]],axis=-1)#batch,2*rnnsize
states_h = tf.concat([states[0][1],states[1][1]],axis=-1)
return output,tf.contrib.rnn.LSTMStateTuple(states_c,states_h)
建议大家还是把tensorflow中cell、lstm的各种参数过一下!参考 https://blog.csdn.net/cerisier/article/details/80135999