TFRecord и tf.train.Example

Посмотреть на 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 файл для справки). Большинство других универсальных типов можно принудительно преобразовать в один из следующих:

  1. tf.train.BytesList (следующие типы могут быть принуждены)

    • string
    • byte
  2. tf.train.FloatList (следующие типы могут быть принуждены)

    • float ( float32 )
    • double ( float64 )
  3. 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 сообщения из одного наблюдения будет то же самое:

  1. В каждом наблюдении, каждый из них должна быть значение преобразуются в tf.train.Feature , содержащий один из 3 совместимых типов, используя одну из функций выше.

  2. Вы создаете карту (словарь) из строки имени объекта в закодированное значение объекта, полученное в # 1.

  3. Карта полученного на стадии 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)

Каждая из этих функций может быть принужден в tf.train.Example -соместимым типа с использованием одного из _bytes_feature , _float_feature , _int64_feature . Вы можете создать 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\x14\n\x08feature3\x12\x08\x12\x06\n\x04[\xd3|?\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00'

Для декодирования использует сообщение 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 ( 32-битовый CRC , используя полином Кастаньол ) хешей для проверки целостности.

Каждая запись хранится в следующих форматах:

uint64 length
uint32 masked_crc32_of_length
byte   data[length]
uint32 masked_crc32_of_data

Записи объединяются вместе для создания файла. ЗПК будут описаны здесь , и маска 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 shapes: (), types: tf.int64>

Применительно к кортежу массивов он возвращает набор кортежей:

features_dataset = tf.data.Dataset.from_tensor_slices((feature0, feature1, feature2, feature3))
features_dataset
<TensorSliceDataset shapes: ((), (), (), ()), types: (tf.bool, tf.int64, tf.string, tf.float64)>
# 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(True, shape=(), dtype=bool)
tf.Tensor(1, shape=(), dtype=int64)
tf.Tensor(b'dog', shape=(), dtype=string)
tf.Tensor(-0.9885608219225024, 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'\nQ\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04R\x12}\xbf\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x01\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01'>

Примените эту функцию к каждому элементу в наборе данных:

serialized_features_dataset = features_dataset.map(tf_serialize_example)
serialized_features_dataset
<MapDataset shapes: (), types: tf.string>
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 shapes: (), types: tf.string>

И записываем их в файл TFRecord:

filename = 'test.tfrecord'
writer = tf.data.experimental.TFRecordWriter(filename)
writer.write(serialized_features_dataset)
WARNING:tensorflow:From /tmp/ipykernel_16482/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: Построить входные TensorFlow трубопроводов руководства.

Используя TFRecordDataset ы могут быть полезны для стандартизации входных данных и оптимизации производительности.

filenames = [filename]
raw_dataset = tf.data.TFRecordDataset(filenames)
raw_dataset
<TFRecordDatasetV2 shapes: (), types: tf.string>

На данный момент набор данных содержит сериализованные tf.train.Example сообщения. При повторении он возвращает их как тензоры скалярных строк.

Используйте .take метод , чтобы показывать только первые 10 записей.

for raw_record in raw_dataset.take(10):
  print(repr(raw_record))
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04R\x12}\xbf\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x01'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xb5\x91\xdc\xbb\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xbd\x91g=\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\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\x04e\xc5\x98>'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nS\n\x15\n\x08feature2\x12\t\n\x07\n\x05horse\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x03\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04e\xa4|>\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\x00\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x0b\xb3\x02@\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04G\xa4\xda\xbf\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x01'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xd2/\xcf\xbf'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04<\xedO?\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nR\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\x08feature3\x12\x08\x12\x06\n\x041I\xe1?\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat'>

Эти тензоры можно проанализировать с помощью функции ниже. Обратите внимание , что feature_description здесь необходим , потому что tf.data.Dataset S Использовать граф-исполнение, и нужно это описание , чтобы построить свою форму и типа подпись:

# 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 shapes: {feature0: (), feature1: (), feature2: (), feature3: ()}, types: {feature0: tf.int64, feature1: tf.int64, feature2: tf.string, feature3: tf.float32}>

Используйте активное выполнение для отображения наблюдений в наборе данных. В этом наборе данных 10 000 наблюдений, но вы отобразите только первые 10. Данные отображаются в виде словаря функций. Каждый элемент является tf.Tensor и numpy элемент этого тензора отображает значение функции:

for parsed_record in parsed_dataset.take(10):
  print(repr(parsed_record))
{'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.9885608>}
{'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.006731237>}
{'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.05653547>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, '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.298381>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.24672087>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=2.042178>}
{'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=-1.7081383>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'dog'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-1.6186469>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, '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.81221366>}
{'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.7600461>}

Здесь tf.parse_example функция распаковывает tf.train.Example поля в стандартные тензоры.

Файлы TFRecord в Python

tf.io модуль также содержит чисто 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 shapes: (), types: tf.string>
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: 1
      }
    }
  }
  feature {
    key: "feature1"
    value {
      int64_list {
        value: 1
      }
    }
  }
  feature {
    key: "feature2"
    value {
      bytes_list {
        value: "dog"
      }
    }
  }
  feature {
    key: "feature3"
    value {
      float_list {
        value: -0.9885607957839966
      }
    }
  }
}

То , что возвращает tf.train.Example прото который dificult для использования , как есть, но это в основном это представление:

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

Следующий код вручную преобразует Example для словаря NumPy массивов, без использования TensorFlow Ops. Обратитесь к файлу прото для detials.

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
{'feature1': array([1]),
 'feature0': array([1]),
 'feature2': array([b'dog'], dtype='|S3'),
 'feature3': array([-0.9885608])}

Пошаговое руководство: чтение и запись данных изображения

Это сквозной пример того, как читать и записывать данные изображения с помощью 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>'))

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

Запишите файл 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 shapes: {depth: (), height: (), image_raw: (), label: (), width: ()}, types: {depth: tf.int64, height: tf.int64, image_raw: tf.string, label: tf.int64, width: tf.int64}>

Восстановите образы из файла TFRecord:

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

jpeg

jpeg