TensorFlow 仅在使用 MultiRNNCell 时抛出错误
TensorFlow throws error only when using MultiRNNCell
我正在使用旧版序列到序列框架在 TensorFlow 1.0.1 中构建编码器-解码器模型。当我在编码器和解码器中有一层 LSTM 时,一切正常。但是,当我尝试使用包裹在 MultiRNNCell
中的 >1 层 LSTM 时,调用 tf.contrib.legacy_seq2seq.rnn_decoder
.
时出现错误
完整的错误在这个 post 的最后,但简而言之,它是由一行
引起的
(c_prev, m_prev) = state
在 TensorFlow 中抛出 TypeError: 'Tensor' object is not iterable.
。我对此感到困惑,因为我传递给 rnn_decoder
的初始状态确实应该是一个元组。据我所知,使用 1 层或 >1 层之间的唯一区别是后者涉及使用 MultiRNNCell
。使用此功能时我应该了解一些 API 怪癖吗?
这是我的代码(基于 this GitHub 存储库中的示例)。为它的长度道歉;这是我能做到的最小限度,同时仍然是完整和可验证的。
import tensorflow as tf
import tensorflow.contrib.legacy_seq2seq as seq2seq
import tensorflow.contrib.rnn as rnn
seq_len = 50
input_dim = 300
output_dim = 12
num_layers = 2
hidden_units = 100
sess = tf.Session()
encoder_inputs = []
decoder_inputs = []
for i in range(seq_len):
encoder_inputs.append(tf.placeholder(tf.float32, shape=(None, input_dim),
name="encoder_{0}".format(i)))
for i in range(seq_len + 1):
decoder_inputs.append(tf.placeholder(tf.float32, shape=(None, output_dim),
name="decoder_{0}".format(i)))
if num_layers > 1:
# Encoder cells (bidirectional)
# Forward
enc_cells_fw = [rnn.LSTMCell(hidden_units)
for _ in range(num_layers)]
enc_cell_fw = rnn.MultiRNNCell(enc_cells_fw)
# Backward
enc_cells_bw = [rnn.LSTMCell(hidden_units)
for _ in range(num_layers)]
enc_cell_bw = rnn.MultiRNNCell(enc_cells_bw)
# Decoder cell
dec_cells = [rnn.LSTMCell(2*hidden_units)
for _ in range(num_layers)]
dec_cell = rnn.MultiRNNCell(dec_cells)
else:
# Encoder
enc_cell_fw = rnn.LSTMCell(hidden_units)
enc_cell_bw = rnn.LSTMCell(hidden_units)
# Decoder
dec_cell = rnn.LSTMCell(2*hidden_units)
# Make sure input and output are the correct dimensions
enc_cell_fw = rnn.InputProjectionWrapper(enc_cell_fw, input_dim)
enc_cell_bw = rnn.InputProjectionWrapper(enc_cell_bw, input_dim)
dec_cell = rnn.OutputProjectionWrapper(dec_cell, output_dim)
_, final_fw_state, final_bw_state = \
rnn.static_bidirectional_rnn(enc_cell_fw,
enc_cell_bw,
encoder_inputs,
dtype=tf.float32)
# Concatenate forward and backward cell states
# (The state is a tuple of previous output and cell state)
if num_layers == 1:
initial_dec_state = tuple([tf.concat([final_fw_state[i],
final_bw_state[i]], 1)
for i in range(2)])
else:
initial_dec_state = tuple([tf.concat([final_fw_state[-1][i],
final_bw_state[-1][i]], 1)
for i in range(2)])
decoder = seq2seq.rnn_decoder(decoder_inputs, initial_dec_state, dec_cell)
tf.global_variables_initializer().run(session=sess)
这是错误:
Traceback (most recent call last):
File "example.py", line 67, in <module>
decoder = seq2seq.rnn_decoder(decoder_inputs, initial_dec_state, dec_cell)
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/contrib/legacy_seq2seq/python/ops/seq2seq.py", line 150, in rnn_decoder
output, state = cell(inp, state)
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/contrib/rnn/python/ops/core_rnn_cell_impl.py", line 426, in __call__
output, res_state = self._cell(inputs, state)
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/contrib/rnn/python/ops/core_rnn_cell_impl.py", line 655, in __call__
cur_inp, new_state = cell(cur_inp, cur_state)
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/contrib/rnn/python/ops/core_rnn_cell_impl.py", line 321, in __call__
(c_prev, m_prev) = state
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 502, in __iter__
raise TypeError("'Tensor' object is not iterable.")
TypeError: 'Tensor' object is not iterable.
谢谢!
问题出在传递给 seq2seq.rnn_decoder
的初始状态 (initial_dec_state
) 的格式中。
当您使用 rnn.MultiRNNCell
时,您正在构建多层循环网络,因此您需要为这些层中的 每个 层提供初始状态。
因此,您应该提供一个 list 元组作为初始状态,其中列表的每个元素都是来自循环网络相应层的前一个状态。
所以你的 initial_dec_state
,像这样初始化:
initial_dec_state = tuple([tf.concat([final_fw_state[-1][i],
final_bw_state[-1][i]], 1)
for i in range(2)])
应该是这样的:
initial_dec_state = [
tuple([tf.concat([final_fw_state[j][i],final_bw_state[j][i]], 1)
for i in range(2)]) for j in range(len(final_fw_state))
]
它创建一个元组列表,格式如下:
[(state_c1, state_m1), (state_c2, state_m2) ...]
更详细地说,'Tensor' object is not iterable.
错误的发生是因为 seq2seq.rnn_decoder
在内部调用您的 rnn.MultiRNNCell
(dec_cell
) 传递初始状态 (initial_dec_state
)
rnn.MultiRNNCell.__call__
遍历初始状态列表,并为每个初始状态提取元组 (c_prev, m_prev)
(在语句 (c_prev, m_prev) = state
中)。
所以如果你只传递一个元组,rnn.MultiRNNCell.__call__
将遍历它,一旦它到达 (c_prev, m_prev) = state
它就会找到一个张量(应该是一个元组)作为 state
并会抛出 'Tensor' object is not iterable.
错误。
了解 seq2seq.rnn_decoder
期望的初始状态格式的一个好方法是调用 dec_cell.zero_state(batch_size, dtype=tf.float32)
。此方法 returns 以初始化您正在使用的循环模块所需的确切格式填零状态张量。
我正在使用旧版序列到序列框架在 TensorFlow 1.0.1 中构建编码器-解码器模型。当我在编码器和解码器中有一层 LSTM 时,一切正常。但是,当我尝试使用包裹在 MultiRNNCell
中的 >1 层 LSTM 时,调用 tf.contrib.legacy_seq2seq.rnn_decoder
.
完整的错误在这个 post 的最后,但简而言之,它是由一行
引起的(c_prev, m_prev) = state
在 TensorFlow 中抛出 TypeError: 'Tensor' object is not iterable.
。我对此感到困惑,因为我传递给 rnn_decoder
的初始状态确实应该是一个元组。据我所知,使用 1 层或 >1 层之间的唯一区别是后者涉及使用 MultiRNNCell
。使用此功能时我应该了解一些 API 怪癖吗?
这是我的代码(基于 this GitHub 存储库中的示例)。为它的长度道歉;这是我能做到的最小限度,同时仍然是完整和可验证的。
import tensorflow as tf
import tensorflow.contrib.legacy_seq2seq as seq2seq
import tensorflow.contrib.rnn as rnn
seq_len = 50
input_dim = 300
output_dim = 12
num_layers = 2
hidden_units = 100
sess = tf.Session()
encoder_inputs = []
decoder_inputs = []
for i in range(seq_len):
encoder_inputs.append(tf.placeholder(tf.float32, shape=(None, input_dim),
name="encoder_{0}".format(i)))
for i in range(seq_len + 1):
decoder_inputs.append(tf.placeholder(tf.float32, shape=(None, output_dim),
name="decoder_{0}".format(i)))
if num_layers > 1:
# Encoder cells (bidirectional)
# Forward
enc_cells_fw = [rnn.LSTMCell(hidden_units)
for _ in range(num_layers)]
enc_cell_fw = rnn.MultiRNNCell(enc_cells_fw)
# Backward
enc_cells_bw = [rnn.LSTMCell(hidden_units)
for _ in range(num_layers)]
enc_cell_bw = rnn.MultiRNNCell(enc_cells_bw)
# Decoder cell
dec_cells = [rnn.LSTMCell(2*hidden_units)
for _ in range(num_layers)]
dec_cell = rnn.MultiRNNCell(dec_cells)
else:
# Encoder
enc_cell_fw = rnn.LSTMCell(hidden_units)
enc_cell_bw = rnn.LSTMCell(hidden_units)
# Decoder
dec_cell = rnn.LSTMCell(2*hidden_units)
# Make sure input and output are the correct dimensions
enc_cell_fw = rnn.InputProjectionWrapper(enc_cell_fw, input_dim)
enc_cell_bw = rnn.InputProjectionWrapper(enc_cell_bw, input_dim)
dec_cell = rnn.OutputProjectionWrapper(dec_cell, output_dim)
_, final_fw_state, final_bw_state = \
rnn.static_bidirectional_rnn(enc_cell_fw,
enc_cell_bw,
encoder_inputs,
dtype=tf.float32)
# Concatenate forward and backward cell states
# (The state is a tuple of previous output and cell state)
if num_layers == 1:
initial_dec_state = tuple([tf.concat([final_fw_state[i],
final_bw_state[i]], 1)
for i in range(2)])
else:
initial_dec_state = tuple([tf.concat([final_fw_state[-1][i],
final_bw_state[-1][i]], 1)
for i in range(2)])
decoder = seq2seq.rnn_decoder(decoder_inputs, initial_dec_state, dec_cell)
tf.global_variables_initializer().run(session=sess)
这是错误:
Traceback (most recent call last):
File "example.py", line 67, in <module>
decoder = seq2seq.rnn_decoder(decoder_inputs, initial_dec_state, dec_cell)
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/contrib/legacy_seq2seq/python/ops/seq2seq.py", line 150, in rnn_decoder
output, state = cell(inp, state)
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/contrib/rnn/python/ops/core_rnn_cell_impl.py", line 426, in __call__
output, res_state = self._cell(inputs, state)
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/contrib/rnn/python/ops/core_rnn_cell_impl.py", line 655, in __call__
cur_inp, new_state = cell(cur_inp, cur_state)
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/contrib/rnn/python/ops/core_rnn_cell_impl.py", line 321, in __call__
(c_prev, m_prev) = state
File "/home/tao/.virtualenvs/example/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 502, in __iter__
raise TypeError("'Tensor' object is not iterable.")
TypeError: 'Tensor' object is not iterable.
谢谢!
问题出在传递给 seq2seq.rnn_decoder
的初始状态 (initial_dec_state
) 的格式中。
当您使用 rnn.MultiRNNCell
时,您正在构建多层循环网络,因此您需要为这些层中的 每个 层提供初始状态。
因此,您应该提供一个 list 元组作为初始状态,其中列表的每个元素都是来自循环网络相应层的前一个状态。
所以你的 initial_dec_state
,像这样初始化:
initial_dec_state = tuple([tf.concat([final_fw_state[-1][i],
final_bw_state[-1][i]], 1)
for i in range(2)])
应该是这样的:
initial_dec_state = [
tuple([tf.concat([final_fw_state[j][i],final_bw_state[j][i]], 1)
for i in range(2)]) for j in range(len(final_fw_state))
]
它创建一个元组列表,格式如下:
[(state_c1, state_m1), (state_c2, state_m2) ...]
更详细地说,'Tensor' object is not iterable.
错误的发生是因为 seq2seq.rnn_decoder
在内部调用您的 rnn.MultiRNNCell
(dec_cell
) 传递初始状态 (initial_dec_state
)
rnn.MultiRNNCell.__call__
遍历初始状态列表,并为每个初始状态提取元组 (c_prev, m_prev)
(在语句 (c_prev, m_prev) = state
中)。
所以如果你只传递一个元组,rnn.MultiRNNCell.__call__
将遍历它,一旦它到达 (c_prev, m_prev) = state
它就会找到一个张量(应该是一个元组)作为 state
并会抛出 'Tensor' object is not iterable.
错误。
了解 seq2seq.rnn_decoder
期望的初始状态格式的一个好方法是调用 dec_cell.zero_state(batch_size, dtype=tf.float32)
。此方法 returns 以初始化您正在使用的循环模块所需的确切格式填零状态张量。