TFRecord dan tf.train.Contoh

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Format TFRecord adalah format sederhana untuk menyimpan urutan catatan biner.

Buffer protokol adalah pustaka lintas platform dan lintas bahasa untuk serialisasi data terstruktur yang efisien.

Pesan protokol ditentukan oleh file .proto , ini sering kali merupakan cara termudah untuk memahami jenis pesan.

Pesan tf.train.Example (atau protobuf) adalah jenis pesan fleksibel yang mewakili pemetaan {"string": value} . Ini dirancang untuk digunakan dengan TensorFlow dan digunakan di seluruh API tingkat yang lebih tinggi seperti TFX .

Buku catatan ini menunjukkan cara membuat, mengurai, dan menggunakan pesan tf.train.Example , lalu membuat cerita bersambung, menulis, dan membaca pesan tf.train.Example ke dan dari file .tfrecord .

Mempersiapkan

import tensorflow as tf

import numpy as np
import IPython.display as display

tf.train.Example

Tipe data untuk tf.train.Example

Pada dasarnya, tf.train.Example adalah pemetaan {"string": tf.train.Feature} .

Jenis pesan tf.train.Feature dapat menerima salah satu dari tiga jenis berikut (Lihat file .proto untuk referensi). Sebagian besar tipe generik lainnya dapat dipaksa menjadi salah satu dari ini:

  1. tf.train.BytesList (tipe berikut dapat dipaksakan)

    • string
    • byte
  2. tf.train.FloatList (tipe berikut dapat dipaksakan)

    • float ( float32 )
    • double ( float64 )
  3. tf.train.Int64List (tipe berikut dapat dipaksakan)

    • bool
    • enum
    • int32
    • uint32
    • int64
    • uint64

Untuk mengonversi jenis TensorFlow standar menjadi tf.train.Example -compatible tf.train.Feature , Anda dapat menggunakan fungsi pintasan di bawah ini. Perhatikan bahwa setiap fungsi mengambil nilai input skalar dan mengembalikan tf.train.Feature yang berisi salah satu dari tiga jenis list di atas:

# 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]))

Di bawah ini adalah beberapa contoh bagaimana fungsi-fungsi ini bekerja. Perhatikan berbagai jenis input dan jenis output standar. Jika tipe input untuk suatu fungsi tidak cocok dengan salah satu tipe paksaan yang disebutkan di atas, fungsi tersebut akan memunculkan pengecualian (mis _int64_feature(1.0) akan error karena 1.0 adalah float—oleh karena itu, fungsi tersebut harus digunakan dengan fungsi _float_feature sebagai gantinya ):

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
}

Semua pesan proto dapat diserialisasi ke string biner menggunakan metode .SerializeToString :

feature = _float_feature(np.exp(1))

feature.SerializeToString()
b'\x12\x06\n\x04T\xf8-@'

Membuat tf.train.Example pesan

Misalkan Anda ingin membuat pesan tf.train.Example dari data yang ada. Dalam praktiknya, dataset dapat berasal dari mana saja, tetapi prosedur pembuatan tf.train.Example pesan dari satu observasi akan sama:

  1. Dalam setiap pengamatan, setiap nilai perlu dikonversi ke tf.train.Feature yang berisi salah satu dari 3 tipe yang kompatibel, menggunakan salah satu fungsi di atas.

  2. Anda membuat peta (kamus) dari string nama fitur ke nilai fitur yang disandikan yang dihasilkan di #1.

  3. Peta yang dihasilkan pada langkah 2 diubah menjadi pesan Features .

Di buku catatan ini, Anda akan membuat kumpulan data menggunakan NumPy.

Dataset ini akan memiliki 4 fitur:

  • fitur boolean, False atau True dengan probabilitas yang sama
  • fitur integer yang dipilih secara acak secara seragam dari [0, 5]
  • fitur string yang dihasilkan dari tabel string dengan menggunakan fitur integer sebagai indeks
  • fitur float dari distribusi normal standar

