tf.data.Dataset可反馈迭代器,用于训练和推理

时间:2019-03-04 22:25:54

标签: python tensorflow tensorflow-datasets

我有一个 TensorFlow 模型,该模型使用 tf.data.Dataset feedable 迭代器在训练和验证之间进行切换。两个数据集共享相同的结构,即它们具有特征矩阵和相应的标签矢量。为了使用相同的模型和迭代器进行推理(没有标签向量仅是Featurex矩阵),我需要理想地提供零标签向量。有没有更有效,更优雅的方法来使用数据集API进行训练(验证)和推理?

在代码中:

// ** EF6 **
public class IdeaConfiguration : EntityTypeConfiguration<Idea>
{
    public IdeaConfiguration()
    {
        ToTable("Ideas");
        HasKey(x => x.Id);

        HasMany(x => x.Reactions)
            .WithRequired()
            .Map(x => x.MapKey("IdeaId")); // This tells EF to use an IdeaId field on Reaction.
    }
}

// ** EF Core **
    public class IdeaConfiguration : IEntityTypeConfiguration<Idea>
    {
        void IEntityTypeConfiguration<Idea>.Configure(EntityTypeBuilder<Idea> builder)
        {
            builder.ToTable("Ideas");
            builder.HasKey(x => x.Id);

            builder.HasMany(x => x.Reactions)
                .WithOne()
                .HasForeignKey("IdeaId"); // Creates a shadow property for the association.
        }
    }

功能和标签在模型内部用作输入占位符。 为了在数据集之间切换,我需要为每个数据集创建一个迭代器:

In [1]: import pandas as pd

In [2]: s = pd.Series(range(10))

In [3]: s
Out[3]: 
0    0
1    1
2    2
3    3
4    4
5    5
6    6
7    7
8    8
9    9
dtype: int64

然后创建手柄

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

如果添加此迭代器,它将抛出异常,因为“组件数不匹配:预期2种类型,但得到1种”。 有什么建议吗?

此帖子How to use tf.Dataset design in both training and inferring?与该问题有关,但是tf.data.Dataset没有解压缩方法。

此问题的最佳做法是什么?

2 个答案:

答案 0 :(得分:0)

如果您的图形代码是我想您正在尝试从数据集中提取标签y的值,对吗?在推论时间,它可能被烘焙到张量流依赖图中。

您在这里有几种选择。可能最简单的解决方案是从代码中重新创建图形(运行您的build_graph()函数,然后使用类似saver.restore(sess, "/tmp/model.ckpt")的方式加载权重)。如果以这种方式进行操作,则可以重新创建没有标签y的图形。我假设y上没有其他依赖项(有时tensorboard摘要还会添加您需要检查的依赖项)。您的问题现在应该已经解决。

但是,既然我已经编写了上面的注释(由于它仍然是有用的信息,我将其保留不变),我意识到您甚至不需要它。在推论时,您不应在任何地方使用标签(再次,仔细检查张量板摘要)。如果您不需要y,则tensorflow不应运行任何使用y的操作。这应包括不尝试从数据集中提取它们。仔细检查您是否不要求tensorflow在推断时在任何地方使用标签。

答案 1 :(得分:0)

我认为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()