【问题标题】:How to use tensorflow's Dataset API Iterator as an input of a (recurrent) neural network?如何使用 tensorflow 的 Dataset API Iterator 作为(循环)神经网络的输入?
【发布时间】:2018-05-03 18:02:03
【问题描述】:

当使用 tensorflow 的 Dataset API 迭代器时,我的目标是定义一个 RNN,它在迭代器的 get_next() 张量上运行作为其输入(参见代码中的 (1))。

但是,简单地将dynamic_rnn 定义为get_next() 作为其输入会导致错误: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) 在代码中)。 但是,如果我理解正确,这不是一个有效的解决方案,因为我们首先评估然后重新初始化张量。

有没有办法:

  1. 直接在迭代器的输出之上定义dynamic_rnn

或:

  1. 以某种方式直接将现有的get_next() 张量传递给作为dynamic_rnn 输入的占位符?

完整的工作示例; (1) 版本是我想要工作的,但它没有,而(2) 是有效的解决方法。

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。)

非常感谢:)

【问题讨论】:

  • 这与您的问题无关,但您的代码帮助我弄清楚在将“数据集”中的元素提供给 session.run 时应该使用 eval()。谢谢!

标签: tensorflow rnn tensorflow-datasets


【解决方案1】:

原来这个神秘的错误很可能是 tensorflow 中的一个错误,请参阅https://github.com/tensorflow/tensorflow/issues/14729。更具体地说,错误确实来自输入错误的数据类型(在我上面的示例中,data 数组包含 int32 值,但它应该包含浮点数)。

而不是得到ValueError: Initializer for variable rnn/basic_lstm_cell/kernel/ is from inside a control-flow construct 错误,
tensorflow 应该返回:
TypeError: Tensors in list passed to 'values' of 'ConcatV2' Op have types [int32, float32] that don't all match.(参见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)

然后下面的代码应该可以正常工作了:

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()})

【讨论】:

  • 为什么输出的形状是(1,3,8)?有 3 个观察结果。
  • 看看dynamic_rnn returns1是batch size(因为我们只在一个batch上定义,next_batch),3是一个batch内的时间戳数,8是RNN单元数。
  • 但在您的示例中,您在实例中批处理了 2 个观察结果。
  • 啊,你是对的,没注意到。在这种情况下,形状将是(2,3,8)。你从哪里得到(1,3,8)
  • 您给出的最小工作示例将o 的形状吐出为(1,3,8)
猜你喜欢
  • 2018-10-27
  • 1970-01-01
  • 2016-08-18
  • 2016-08-12
  • 1970-01-01
  • 2016-11-12
  • 2017-06-13
  • 1970-01-01
  • 2017-02-19
相关资源
最近更新 更多