Pertimbangkan sampel yang terdiri dari 10.000 pengamatan yang terdistribusi secara independen dan identik dari masing-masing distribusi di atas:

# 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)

Masing-masing fitur ini dapat dipaksa menjadi tipe yang kompatibel dengan tf.train.Example menggunakan salah satu dari _bytes_feature , _float_feature , _int64_feature . Anda kemudian dapat membuat pesan tf.train.Example dari fitur yang disandikan ini:

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()

Misalnya, Anda memiliki satu pengamatan dari kumpulan data, [False, 4, bytes('goat'), 0.9876] . Anda dapat membuat dan mencetak pesan tf.train.Example untuk pengamatan ini menggunakan create_message() . Setiap pengamatan tunggal akan ditulis sebagai pesan Features sesuai di atas. Perhatikan bahwa pesan tf.train.Example hanyalah pembungkus di sekitar pesan 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|?'

Untuk memecahkan kode pesan, gunakan metode 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
      }
    }
  }
}

Detail format TFRecords

File TFRecord berisi urutan catatan. File hanya dapat dibaca secara berurutan.

Setiap catatan berisi string-byte, untuk muatan data, ditambah panjang data, dan hash CRC-32C ( CRC 32-bit menggunakan polinomial Castagnoli ) untuk pemeriksaan integritas.

Setiap record disimpan dalam format berikut:

uint64 length
uint32 masked_crc32_of_length
byte   data[length]
uint32 masked_crc32_of_data

Catatan digabungkan bersama untuk menghasilkan file. CRC dijelaskan di sini , dan topeng CRC adalah:

masked_crc = ((crc >> 15) | (crc << 17)) + 0xa282ead8ul

File TFRecord menggunakan tf.data

Modul tf.data juga menyediakan alat untuk membaca dan menulis data di TensorFlow.

Menulis file TFRecord

Cara termudah untuk memasukkan data ke dalam kumpulan data adalah dengan menggunakan metode from_tensor_slices .

Diterapkan ke array, ia mengembalikan set data skalar:

tf.data.Dataset.from_tensor_slices(feature1)
<TensorSliceDataset element_spec=TensorSpec(shape=(), dtype=tf.int64, name=None)>

Diterapkan ke tupel array, ia mengembalikan kumpulan data tupel:

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)

Gunakan metode tf.data.Dataset.map untuk menerapkan fungsi ke setiap elemen Dataset .

Fungsi yang dipetakan harus beroperasi dalam mode grafik TensorFlow—fungsi ini harus beroperasi dan mengembalikan tf.Tensors . Fungsi non-tensor, seperti serialize_example , dapat dibungkus dengan tf.py_function agar kompatibel.

Menggunakan tf.py_function perlu menentukan informasi bentuk dan tipe yang tidak tersedia:

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'>

Terapkan fungsi ini ke setiap elemen dalam kumpulan data:

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)>

