将TFRecord示例的目录集成到模型培训中

时间:2017-11-06 21:29:06

标签: python tensorflow tfrecord

为了训练Tensorflow模型,从多个TFRecord文件提供数据的最有效方法是什么?使用我当前的流程,我迭代TFRecords中的示例,分别将示例提取到Python变量中,但我不相信这是做到这一点的正确方法。

我正在从Keras迁移到Tensorflow,希望在我的工作流程中看到一些速度提升。为此,我已将数据移至TFRecord,现在我正在尝试了解如何使用TFRecord文件目录运行基本线性回归模型。我已经达到了这样的程度,我可以将TFRecord读入Tensor并批量训练(代码取自Tensorflow入门示例,然后进行修改):

# Model parameters
W = tf.Variable([.1], dtype=tf.float32)
b = tf.Variable([.1], dtype=tf.float32)

# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W*x + b
y = tf.placeholder(tf.float32)

# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.1)
train = optimizer.minimize(loss)


# Transforms a scalar string `example_proto` into a pair of a scalar string and
# a scalar integer, representing an image and its label, respectively.
def _parse_function(example_proto):
    keys_to_features = {
        "X": tf.FixedLenFeature([40], tf.float32),
        "Y": tf.FixedLenFeature([10], tf.float32)
    }
    example = tf.parse_single_example(example_proto, keys_to_features)
    return example["X"][0], example["Y"][0]

filenames = tf.placeholder(tf.string, shape=[None])
dataset   = tf.data.TFRecordDataset(filenames, "ZLIB")
dataset   = dataset.map(_parse_function)
dataset   = dataset.repeat()
dataset   = dataset.batch(1024)
iterator  = dataset.make_initializable_iterator()
next_element = iterator.get_next()

# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
sess.run(iterator.initializer, feed_dict = { filenames: training_filenames })
for i in range(10):
    **x_train, y_train = sess.run(iterator.get_next())**
    sess.run(train, {x: x_train, y: y_train})

我的问题是我不相信这符合Tensorflow可能的,最有效的数据集工作流程。特别是,将数据从二进制文件提取到python变量然后将其提供给训练过程有什么意义呢? (下面一行)

    **x_train, y_train = sess.run(iterator.get_next())**

我的印象是应该有一种方法可以将二进制数据提供给会话以便更直接地进行培训,但在阅读了TF教程,示例和其他堆栈溢出帖子后,我找不到任何内容。

1 个答案:

答案 0 :(得分:2)

数据集API非常灵活多变。它可以像你一样用作字典输入。但是,更好的方法是将数据集合并到图表中,并使其一次处理。

def model_function(input, label)
   # Model parameters
   W = tf.Variable([None, input.shape[1]], dtype=tf.float32)
   b = tf.Variable([input.shape[1]], dtype=tf.float32)

   # Model input and output
   x = input
   linear_model = W*x + b
   y = label

   # loss
   loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares
   # optimizer
   optimizer = tf.train.GradientDescentOptimizer(0.1)
   train = optimizer.minimize(loss)

   return train


---<Previous dataset related code>---

iterator.make_initializable_iterator()
next_example, next_label = iterator.get_next()

train_op = model_function(next_example, next label)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for steps in range(1000):
        _ = sess.run([train_op], feeddict={filenames: training_filenames})

这样,数据集操作就是主图的一部分。这也将更好地使用数据集的排队结构。由于只使用了一个sess.run,因此运行函数的开销最小化。

有关详细信息,请查看文档的这一部分:Importing data | Tensorflow 1.4

如果需要训练在图形运行时指定的文件名,则只能在feeddict中指定该占位符。但是,我建议不要这样做。文件名相当静态。我会使用资源文件,如config.py,并将所有配置属性放在该文件中。然后在图形构造上加载文件名。

要指定文件名,有两种方法。 第一个:

...
filenames = tf.constant([filename1.tfrecords, filename2.tfrecords], dtype=tf.String)
dataset = tf.data.Dataset(filenames, "ZLIB")
...

否则更合适的方法是在主文件夹中创建一个名为resources的新目录,在其中放置并清空__init__.py文件,另一个名为config.py。 在config.py中:

--- inside config.py ---

FILENAMES = ["filename1.tfrecord", "filename2.tfrecord"]

在正在创建数据集的主张量流函数内:

--- inside tensorflow file ---

from resources import config

...
filenames = tf.constant(config.FILENAMES, dtype=tf.String)
dataset = tf.data.Dataset(filenames, "ZLIB")
...