如何批量写TFRecords?

时间:2018-02-21 16:16:26

标签: python tensorflow file-writing

我有一个大约有4000万行的CSV。每行都是一个训练实例。根据{{​​3}}我正在尝试编码并将数据保存在TFRecord文件中。

我找到的所有示例(the documentation on consuming TFRecords)都表明创建TFRecord的过程取决于类TFRecordWriter。该类有一个方法write,它将数据的序列化字符串表示作为输入,并将其写入磁盘。但是,这似乎是一次完成一个训练实例。

如何编写一批序列化数据?

让我说我有一个功能:

  def write_row(sentiment, text, encoded):
    feature = {"one_hot": _float_feature(encoded),
               "label": _int64_feature([sentiment]),
               "text": _bytes_feature([text.encode()])}

    example = tf.train.Example(features=tf.train.Features(feature=feature))
    writer.write(example.SerializeToString())

写入磁盘4000万次(每个示例一次)将非常慢。批量处理这些数据并一次编写50k或100k示例(就机器的资源允许而言)更有效。但是,在TFRecordWriter中似乎没有任何方法可以做到这一点。

有些事情:

class MyRecordWriter:

  def __init__(self, writer):
    self.records = []
    self.counter = 0
    self.writer = writer

  def write_row_batched(self, sentiment, text, encoded):
    feature = {"one_hot": _float_feature(encoded),
               "label": _int64_feature([sentiment]),
               "text": _bytes_feature([text.encode()])}

    example = tf.train.Example(features=tf.train.Features(feature=feature))
    self.records.append(example.SerializeToString())
    self.counter += 1
    if self.counter >= 10000:
      self.writer.write(os.linesep.join(self.records))
      self.counter = 0
      self.records = []

但是当读取此方法创建的文件时,我收到以下错误:

tensorflow/core/framework/op_kernel.cc:1192] Invalid argument: Could not parse example input, value: '
��

label

��
one_hot����
��

注意:我可以更改编码过程,以便每个example proto包含数千个示例,而不仅仅是一个但是 我不希望以这种方式写入TFrecord文件时预先批量处理数据,因为当我想使用该文件进行不同批量大小的培训时,它会在我的培训管道中引入额外的开销。

1 个答案:

答案 0 :(得分:3)

TFRecords是二进制格式。使用以下行,您将其视为文本文件:self.writer.write(os.linesep.join(self.records))

这是因为您使用的操作取决于linesep\n\r\n)。

解决方案: 只需写下记录。您要求批量编写它们。您可以使用缓冲的编写器。对于4000万行,您可能还需要考虑将数据拆分为单独的文件以实现更好的并行化。

使用TFRecordWriter时:文件已缓存。

证据可以在消息来源中找到:

  • tf_record.py来电pywrap_tensorflow.PyRecordWriter_New
  • PyRecordWriter来电Env::Default()->NewWritableFile
  • Env->NewWritableFile在匹配的FileSystem上调用NewWritableFile
  • e.g。 PosixFileSystem来电fopen
  • fopen返回一个“默认情况下已完全缓冲的流,如果已知它不引用交互式设备”
  • 这将取决于文件系统,但WritableFile注意“实现必须提供缓冲,因为调用者可能会一次向文件追加小片段。”