如何使用 tensorflow 的 Dataset API Iterator 作为(循环)神经网络的输入? [英] How to use tensorflow's Dataset API Iterator as an input of a (recurrent) neural network?
问题描述
当使用 tensorflow 的 Dataset API Iterator 时,我的目标是定义一个 RNN,该 RNN 将迭代器的 get_next()
张量作为其输入(参见 (1)
in代码).
When using the tensorflow's Dataset API Iterator, my goal is to define an RNN that operates on the iterator's get_next()
tensors as its input (see (1)
in the code).
然而,简单地将 dynamic_rnn
定义为 get_next()
作为其输入会导致错误:ValueError: Initializer for variable rnn/basic_lstm_cell/kernel/是从控制流结构内部,例如循环或条件.在循环或条件中创建变量时,使用 lambda 作为初始值设定项.
However, simply defining the dynamic_rnn
with get_next()
as its input results in an error: ValueError: Initializer for variable rnn/basic_lstm_cell/kernel/ is from inside a control-flow construct, such as a loop or conditional. When creating a variable inside a loop or conditional, use a lambda as the initializer.
现在我知道一种解决方法是简单地为 next_batch
创建一个占位符然后 eval()
张量(因为你不能传递张量本身)和使用 feed_dict
传递它(参见代码中的 X
和 (2)
).但是,如果我理解正确,这不是一个有效的解决方案,因为我们首先评估然后重新初始化张量.
Now I know that one workaround is to simply create a placeholder for next_batch
and then eval()
the tensor (because you can't pass the tensor itself) and pass it using feed_dict
(see X
and (2)
in the code).
However, if I understand it correctly, this is not an efficient solution as we first evaluate and then reinitialize the tensor.
有没有办法:
- 直接在迭代器的输出之上定义
dynamic_rnn
;
或:
- 不知何故直接将现有的
get_next()
张量传递给作为dynamic_rnn
输入的占位符?
- Somehow directly pass the existing
get_next()
tensor to the placeholder that is the input ofdynamic_rnn
?
完整的工作示例;(1)
版本是我想要的,但它没有,而 (2)
是可行的解决方法.
Full working example; the (1)
version is what I would like to work but it doesn't, while (2)
is the workaround that does work.
import tensorflow as tf
from tensorflow.contrib.rnn import BasicLSTMCell
from tensorflow.python.data import Iterator
data = [ [[1], [2], [3]], [[4], [5], [6]], [[1], [2], [3]] ]
dataset = tf.data.Dataset.from_tensor_slices(data)
dataset = dataset.batch(2)
iterator = Iterator.from_structure(dataset.output_types,
dataset.output_shapes)
next_batch = iterator.get_next()
iterator_init = iterator.make_initializer(dataset)
# (2):
X = tf.placeholder(tf.float32, shape=(None, 3, 1))
cell = BasicLSTMCell(num_units=8)
# (1):
# outputs, states = lstm_outputs, lstm_states = tf.nn.dynamic_rnn(cell, next_batch, dtype=tf.float32)
# (2):
outputs, states = lstm_outputs, lstm_states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
sess.run(iterator_init)
# (1):
# o, s = sess.run([outputs, states])
# o, s = sess.run([outputs, states])
# (2):
o, s = sess.run([outputs, states], feed_dict={X: next_batch.eval()})
o, s = sess.run([outputs, states], feed_dict={X: next_batch.eval()})
(使用 tensorflow 1.4.0,Python 3.6.)
(Using tensorflow 1.4.0, Python 3.6.)
非常感谢:)
推荐答案
原来这个神秘的错误很可能是 tensorflow 中的一个 bug,参见 https://github.com/tensorflow/tensorflow/issues/14729.更具体地说,错误实际上是由于提供了错误的数据类型(在我上面的示例中,data
数组包含 int32
值,但它应该包含浮点数).
Turns out the mysterious error is likely a bug in tensorflow, see https://github.com/tensorflow/tensorflow/issues/14729. More specifically, the error really comes from feeding a wrong data type (in my example above, the data
array contains int32
values but it should contain floats).
不是得到 ValueError: Initializer for variable rnn/basic_lstm_cell/kernel/is from inside a control-flow structure
错误,
张量流应该返回:TypeError: 列表中的张量传递给 'ConcatV2' Op 的 'values' 的类型 [int32, float32] 并不完全匹配.
(请参阅 1).
Instead of getting the ValueError: Initializer for variable rnn/basic_lstm_cell/kernel/ is from inside a control-flow construct
error,
tensorflow should return:
TypeError: Tensors in list passed to 'values' of 'ConcatV2' Op have types [int32, float32] that don't all match.
(see 1).
要解决此问题,只需更改data = [ [[1], [2], [3]], [[4], [5], [6]], [[1], [2], [3]] ]代码>
到data = np.array([[ [1], [2], [3]], [[4], [5], [6]], [[1], [2], [3]] ], dtype=np.float32)
To fix this problem, simply change
data = [ [[1], [2], [3]], [[4], [5], [6]], [[1], [2], [3]] ]
to
data = np.array([[ [1], [2], [3]], [[4], [5], [6]], [[1], [2], [3]] ], dtype=np.float32)
然后下面的代码应该可以正常工作:
and then the following code shall work properly:
import tensorflow as tf
import numpy as np
from tensorflow.contrib.rnn import BasicLSTMCell
from tensorflow.python.data import Iterator
data = np.array([[ [1], [2], [3]], [[4], [5], [6]], [[1], [2], [3]] ], dtype=np.float32)
dataset = tf.data.Dataset.from_tensor_slices(data)
dataset = dataset.batch(2)
iterator = Iterator.from_structure(dataset.output_types,
dataset.output_shapes)
next_batch = iterator.get_next()
iterator_init = iterator.make_initializer(dataset)
# (2):
# X = tf.placeholder(tf.float32, shape=(None, 3, 1))
cell = BasicLSTMCell(num_units=8)
# (1):
outputs, states = lstm_outputs, lstm_states = tf.nn.dynamic_rnn(cell, next_batch, dtype=tf.float32)
# (2):
# outputs, states = lstm_outputs, lstm_states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
sess.run(iterator_init)
# (1):
o, s = sess.run([outputs, states])
o, s = sess.run([outputs, states])
# (2):
# o, s = sess.run([outputs, states], feed_dict={X: next_batch.eval()})
# o, s = sess.run([outputs, states], feed_dict={X: next_batch.eval()})
这篇关于如何使用 tensorflow 的 Dataset API Iterator 作为(循环)神经网络的输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!