西大路网站建设公司,昆明seo优化,广东建设工程注册执业中心网站,应用制作下载揭秘关于TFRcord的五脏六腑 前言#xff1a;本篇文章将演示如何创建、解析和使用tf.Example消息#xff0c;以及如何在.tfrecord文件之间对tf.Example消息进行序列化、写入和读取。 教程讲解使用的都是结构化数据#xff0c;文章最后还会演示如果将图片写成.tfrecord文件本篇文章将演示如何创建、解析和使用tf.Example消息以及如何在.tfrecord文件之间对tf.Example消息进行序列化、写入和读取。 教程讲解使用的都是结构化数据文章最后还会演示如果将图片写成.tfrecord文件这在同个数据集用于不同模型情景之下非常有用。 官网文档是从讲原理然后再展现示例。我觉得这种方式很容易劝退小白因为原理晦涩难懂。这里先展示示例然后再肢解示例先总体再细分的思想 希望能让读者更容易理解和接受 一、如何将标量输入值变成协议消息
这里先不解释什么是协议消息先看示例后解释
# todo 导入相应工具包
import tensorflow as tfimport numpy as np
import IPython.display as display# todo 为了讲解模拟生成一些数据
# 这里准备生成10000个元素
n_observations int(1e4)# 随机生成10000个True和False布尔值
feature0 np.random.choice([False, True], n_observations)# 随机生成10000个0-5的整数
feature1 np.random.randint(0, 5, n_observations)# 随机生成10000个值是以下字符串的字符串
strings np.array([bcat, bdog, bchicken, bhorse, bgoat])
feature2 strings[feature1]# 随机生成10000个01正太分布数据数据是浮点型
feature3 np.random.randn(n_observations)# todo 下面分别演示将字符串类型标量、浮点型标量、整数型标量转换成协议消息
# todo 这些方法可以复制过去直接使用
def _bytes_feature(value):输入string / byte类型数据返回bytes_list类型的协议消息if isinstance(value, type(tf.constant(0))):value value.numpy() # BytesList wont unpack a string from an EagerTensor.return tf.train.Feature(bytes_listtf.train.BytesList(value[value])) # 先记住这个写法这个写法是TF官网推荐的写法def _float_feature(value):输入float / double类型数据返回float_list类型的协议消息return tf.train.Feature(float_listtf.train.FloatList(value[value]))def _int64_feature(value):输入bool / enum / int / uint.类型数据返回int64_list类型的协议消息return tf.train.Feature(int64_listtf.train.Int64List(value[value]))# todo 通过调用上面的方法可以做到将相应类型的标量转换成协议消息了
print(_bytes_feature(btest_string)) # 字符串
print(_bytes_feature(utest_bytes.encode(utf-8))) # 二进制bytesprint(_float_feature(np.exp(1))) # 浮点型自然数eprint(_int64_feature(True)) # 布尔型
print(_int64_feature(1)) # 整型结果如下。结果展示的就是协议消息的“样子”协议消息就是长这样协议消息对应的值就是value里面的值
bytes_list {value: test_string
}bytes_list {value: test_bytes
}float_list {value: 2.7182817459106445
}int64_list {value: 1
}int64_list {value: 1
}二、如何将协议消息变成二进制字符串
接着上面代码的延续先不解释什么是二进制字符串读者先阅读一遍代码的注释
# todo 将浮点型标量转成协议消息
feature _float_feature(np.exp(1))# todo 使用方法SerializeToString()将协议消息变成二进制字符串
string_010 feature.SerializeToString()print(string_010) # 结果是 b\x12\x06\n\x04T\xf8-
b\x12\x06\n\x04T\xf8-
就是二进制字符串的样子
你可以简单把它理解成字符串三、如何将协议消息变成字典协议消息
字典型的协议消息如下读者先看一遍代码的注释再进行理解一遍
# todo 构建不同类型的协议消息
bytes_fea _bytes_feature(btest_string) # 字符串协议消息float_fea _float_feature(np.exp(1)) # 浮点型协议消息int64_fea _int64_feature(1) # 整数型协议消息# todo 将协议消息变成字典型协议消息
dict_fea {featrue0:bytes_fea,featrue1:float_fea,featrue2:int64_fea,
}说明
dict_fea就是字典型协议消息其中字典的key可以顺便自己命名而字典的value就是协议消息字典型协议消息就是字典的value就是协议消息的字典
四、如何将字典协议消息变成二进制字符串
做法就是将字典协议消息转成特征消息因为特征消息是协议消息的一种所以可以将特征消息根据方法SerializeToString()变成二进制字符串
# todo 构建不同类型的协议消息
bytes_fea _bytes_feature(btest_string) # 字符串协议消息float_fea _float_feature(np.exp(1)) # 浮点型协议消息int64_fea _int64_feature(1) # 整数型协议消息# todo 将协议消息变成字典型协议消息
dict_fea {featrue0:bytes_fea,featrue1:float_fea,featrue2:int64_fea,
}# todo 将协议消息变成特征消息代码就是这么写的读者根据官网推荐这些写法这么写即可
example_proto tf.train.Example(featurestf.train.Features(featuredict_fea))# todo 将特征消息转成二进制字符串
bytes_string example_proto.SerializeToString()
print(bytes_string)结果如下。显示的就是字典协议消息的二进制字符串
b\nF\n\x1b\n\x08featrue0\x12\x0f\n\r\n\x0btest_string\n\x14\n\x08featrue1\x12\x08\x12\x06\n\x04T\xf8-\n\x11\n\x08featrue2\x12\x05\x1a\x03\n\x01\x01五、关于TFRecord文件各种疑问 什么是TFRecord文件 TFRecord 格式是一种用于存储二进制字符串记录序列的简单格式。 为什么要用TFRecord文件 通过tfrecord文件建立的数据管道Dataset对象读数的性能更好 TFRecord格式详细信息 TFRecord 文件包含一系列记录。该文件只能按顺序读取。 每条记录包含一个字节字符串用于数据有效负载外加数据长度以及用于完整性检查的 CRC32C使用 Castagnoli 多项式的 32 位 CRC哈希值。 每条记录会存储为以下格式 uint64 length uint32 masked_crc32_of_length byte data[length] uint32 masked_crc32_of_data将记录连接起来以生成文件。此处对 CRC 进行了说明且 CRC 的掩码为 masked_crc ((crc 15) | (crc 17)) 0xa282ead8ul注不需要在 TFRecord 文件中使用 tf.Example。tf.Example 只是将字典序列化为字节字符串的一种方法。文本行、编码的图像数据或序列化的张量使用 tf.io.serialize_tensor或在加载时使用 tf.io.parse_tensor。有关更多选项请参阅 tf.io 模块。
六、TFRecord文件如何存储数据
TFRecord文件存储的是二进制字符串二进制字符串由协议消息或者是字典协议消息生成协议消息又由标量或者是向量生成。
所以TFRecord存储的二进制字符串相当于存储了真实的数据
之所以要通过协议消息、字典协议消息来存储这些数据是因为这样子可以提高数据的复用率和使用效率
七、将numpy数据存储成TFRecord格式文件
读者可以直接阅读代码的注释.从上往下阅读即可不需要觉得很难
# todo 导入相应工具包
import tensorflow as tfimport numpy as np
import IPython.display as display# todo 为了讲解模拟生成一些数据
# 这里准备生成10000个元素
n_observations int(1e4)# 随机生成10000个True和False布尔值
feature0 np.random.choice([False, True], n_observations)# 随机生成10000个0-5的整数
feature1 np.random.randint(0, 5, n_observations)# 随机生成10000个值是以下字符串的字符串
strings np.array([bcat, bdog, bchicken, bhorse, bgoat])
feature2 strings[feature1]# 随机生成10000个01正太分布数据数据是浮点型
feature3 np.random.randn(n_observations)# todo 下面分别演示将字符串类型标量、浮点型标量、整数型标量转换成协议消息
# todo 这些方法可以复制过去直接使用
def _bytes_feature(value):输入string / byte类型数据返回bytes_list类型的协议消息if isinstance(value, type(tf.constant(0))):value value.numpy() # BytesList wont unpack a string from an EagerTensor.return tf.train.Feature(bytes_listtf.train.BytesList(value[value])) # 先记住这个写法这个写法是TF官网推荐的写法def _float_feature(value):输入float / double类型数据返回float_list类型的协议消息return tf.train.Feature(float_listtf.train.FloatList(value[value]))def _int64_feature(value):输入bool / enum / int / uint.类型数据返回int64_list类型的协议消息return tf.train.Feature(int64_listtf.train.Int64List(value[value]))def serialize_example(feature0, feature1, feature2, feature3):输入标量转成字典协议消息转成特征消息转成二进制字符串# 构建字典协议消息feature {feature0: _int64_feature(feature0),feature1: _int64_feature(feature1),feature2: _bytes_feature(feature2),feature3: _float_feature(feature3),}# Create a Features message using tf.train.Example.example_proto tf.train.Example(featurestf.train.Features(featurefeature))return example_proto.SerializeToString()# todo 将二进制字符串写进tfrecord文件中
filename ./test.tfrecord
with tf.io.TFRecordWriter(filename) as writer: # 构建一个写入对象的上下文for i in range(n_observations): # 循环写入example serialize_example(feature0[i], feature1[i], feature2[i], feature3[i])writer.write(example)ipython-input-62-e109c8c4da87:38: DeprecationWarning: In future, it will be an error for np.bool_ scalars to be interpreted as an indexreturn tf.train.Feature(int64_listtf.train.Int64List(value[value]))从上面可以看出来上面的代码需要循环写入数据速度比较慢下面介绍一种速度更加快速的写入方法
八、通过Dataset将numpy数据存储成TFRecord格式文件
过程代码解释了原理并且这些代码都可以进行复用请读者认真消化
# todo 导入相应工具包
import tensorflow as tfimport numpy as np
import IPython.display as display# todo 为了讲解模拟生成一些数据
# 这里准备生成10000个元素
n_observations int(1e4)# 随机生成10000个True和False布尔值
feature0 np.random.choice([False, True], n_observations)# 随机生成10000个0-5的整数
feature1 np.random.randint(0, 5, n_observations)# 随机生成10000个值是以下字符串的字符串
strings np.array([bcat, bdog, bchicken, bhorse, bgoat])
feature2 strings[feature1]# 随机生成10000个01正太分布数据数据是浮点型
feature3 np.random.randn(n_observations)# todo 下面分别演示将字符串类型标量、浮点型标量、整数型标量转换成协议消息
# todo 这些方法可以复制过去直接使用
def _bytes_feature(value):输入string / byte类型数据返回bytes_list类型的协议消息if isinstance(value, type(tf.constant(0))):value value.numpy() # BytesList wont unpack a string from an EagerTensor.return tf.train.Feature(bytes_listtf.train.BytesList(value[value])) # 先记住这个写法这个写法是TF官网推荐的写法def _float_feature(value):输入float / double类型数据返回float_list类型的协议消息return tf.train.Feature(float_listtf.train.FloatList(value[value]))def _int64_feature(value):输入bool / enum / int / uint.类型数据返回int64_list类型的协议消息return tf.train.Feature(int64_listtf.train.Int64List(value[value]))def serialize_example(feature0, feature1, feature2, feature3):输入标量转成字典协议消息转成特征消息转成二进制字符串# 构建字典协议消息feature {feature0: _int64_feature(feature0),feature1: _int64_feature(feature1),feature2: _bytes_feature(feature2),feature3: _float_feature(feature3),}# Create a Features message using tf.train.Example.example_proto tf.train.Example(featurestf.train.Features(featurefeature))return example_proto.SerializeToString()# todo 构建Dataset对象
features_dataset tf.data.Dataset.from_tensor_slices((feature0, feature1, feature2, feature3))def tf_serialize_example(f0,f1,f2,f3):tf_string tf.py_function( # py_function函数将python函数转成可以通过tf计算图进行运算的函数提升速度的关键就是在此serialize_example,(f0,f1,f2,f3), # 传到函数serialize_example的参数tf.string) # 指定函数serialize_example返回值的类型return tf.reshape(tf_string, ()) # 返回结果# todo 构建一个生成器
def generator():for features in features_dataset:yield serialize_example(*features)if True:# todo 通过map函数将函数tf_serialize_example作用到features_dataset对象中的每个元素中生成一个新的Dataset对象serialized_features_dataset features_dataset.map(tf_serialize_example)
else:# todo 也可以直接通过生成器构建需要的Dataset对象serialized_features_dataset tf.data.Dataset.from_generator(generator, # 可调用的生成器函数output_typestf.string, # 输出数据的类型output_shapes() # 输出数据的形状)# todo 通过Dataset对象将数据存储成TFRecord格式文件
filename test.tfrecord
writer tf.data.experimental.TFRecordWriter(filename)
writer.write(serialized_features_dataset)九、通过Dataset对象读取TFRecord格式文件
过程代码解释了原理并且这些代码都可以进行复用请读者认真消化。定义特征描述这个非常重要主要是定义了特征描述的形状和类型 # 将TFRecord文件读成Dataset对象
filenames [filename]
raw_dataset tf.data.TFRecordDataset(filenames)# todo 定义特征描述这个非常重要格式如下主要是定义了特征描述的形状和类型
feature_description {feature0: tf.io.FixedLenFeature([], tf.int64, default_value0),feature1: tf.io.FixedLenFeature([], tf.int64, default_value0),feature2: tf.io.FixedLenFeature([], tf.string, default_value),feature3: tf.io.FixedLenFeature([], tf.float32, default_value0.0),
}def _parse_function(example_proto):# 将二进制字符串转成实际的存储数据return tf.io.parse_single_example(example_proto, feature_description)# 运用map函数将函数_parse_function作用到Dataset对象的每个元素里面
parsed_dataset raw_dataset.map(_parse_function)# parsed_dataset对象的每个元素就是真实的存储数据
for parsed_record in parsed_dataset.take(10):print(repr(parsed_record))break结果如下
{feature0: tf.Tensor: shape(), dtypeint64, numpy1, feature1: tf.Tensor: shape(), dtypeint64, numpy2, feature2: tf.Tensor: shape(), dtypestring, numpybchicken, feature3: tf.Tensor: shape(), dtypefloat32, numpy-0.10460473}10、欢迎关注下期讲解使用TFRecord文件读取和写入图像数据