Dan tuliskan ke file 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`

Membaca file TFRecord

Anda juga dapat membaca file TFRecord menggunakan kelas tf.data.TFRecordDataset .

Informasi lebih lanjut tentang penggunaan file TFRecord menggunakan tf.data dapat ditemukan di tf.data: Panduan pipeline input build TensorFlow .

Menggunakan TFRecordDataset s dapat berguna untuk menstandardisasi data input dan mengoptimalkan kinerja.

filenames = [filename]
raw_dataset = tf.data.TFRecordDataset(filenames)
raw_dataset
<TFRecordDatasetV2 element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>

Pada titik ini kumpulan data berisi pesan tf.train.Example serial. Ketika diulang, ia mengembalikan ini sebagai tensor string skalar.

Gunakan metode .take untuk hanya menampilkan 10 catatan pertama.

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'>

Tensor ini dapat diuraikan menggunakan fungsi di bawah ini. Perhatikan bahwa feature_description diperlukan di sini karena tf.data.Dataset s menggunakan eksekusi grafik, dan memerlukan deskripsi ini untuk membuat bentuk dan jenis tanda tangannya:

# 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)

Atau, gunakan tf.parse example untuk mengurai seluruh batch sekaligus. Terapkan fungsi ini ke setiap item dalam kumpulan data menggunakan metode 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)}>

Gunakan eksekusi bersemangat untuk menampilkan pengamatan dalam dataset. Ada 10.000 pengamatan dalam kumpulan data ini, tetapi Anda hanya akan menampilkan 10 pengamatan pertama. Data ditampilkan sebagai kamus fitur. Setiap item adalah tf.Tensor , dan elemen numpy dari tensor ini menampilkan nilai fitur:

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>}

Di sini, fungsi tf.parse_example membongkar bidang tf.train.Example ke dalam tensor standar.

File TFRecord dengan Python

Modul tf.io juga berisi fungsi-fungsi Python murni untuk membaca dan menulis file TFRecord.

Menulis file TFRecord

Selanjutnya, tulis 10.000 observasi ke file test.tfrecord . Setiap observasi diubah menjadi pesan tf.train.Example , kemudian ditulis ke file. Anda kemudian dapat memverifikasi bahwa file test.tfrecord telah dibuat:

# 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

Membaca file TFRecord

Tensor serial ini dapat dengan mudah diurai menggunakan 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
      }
    }
  }
}

Itu mengembalikan proto tf.train.Example yang sulit digunakan apa adanya, tetapi pada dasarnya merupakan representasi dari:

Dict[str,
     Union[List[float],
           List[int],
           List[str]]]

Kode berikut secara manual mengonversi Example ke kamus array NumPy, tanpa menggunakan TensorFlow Ops. Lihat file PROTO untuk detailnya.

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')}

Panduan: Membaca dan menulis data gambar

Ini adalah contoh ujung ke ujung tentang cara membaca dan menulis data gambar menggunakan TFRecords. Menggunakan gambar sebagai data input, Anda akan menulis data sebagai file TFRecord, kemudian membaca file kembali dan menampilkan gambar.

Ini dapat berguna jika, misalnya, Anda ingin menggunakan beberapa model pada kumpulan data input yang sama. Alih-alih menyimpan data gambar mentah, itu dapat diproses sebelumnya ke dalam format TFRecords, dan itu dapat digunakan dalam semua pemrosesan dan pemodelan lebih lanjut.

Pertama, mari unduh gambar kucing di salju ini dan foto Jembatan Williamsburg, NYC yang sedang dibangun.

Ambil gambar

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>'))

jpeg

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>'))

jpeg

Tulis file TFRecord

Seperti sebelumnya, enkodekan fitur sebagai tipe yang kompatibel dengan tf.train.Example . Ini menyimpan fitur string gambar mentah, serta fitur label tinggi, lebar, kedalaman, dan arbitrer. Yang terakhir digunakan saat Anda menulis file untuk membedakan antara gambar kucing dan gambar jembatan. Gunakan 0 untuk gambar kucing, dan 1 untuk gambar jembatan:

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
      }
...

Perhatikan bahwa semua fitur sekarang disimpan dalam pesan tf.train.Example . Selanjutnya, fungsikan kode di atas dan tulis pesan contoh ke file bernama 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

Baca file TFRecord

Anda sekarang memiliki file— images.tfrecords —dan sekarang dapat mengulangi catatan di dalamnya untuk membaca kembali apa yang Anda tulis. Mengingat bahwa dalam contoh ini Anda hanya akan mereproduksi gambar, satu-satunya fitur yang Anda perlukan adalah string gambar mentah. Ekstrak menggunakan getter yang dijelaskan di atas, yaitu example.features.feature['image_raw'].bytes_list.value[0] . Anda juga dapat menggunakan label untuk menentukan catatan mana yang kucing dan mana yang jembatan:

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)}>

Pulihkan gambar dari file TFRecord:

for image_features in parsed_image_dataset:
  image_raw = image_features['image_raw'].numpy()
  display.display(display.Image(data=image_raw))

jpeg

jpeg