Python 用于训练和推理的tf.data.Dataset可反馈迭代器
我有一个TensorFlow模型,它使用tf.data.Dataset feedable迭代器在训练和验证之间切换。两个数据集共享相同的结构,即它们有一个特征矩阵和相应的标签向量。为了使用相同的模型和迭代器进行推理(无标签向量仅featurex矩阵),理想情况下,我需要提供零标签向量。是否有一种更高效、更优雅的方法来使用dataset API进行培训(验证)和推理 代码:Python 用于训练和推理的tf.data.Dataset可反馈迭代器,python,tensorflow,tensorflow-datasets,Python,Tensorflow,Tensorflow Datasets,我有一个TensorFlow模型,它使用tf.data.Dataset feedable迭代器在训练和验证之间切换。两个数据集共享相同的结构,即它们有一个特征矩阵和相应的标签向量。为了使用相同的模型和迭代器进行推理(无标签向量仅featurex矩阵),理想情况下,我需要提供零标签向量。是否有一种更高效、更优雅的方法来使用dataset API进行培训(验证)和推理 代码: training_dataset = tf.data.Dataset.from_tensor_slices((X_train
training_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
validation_dataset = tf.data.Dataset.from_tensor_slices((X_validation, y_validation))
handle = tf.placeholder(tf.string, shape=[])
iterator = tf.data.Iterator.from_string_handle(handle, training_dataset.output_types, training_dataset.output_shapes)
features, labels = iterator.get_next()
特征和标签在模型内部用作输入占位符。
为了在数据集之间切换,我需要为每个数据集创建一个迭代器:
training_iterator = training_dataset.make_initializable_iterator()
validation_iterator = validation_dataset.make_initializable_iterator()
然后创建句柄
training_handle = sess.run(training_iterator.string_handle())
validation_handle = sess.run(validation_iterator.string_handle())
并使用句柄
选择要使用的数据集,例如:
sess.run(next_element, feed_dict={handle: training_handle})
现在,如果我有没有标签的推断数据会发生什么
inference_dataset = tf.data.Dataset.from_tensor_slices(X_inference) # NO y values
inferece_iterator = inference_dataset.make_initializable_iterator()
如果我添加这个迭代器,它将抛出和异常,因为“组件的数量不匹配:预期为2个类型,但得到1个。”
有什么建议吗
这篇文章与这个问题有关,但是tf.data.Dataset没有解压方法
解决此问题的最佳做法是什么 如果您的图形代码,我假设您正在尝试从数据集中提取标签
y
的值,对吗?在推理时,这可能被烘焙到tensorflow依赖关系图中
你有几个选择。最简单的解决方案可能是从代码中重新创建图形(运行build\u graph()
函数,然后使用类似saver.restore(sess,“/tmp/model.ckpt”)
的方法加载权重)。如果这样做,则可以在不使用标签的情况下重新创建图形y
。我假设在y
上没有其他依赖项(有时tensorboard摘要也会添加您需要检查的依赖项)。你的问题现在应该解决了
然而,现在我已经写了上面的评论(我将原封不动地留下,因为它仍然是有用的信息),我意识到你可能甚至不需要它。在推断时,您不应该在任何地方使用标签(再次检查张力板摘要)。如果不需要
y
,则tensorflow不应运行任何使用y
的操作。这应该包括不尝试从数据集中提取它们。仔细检查您是否没有要求tensorflow在推断时在任何地方使用标签。我认为David Parks提出的第一个解决方案是这样的,我认为这比在代码中混用tf.cond要好
import tensorflow as tf
import numpy as np
def build_model(features, labels=None, train=False):
linear_model = tf.layers.Dense(units=1)
y_pred = linear_model(features)
if train:
loss = tf.losses.mean_squared_error(labels=labels, predictions=y_pred)
optimizer = tf.train.GradientDescentOptimizer(1e-4)
train = optimizer.minimize(loss)
return train, loss
else:
return y_pred
X_train = np.random.random(100).reshape(-1, 1)
y_train = np.random.random(100).reshape(-1, 1)
training_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
training_dataset = training_dataset.batch(10)
training_dataset = training_dataset.shuffle(20)
handle = tf.placeholder(tf.string, shape=[])
iterator = tf.data.Iterator.from_string_handle(handle, training_dataset.output_types, training_dataset.output_shapes)
features, labels = iterator.get_next()
training_iterator = training_dataset.make_one_shot_iterator()
train, loss = build_model(features, labels, train=True)
saver = tf.train.Saver()
init = tf.global_variables_initializer()
sess = tf.Session()
training_handle = sess.run(training_iterator.string_handle())
sess.run(init)
for i in range(10):
_, loss_value = sess.run((train, loss), feed_dict={handle: training_handle})
print(loss_value)
saver.save(sess, "tmp/model.ckpt")
sess.close()
tf.reset_default_graph()
X_test = np.random.random(10).reshape(-1, 1)
inference_dataset = tf.data.Dataset.from_tensor_slices(X_test)
inference_dataset = inference_dataset.batch(5)
handle = tf.placeholder(tf.string, shape=[])
iterator_inference = tf.data.Iterator.from_string_handle(handle, inference_dataset.output_types, inference_dataset.output_shapes)
inference_iterator = inference_dataset.make_one_shot_iterator()
features_inference = iterator_inference.get_next()
y_pred = build_model(features_inference)
saver = tf.train.Saver()
sess = tf.Session()
inference_handle = sess.run(inference_iterator.string_handle())
saver.restore(sess, "tmp/model.ckpt") # Restore variables from disk.
print(sess.run(y_pred, feed_dict={handle: inference_handle}))
sess.close()
谢谢你的回答,但是问题不是我在图中使用了
y
。如果使用feed_dict,则使用相同的图形,它工作正常(仅将X作为输入传递)。当我尝试使用迭代器时,会出现这个错误,它期望底层数据集有两个组件X
和y
。所以我想知道,是否可以在生产中使用迭代器和数据集进行训练和推理,而推理数据集只有X
?在图形运行时,如果该组件未使用,它不应该尝试从迭代器中提取第二个组件。至少我希望是这样。也许您正在重建图形并试图从迭代器中提取2个值,在这种情况下,一个简单的基于python的if
语句应该可以解决这个问题。另一种解决方案可能是显式命名dataset元素。这应该是相当简单的事情,只是某个细节。问题是否发生在图形运行时(在sess.run
)或构建图形时(例如在python land中)?它发生在图形运行时。您能否提供第二种解决方案的示例,即明确命名数据集元素?这是一个与命名数据集中元素相关的问题:如果是图形出错,您也可以尝试实现tf.cond
,尽管我觉得有一个更干净的解决方案: