مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
فرمت TFRecord یک فرمت ساده برای ذخیره دنباله ای از رکوردهای باینری است.
بافرهای پروتکل یک کتابخانه بین پلتفرمی و بین زبانی برای سریال سازی کارآمد داده های ساخت یافته هستند.
پیامهای پروتکل با فایلهای .proto
تعریف میشوند، اینها اغلب سادهترین راه برای درک نوع پیام هستند.
پیام tf.train.Example
(یا protobuf) یک نوع پیام منعطف است که نگاشت {"string": value}
نشان می دهد. این برای استفاده با TensorFlow طراحی شده است و در سراسر API های سطح بالاتر مانند TFX استفاده می شود.
این نوت بوک نحوه ایجاد، تجزیه و استفاده از پیام tf.train.Example
و سپس سریال سازی، نوشتن و خواندن پیام های tf.train.Example
را به فایل های .tfrecord
. و از آن ها نشان می دهد.
برپایی
import tensorflow as tf
import numpy as np
import IPython.display as display
tf.train.Example
انواع داده برای tf.train.Example
اساساً، یک tf.train.Example
یک نگاشت {"string": tf.train.Feature}
است.
نوع پیام tf.train.Feature
می تواند یکی از سه نوع زیر را بپذیرد (برای مرجع به فایل .proto
مراجعه کنید). بیشتر انواع عمومی دیگر را می توان به یکی از این موارد وادار کرد:
tf.train.BytesList
(انواع زیر را می توان اجبار کرد)-
string
-
byte
-
tf.train.FloatList
(انواع زیر را می توان اجبار کرد)-
float
(float32
) -
double
(float64
)
-
tf.train.Int64List
(انواع زیر را می توان اجبار کرد)-
bool
-
enum
-
int32
-
uint32
-
int64
-
uint64
-
برای تبدیل یک نوع استاندارد TensorFlow به tf.train.Example
tf.train.Feature
، می توانید از توابع میانبر زیر استفاده کنید. توجه داشته باشید که هر تابع یک مقدار ورودی اسکالر می گیرد و یک tf.train.Feature
حاوی یکی از سه نوع list
بالا را برمی گرداند:
# The following functions can be used to convert a value to a type compatible
# with tf.train.Example.
def _bytes_feature(value):
"""Returns a bytes_list from a string / byte."""
if isinstance(value, type(tf.constant(0))):
value = value.numpy() # BytesList won't unpack a string from an EagerTensor.
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def _float_feature(value):
"""Returns a float_list from a float / double."""
return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))
def _int64_feature(value):
"""Returns an int64_list from a bool / enum / int / uint."""
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
در زیر چند نمونه از نحوه عملکرد این توابع آورده شده است. به انواع مختلف ورودی و انواع استاندارد خروجی توجه کنید. اگر نوع ورودی برای یک تابع با یکی از انواع اجباری ذکر شده در بالا مطابقت نداشته باشد، تابع یک استثنا ایجاد می کند (به عنوان مثال _int64_feature(1.0)
با خطا مواجه می شود زیرا 1.0
یک شناور است—بنابراین، باید به جای آن از تابع _float_feature
استفاده شود. ):
print(_bytes_feature(b'test_string'))
print(_bytes_feature(u'test_bytes'.encode('utf-8')))
print(_float_feature(np.exp(1)))
print(_int64_feature(True))
print(_int64_feature(1))
bytes_list { value: "test_string" } bytes_list { value: "test_bytes" } float_list { value: 2.7182817459106445 } int64_list { value: 1 } int64_list { value: 1 }
همه پیام های پروتو را می توان با استفاده از روش .SerializeToString
به یک رشته باینری سریال کرد:
feature = _float_feature(np.exp(1))
feature.SerializeToString()
b'\x12\x06\n\x04T\xf8-@'
ایجاد یک پیام tf.train.Example
فرض کنید می خواهید یک پیام tf.train.Example
از داده های موجود ایجاد کنید. در عمل، مجموعه داده ممکن است از هر جایی آمده باشد، اما روند ایجاد پیام tf.train.Example
از یک مشاهده یکسان خواهد بود:
در هر مشاهده، هر مقدار باید با استفاده از یکی از توابع بالا به یک
tf.train.Feature
حاوی یکی از 3 نوع سازگار تبدیل شود.شما یک نقشه (فرهنگ لغت) از رشته نام ویژگی به مقدار ویژگی کدگذاری شده تولید شده در شماره 1 ایجاد می کنید.
نقشه تولید شده در مرحله 2 به پیام
Features
تبدیل می شود.
در این نوت بوک با استفاده از NumPy یک مجموعه داده ایجاد خواهید کرد.
این مجموعه داده دارای 4 ویژگی خواهد بود:
- یک ویژگی بولی،
False
یاTrue
با احتمال مساوی - یک ویژگی عدد صحیح به طور یکنواخت به طور تصادفی از
[0, 5]
انتخاب شده است. - یک ویژگی رشته ای که از یک جدول رشته ای با استفاده از ویژگی عدد صحیح به عنوان شاخص ایجاد می شود
- یک ویژگی شناور از یک توزیع نرمال استاندارد
نمونه ای متشکل از 10000 مشاهدات توزیع شده مستقل و یکسان از هر یک از توزیع های فوق را در نظر بگیرید:
# The number of observations in the dataset.
n_observations = int(1e4)
# Boolean feature, encoded as False or True.
feature0 = np.random.choice([False, True], n_observations)
# Integer feature, random from 0 to 4.
feature1 = np.random.randint(0, 5, n_observations)
# String feature.
strings = np.array([b'cat', b'dog', b'chicken', b'horse', b'goat'])
feature2 = strings[feature1]
# Float feature, from a standard normal distribution.
feature3 = np.random.randn(n_observations)
هر یک از این ویژگیها را میتوان با استفاده از یکی از _bytes_feature
، _float_feature
، _int64_feature
وارد یک نوع tf.train.Example
-compatible کرد. سپس می توانید یک پیام tf.train.Example
از این ویژگی های رمزگذاری شده ایجاد کنید:
def serialize_example(feature0, feature1, feature2, feature3):
"""
Creates a tf.train.Example message ready to be written to a file.
"""
# Create a dictionary mapping the feature name to the tf.train.Example-compatible
# data type.
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(features=tf.train.Features(feature=feature))
return example_proto.SerializeToString()
به عنوان مثال، فرض کنید یک مشاهده واحد از مجموعه داده دارید، [False, 4, bytes('goat'), 0.9876]
. می توانید پیام tf.train.Example
را برای این مشاهده با استفاده از create_message()
ایجاد و چاپ کنید. هر مشاهده منفرد به عنوان یک پیام Features
مطابق موارد بالا نوشته می شود. توجه داشته باشید که پیام tf.train.Example
فقط یک بسته بندی در اطراف پیام Features
است:
# This is an example observation from the dataset.
example_observation = []
serialized_example = serialize_example(False, 4, b'goat', 0.9876)
serialized_example
b'\nR\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04[\xd3|?'
برای رمزگشایی پیام از روش tf.train.Example.FromString
استفاده کنید.
example_proto = tf.train.Example.FromString(serialized_example)
example_proto
features { feature { key: "feature0" value { int64_list { value: 0 } } } feature { key: "feature1" value { int64_list { value: 4 } } } feature { key: "feature2" value { bytes_list { value: "goat" } } } feature { key: "feature3" value { float_list { value: 0.9876000285148621 } } } }
جزئیات فرمت TFRecords
یک فایل TFRecord حاوی یک دنباله از رکوردها است. فایل را فقط می توان به صورت متوالی خواند.
هر رکورد حاوی یک رشته بایت، برای بار داده، به اضافه طول داده، و هش های CRC-32C ( CRC 32 بیتی با استفاده از چند جمله ای Castagnoli ) برای بررسی یکپارچگی است.
هر رکورد در قالب های زیر ذخیره می شود:
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.data
ماژول tf.data
همچنین ابزارهایی برای خواندن و نوشتن داده ها در TensorFlow فراهم می کند.
نوشتن یک فایل TFRecord
ساده ترین راه برای وارد کردن داده ها به یک مجموعه داده استفاده از روش from_tensor_slices
است.
با اعمال بر روی یک آرایه، مجموعه داده ای از اسکالرها را برمی گرداند:
tf.data.Dataset.from_tensor_slices(feature1)
<TensorSliceDataset element_spec=TensorSpec(shape=(), dtype=tf.int64, name=None)>
با اعمال روی چند آرایه، مجموعه داده ای از چند تایی را برمی گرداند:
features_dataset = tf.data.Dataset.from_tensor_slices((feature0, feature1, feature2, feature3))
features_dataset
<TensorSliceDataset element_spec=(TensorSpec(shape=(), dtype=tf.bool, name=None), TensorSpec(shape=(), dtype=tf.int64, name=None), TensorSpec(shape=(), dtype=tf.string, name=None), TensorSpec(shape=(), dtype=tf.float64, name=None))>
# Use `take(1)` to only pull one example from the dataset.
for f0,f1,f2,f3 in features_dataset.take(1):
print(f0)
print(f1)
print(f2)
print(f3)
tf.Tensor(False, shape=(), dtype=bool) tf.Tensor(4, shape=(), dtype=int64) tf.Tensor(b'goat', shape=(), dtype=string) tf.Tensor(0.5251196235602504, shape=(), dtype=float64)
از روش tf.data.Dataset.map
برای اعمال یک تابع به هر عنصر از Dataset
استفاده کنید.
تابع نگاشت شده باید در حالت نمودار TensorFlow کار کند—باید روی tf.Tensors
کار کرده و برگرداند. یک تابع غیر تانسور، مانند serialize_example
، می تواند با tf.py_function
پیچیده شود تا سازگار شود.
استفاده از tf.py_function
مستلزم تعیین شکل و نوع اطلاعاتی است که در غیر این صورت در دسترس نیست:
def tf_serialize_example(f0,f1,f2,f3):
tf_string = tf.py_function(
serialize_example,
(f0, f1, f2, f3), # Pass these args to the above function.
tf.string) # The return type is `tf.string`.
return tf.reshape(tf_string, ()) # The result is a scalar.
tf_serialize_example(f0, f1, f2, f3)
<tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04=n\x06?\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04'>
این تابع را برای هر عنصر در مجموعه داده اعمال کنید:
serialized_features_dataset = features_dataset.map(tf_serialize_example)
serialized_features_dataset
<MapDataset element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>
def generator():
for features in features_dataset:
yield serialize_example(*features)
serialized_features_dataset = tf.data.Dataset.from_generator(
generator, output_types=tf.string, output_shapes=())
serialized_features_dataset
<FlatMapDataset element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>
و آنها را در یک فایل TFRecord بنویسید:
filename = 'test.tfrecord'
writer = tf.data.experimental.TFRecordWriter(filename)
writer.write(serialized_features_dataset)
WARNING:tensorflow:From /tmp/ipykernel_25215/3575438268.py:2: TFRecordWriter.__init__ (from tensorflow.python.data.experimental.ops.writers) is deprecated and will be removed in a future version. Instructions for updating: To write TFRecords to disk, use `tf.io.TFRecordWriter`. To save and load the contents of a dataset, use `tf.data.experimental.save` and `tf.data.experimental.load`
خواندن یک فایل TFRecord
همچنین می توانید فایل TFRecord را با استفاده از کلاس tf.data.TFRecordDataset
.
اطلاعات بیشتر در مورد مصرف فایلهای TFRecord با استفاده از tf.data
را میتوانید در tf.data بیابید: راهنمای خطوط لوله ورودی Build TensorFlow .
استفاده از TFRecordDataset
می تواند برای استانداردسازی داده های ورودی و بهینه سازی عملکرد مفید باشد.
filenames = [filename]
raw_dataset = tf.data.TFRecordDataset(filenames)
raw_dataset
<TFRecordDatasetV2 element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>
در این مرحله مجموعه داده حاوی پیامهای tf.train.Example
است. وقتی روی آن تکرار می شود، اینها را به عنوان تانسور رشته ای اسکالر برمی گرداند.
از روش .take
برای نمایش 10 رکورد اول استفاده کنید.
for raw_record in raw_dataset.take(10):
print(repr(raw_record))
<tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04=n\x06?'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x9d\xfa\x98\xbe\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x01\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04a\xc0r?\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x92Q(?'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04>\xc0\xe5>\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04I!\xde\xbe\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xe0\x1a\xab\xbf\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x87\xb2\xd7?\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04n\xe19>\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat'> <tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x1as\xd9\xbf\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat'>
این تانسورها را می توان با استفاده از تابع زیر تجزیه کرد. توجه داشته باشید که feature_description
در اینجا ضروری است زیرا tf.data.Dataset
از اجرای گراف استفاده می کند و برای ساخت شکل و نوع امضای خود به این توضیحات نیاز دارد:
# Create a description of the features.
feature_description = {
'feature0': tf.io.FixedLenFeature([], tf.int64, default_value=0),
'feature1': tf.io.FixedLenFeature([], tf.int64, default_value=0),
'feature2': tf.io.FixedLenFeature([], tf.string, default_value=''),
'feature3': tf.io.FixedLenFeature([], tf.float32, default_value=0.0),
}
def _parse_function(example_proto):
# Parse the input `tf.train.Example` proto using the dictionary above.
return tf.io.parse_single_example(example_proto, feature_description)
از طرف دیگر، از tf.parse example
برای تجزیه کل دسته به یکباره استفاده کنید. با استفاده از روش tf.data.Dataset.map
، این تابع را برای هر آیتم در مجموعه داده اعمال کنید:
parsed_dataset = raw_dataset.map(_parse_function)
parsed_dataset
<MapDataset element_spec={'feature0': TensorSpec(shape=(), dtype=tf.int64, name=None), 'feature1': TensorSpec(shape=(), dtype=tf.int64, name=None), 'feature2': TensorSpec(shape=(), dtype=tf.string, name=None), 'feature3': TensorSpec(shape=(), dtype=tf.float32, name=None)}>
از اجرای مشتاق برای نمایش مشاهدات در مجموعه داده استفاده کنید. 10000 مشاهده در این مجموعه داده وجود دارد، اما شما فقط 10 مورد اول را نمایش خواهید داد. داده ها به عنوان فرهنگ لغت ویژگی ها نمایش داده می شوند. هر مورد یک tf.Tensor
است و عنصر numpy
این تانسور مقدار ویژگی را نشان می دهد:
for parsed_record in parsed_dataset.take(10):
print(repr(parsed_record))
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=4>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'goat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.5251196>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=4>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'goat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-0.29878703>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'dog'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.94824797>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.65749466>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=4>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'goat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.44873232>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=2>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'chicken'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-0.4338477>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-1.3367577>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=1.6851357>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=4>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'goat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.18152401>} {'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=4>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'goat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-1.6988251>}
در اینجا، تابع tf.parse_example
فیلدهای tf.train.Example
را در تانسورهای استاندارد باز می کند.
فایل های TFRecord در پایتون
ماژول tf.io
همچنین دارای توابع Pure-Python برای خواندن و نوشتن فایلهای TFRecord است.
نوشتن یک فایل TFRecord
سپس، 10000 مشاهده را در فایل test.tfrecord
. هر مشاهده به یک پیام tf.train.Example
تبدیل می شود، سپس به فایل نوشته می شود. سپس می توانید تأیید کنید که فایل test.tfrecord
ایجاد شده است:
# Write the `tf.train.Example` observations to the file.
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)
du -sh {filename}
984K test.tfrecord
خواندن یک فایل TFRecord
این تانسورهای سریالی را می توان به راحتی با استفاده از tf.train.Example.ParseFromString
تجزیه کرد:
filenames = [filename]
raw_dataset = tf.data.TFRecordDataset(filenames)
raw_dataset
<TFRecordDatasetV2 element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>
for raw_record in raw_dataset.take(1):
example = tf.train.Example()
example.ParseFromString(raw_record.numpy())
print(example)
features { feature { key: "feature0" value { int64_list { value: 0 } } } feature { key: "feature1" value { int64_list { value: 4 } } } feature { key: "feature2" value { bytes_list { value: "goat" } } } feature { key: "feature3" value { float_list { value: 0.5251196026802063 } } } }
این یک پروتو tf.train.Example
را برمی گرداند که استفاده از آن به سختی است، اما اساساً نمایشی از یک است:
Dict[str,
Union[List[float],
List[int],
List[str]]]
کد زیر به صورت دستی Example
را بدون استفاده از TensorFlow Ops به فرهنگ لغت آرایه های NumPy تبدیل می کند. برای جزئیات بیشتر به فایل PROTO مراجعه کنید.
result = {}
# example.features.feature is the dictionary
for key, feature in example.features.feature.items():
# The values are the Feature objects which contain a `kind` which contains:
# one of three fields: bytes_list, float_list, int64_list
kind = feature.WhichOneof('kind')
result[key] = np.array(getattr(feature, kind).value)
result
{'feature3': array([0.5251196]), 'feature1': array([4]), 'feature0': array([0]), 'feature2': array([b'goat'], dtype='|S4')}
راهنما: خواندن و نوشتن داده های تصویر
این یک مثال سرتاسر نحوه خواندن و نوشتن داده های تصویر با استفاده از TFRecords است. با استفاده از یک تصویر به عنوان داده ورودی، داده ها را به عنوان یک فایل TFRecord می نویسید، سپس فایل را دوباره خوانده و تصویر را نمایش می دهید.
این می تواند مفید باشد، برای مثال، اگر بخواهید از چندین مدل در یک مجموعه داده ورودی استفاده کنید. بهجای ذخیرهسازی دادههای تصویر خام، میتوان آن را در قالب TFRecords از پیش پردازش کرد و در تمام پردازشها و مدلسازیهای بیشتر از آن استفاده کرد.
ابتدا این تصویر از یک گربه در برف و این عکس از پل ویلیامزبورگ، نیویورک در حال ساخت را دانلود می کنیم.
تصاویر را واکشی کنید
cat_in_snow = tf.keras.utils.get_file(
'320px-Felis_catus-cat_on_snow.jpg',
'https://storage.googleapis.com/download.tensorflow.org/example_images/320px-Felis_catus-cat_on_snow.jpg')
williamsburg_bridge = tf.keras.utils.get_file(
'194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg',
'https://storage.googleapis.com/download.tensorflow.org/example_images/194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg')
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/320px-Felis_catus-cat_on_snow.jpg 24576/17858 [=========================================] - 0s 0us/step 32768/17858 [=======================================================] - 0s 0us/step Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg 16384/15477 [===============================] - 0s 0us/step 24576/15477 [===============================================] - 0s 0us/step
display.display(display.Image(filename=cat_in_snow))
display.display(display.HTML('Image cc-by: <a "href=https://commons.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpg">Von.grzanka</a>'))
display.display(display.Image(filename=williamsburg_bridge))
display.display(display.HTML('<a "href=https://commons.wikimedia.org/wiki/File:New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg">From Wikimedia</a>'))
فایل TFRecord را بنویسید
مانند قبل، ویژگی ها را به عنوان انواع سازگار با tf.train.Example
کنید. این ویژگی رشته تصویر خام و همچنین ارتفاع، عرض، عمق و ویژگی label
دلخواه را ذخیره می کند. مورد دوم هنگام نوشتن فایل برای تمایز بین تصویر گربه و تصویر پل استفاده می شود. از 0
برای تصویر گربه و 1
برای تصویر پل استفاده کنید:
image_labels = {
cat_in_snow : 0,
williamsburg_bridge : 1,
}
# This is an example, just using the cat image.
image_string = open(cat_in_snow, 'rb').read()
label = image_labels[cat_in_snow]
# Create a dictionary with features that may be relevant.
def image_example(image_string, label):
image_shape = tf.io.decode_jpeg(image_string).shape
feature = {
'height': _int64_feature(image_shape[0]),
'width': _int64_feature(image_shape[1]),
'depth': _int64_feature(image_shape[2]),
'label': _int64_feature(label),
'image_raw': _bytes_feature(image_string),
}
return tf.train.Example(features=tf.train.Features(feature=feature))
for line in str(image_example(image_string, label)).split('\n')[:15]:
print(line)
print('...')
features { feature { key: "depth" value { int64_list { value: 3 } } } feature { key: "height" value { int64_list { value: 213 } ...
توجه داشته باشید که همه ویژگی ها اکنون در پیام tf.train.Example
ذخیره می شوند. سپس، کد بالا را کاربردی کنید و پیام های نمونه را در فایلی به نام images.tfrecords
:
# Write the raw image files to `images.tfrecords`.
# First, process the two images into `tf.train.Example` messages.
# Then, write to a `.tfrecords` file.
record_file = 'images.tfrecords'
with tf.io.TFRecordWriter(record_file) as writer:
for filename, label in image_labels.items():
image_string = open(filename, 'rb').read()
tf_example = image_example(image_string, label)
writer.write(tf_example.SerializeToString())
du -sh {record_file}
36K images.tfrecords
فایل TFRecord را بخوانید
شما اکنون فایل - images.tfrecords
- را دارید و اکنون می توانید روی رکوردهای موجود در آن تکرار کنید تا آنچه را که نوشته اید بازخوانی کنید. با توجه به اینکه در این مثال شما فقط تصویر را بازتولید خواهید کرد، تنها ویژگی مورد نیاز رشته تصویر خام است. آن را با استفاده از دریافت کننده های توضیح داده شده در بالا استخراج کنید، یعنی example.features.feature['image_raw'].bytes_list.value[0]
. همچنین می توانید از برچسب ها برای تعیین اینکه کدام رکورد گربه و کدام یک پل است استفاده کنید:
raw_image_dataset = tf.data.TFRecordDataset('images.tfrecords')
# Create a dictionary describing the features.
image_feature_description = {
'height': tf.io.FixedLenFeature([], tf.int64),
'width': tf.io.FixedLenFeature([], tf.int64),
'depth': tf.io.FixedLenFeature([], tf.int64),
'label': tf.io.FixedLenFeature([], tf.int64),
'image_raw': tf.io.FixedLenFeature([], tf.string),
}
def _parse_image_function(example_proto):
# Parse the input tf.train.Example proto using the dictionary above.
return tf.io.parse_single_example(example_proto, image_feature_description)
parsed_image_dataset = raw_image_dataset.map(_parse_image_function)
parsed_image_dataset
<MapDataset element_spec={'depth': TensorSpec(shape=(), dtype=tf.int64, name=None), 'height': TensorSpec(shape=(), dtype=tf.int64, name=None), 'image_raw': TensorSpec(shape=(), dtype=tf.string, name=None), 'label': TensorSpec(shape=(), dtype=tf.int64, name=None), 'width': TensorSpec(shape=(), dtype=tf.int64, name=None)}>
بازیابی تصاویر از فایل TFRecord:
for image_features in parsed_image_dataset:
image_raw = image_features['image_raw'].numpy()
display.display(display.Image(data=image_raw))