TFRecord是TensorFlow中常用的数据打包格式。通过将训练数据或测试数据打包成TFRecord文件,就可以配合TF中相关的DataLoader / Transformer等API实现数据的加载和处理,便于高效地训练和评估模型。
TF官方tutorial:TFRecord and tf.Example
组成TFReocrd的砖石:tf.Example
tf.Example
是一个Protobuffer定义的message,表达了一组string到bytes value的映射。TFRecord文件里面其实就是存储的序列化的tf.Example
。如果对Protobuffer不熟悉,可以去看下Google的文档和教程。
Example 是什么
我们可以具体到相关代码去详细地看下tf.Example
的构成。作为一个Protobuffer message,它被定义在文件core/example/example.proto中:
1 | message Example { |
好吧,原来只是包了一层Features
的message。我们还需要进一步去查找Features
的message定义:
1 | message Features { |
到这里,我们可以看出,tf.Example
确实表达了一组string到Feature的映射。其中,这个string表示feature name,后面的Feature又是一个message。继续寻找:
1 | // Containers for non-sequential data. |
看起来,是描述了一组各种数据类型的list,包括二进制字节流,float或者int64的数值列表。
属于自己的Example
有了上面的分解,要想构造自己数据集的tf.Example
,就可以一步步组合起来。
首先用下面的几个帮助函数,将给定的Python类型数据转换为对应的Feature。
1 | # The following functions can be used to convert a value to a type compatible |
有了Feature
,就可以组成Features
,只要把对应的名字作为string传进去就行了。
1 | features_dict = {'image': _bytes_feature(image_data), 'label': _int64_feature(label)} |
Example
自然也就有了:
1 | example = tf.train.Example(features=features) |
TFRecord
TFRecord是一个二进制文件,只能顺序读取。它的数据打包格式如下:
1 | uint64 length |
其中,data[length]
通常是一个Example
序列化之后的数据。
将Example
写入TFRecord
可以使用python API,将Example
proto写入TFRecord文件。
1 | with tf.io.TFRecordWriter(filename) as writer: |
读取TFRecord中的Example
通过tf.data.TFRecordDataset
得到Dataset
,然后遍历它,并反序列化,就可以得到原始数据。下面的代码段从TFRecord文件中读取刚刚写入的image:
1 | def parse_from_single_example(example_proto): |
或者可以用map
来将parser的pipeline应用于原dataset:
1 | # 注意这里不能用get_image_from_single_example |