TFRecord y tf.train.Ejemplo

Ver en TensorFlow.org Ejecutar en Google Colab Ver fuente en GitHub Descargar cuaderno

El formato TFRecord es un formato simple para almacenar una secuencia de registros binarios.

Búferes de protocolo son una, biblioteca entre lenguajes multiplataforma para la serialización eficiente de los datos estructurados.

Mensajes de protocolo se definen por .proto archivos, estos son a menudo la forma más fácil de entender un tipo de mensaje.

El tf.train.Example mensaje (o protobuf) es un tipo de mensaje flexible que representa un {"string": value} mapeo. Está diseñado para su uso con TensorFlow y se utiliza a través de las API de alto nivel tales como TFX .

Este portátil se muestra cómo crear, de análisis, y utilizar el tf.train.Example mensaje, y luego serializar, escribir y leer tf.train.Example mensajes hacia y desde .tfrecord archivos.

Configuración

import tensorflow as tf

import numpy as np
import IPython.display as display

tf.train.Example

Tipos de datos para tf.train.Example

Fundamentalmente, un tf.train.Example es un {"string": tf.train.Feature} mapeo.

El tf.train.Feature tipo de mensaje puede aceptar uno de los siguientes tres tipos (Ver la .proto archivo de referencia). La mayoría de los otros tipos genéricos se pueden convertir en uno de estos:

  1. tf.train.BytesList (los siguientes tipos pueden ser obligados)

    • string
    • byte
  2. tf.train.FloatList (los siguientes tipos pueden ser obligados)

    • float ( float32 )
    • double ( float64 )
  3. tf.train.Int64List (los siguientes tipos pueden ser obligados)

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

Para convertir un tipo TensorFlow estándar a un tf.train.Example compatible tf.train.Feature , puede utilizar las funciones de acceso directo a continuación. Tenga en cuenta que cada función tiene un valor de entrada y devuelve un escalar tf.train.Feature que contiene uno de los tres list tipos anteriores:

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

A continuación se muestran algunos ejemplos de cómo funcionan estas funciones. Tenga en cuenta los tipos de entrada variables y los tipos de salida estandarizados. Si el tipo de entrada para una función no coincide con uno de los tipos coercible indicadas anteriormente, la función elevará una excepción (por ejemplo _int64_feature(1.0) será error porque 1.0 es un flotador-por lo tanto, se debe utilizar con la _float_feature función en lugar ):

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
}

Todos los mensajes proto se pueden serializar a un binario-cadena usando el .SerializeToString método:

feature = _float_feature(np.exp(1))

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

La creación de un tf.train.Example mensaje

Suponga que desea crear una tf.train.Example mensaje a partir de datos existentes. En la práctica, el conjunto de datos puede venir de cualquier parte, pero el procedimiento de creación de tf.train.Example mensaje de una sola observación será el mismo:

  1. Dentro de cada observación, las necesidades de cada valor a convertir a un tf.train.Feature que contiene uno de los 3 tipos compatibles, usando una de las funciones anteriores.

  2. Usted crea un mapa (diccionario) desde la cadena del nombre de la característica hasta el valor de la característica codificado producido en el n. ° 1.

  3. El mapa producido en la etapa 2 se convierte en un Features mensaje .

En este cuaderno, creará un conjunto de datos utilizando NumPy.

Este conjunto de datos tendrá 4 características:

  • una característica boolean, False o True con igual probabilidad
  • una característica número entero uniformemente elegido al azar de [0, 5]
  • una característica de cadena generada a partir de una tabla de cadenas utilizando la característica de número entero como índice
  • una característica flotante de una distribución normal estándar

Considere una muestra que consta de 10,000 observaciones distribuidas de manera independiente e idéntica de cada una de las distribuciones anteriores:

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

Cada una de estas características se puede forzar en un tf.train.Example tipo compatible usando uno de _bytes_feature , _float_feature , _int64_feature . A continuación, puede crear un tf.train.Example mensaje de estos rasgos codificados:

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

Por ejemplo, suponga que tiene una sola observación del conjunto de datos, [False, 4, bytes('goat'), 0.9876] . Puede crear e imprimir el tf.train.Example mensaje para esta observación usando create_message() . Cada observación solo se puede escribir como una Features mensaje de acuerdo con lo anterior. Tenga en cuenta que la tf.train.Example mensaje es sólo un envoltorio alrededor de la Features mensaje:

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

Para descifrar el mensaje del uso tf.train.Example.FromString método.

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

Detalles del formato de TFRecords

Un archivo TFRecord contiene una secuencia de registros. El archivo solo se puede leer de forma secuencial.

Cada registro contiene un byte-secuencia, para los datos de carga útil, además de los datos de longitud, y CRC-32C ( 32-bit CRC utilizando el polinomio Castagnoli ) hashes para la comprobación de integridad.

Cada registro se almacena en los siguientes formatos:

uint64 length
uint32 masked_crc32_of_length
byte   data[length]
uint32 masked_crc32_of_data

Los registros se concatenan juntos para producir el archivo. CRC se describen aquí , y la máscara de un CDN es:

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

TFRecord archivos mediante tf.data

El tf.data módulo también proporciona herramientas para leer y escribir datos en TensorFlow.

Escribir un archivo TFRecord

La forma más fácil de obtener los datos en un conjunto de datos es utilizar el from_tensor_slices método.

Aplicado a una matriz, devuelve un conjunto de datos de escalares:

tf.data.Dataset.from_tensor_slices(feature1)
<TensorSliceDataset shapes: (), types: tf.int64>

Aplicado a una tupla de matrices, devuelve un conjunto de datos de tuplas:

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)

Usar la tf.data.Dataset.map método para aplicar una función a cada elemento de un Dataset .

La función de mapeado debe operar en el gráfico TensorFlow modo que debe funcionar en y volver tf.Tensors . Una función no-tensor, como serialize_example , se puede envolver con tf.py_function para hacerlo compatible.

Usando tf.py_function requiere para especificar la información de la forma y el tipo que está disponible de otro modo:

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

Aplique esta función a cada elemento del conjunto de datos:

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>

Y escríbalos en un archivo 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`

Leer un archivo TFRecord

También puede leer el archivo TFRecord utilizando el tf.data.TFRecordDataset clase.

Más información sobre el consumo de archivos utilizando TFRecord tf.data se puede encontrar en el tf.data: Construir las tuberías de entrada TensorFlow guía.

Usando TFRecordDataset s puede ser útil para la normalización de los datos de entrada y optimizar el rendimiento.

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

En este punto el conjunto de datos contiene serializados tf.train.Example mensajes. Cuando se repite, los devuelve como tensores de cuerda escalares.

Usar la .take método para mostrar solamente los primeros 10 registros.

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

Estos tensores se pueden analizar mediante la función siguiente. Tenga en cuenta que la feature_description es necesario aquí porque tf.data.Dataset s uso gráfico de ejecución, y la necesidad de esta descripción para construir su forma y tipo de firma:

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

Alternativamente, utilizar tf.parse example para analizar todo el lote a la vez. Aplicar esta función para cada elemento en el conjunto de datos utilizando la tf.data.Dataset.map método:

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

Utilice una ejecución ávida para mostrar las observaciones en el conjunto de datos. Hay 10,000 observaciones en este conjunto de datos, pero solo mostrará las primeras 10. Los datos se muestran como un diccionario de características. Cada elemento es un tf.Tensor , y la numpy elemento de este tensor muestra el valor de la función:

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

Aquí, el tf.parse_example función descomprime los tf.train.Example campos en los tensores estándar.

Archivos TFRecord en Python

El tf.io módulo también contiene funciones puras-Python para la lectura y escritura de archivos TFRecord.

Escribir un archivo TFRecord

A continuación, escribir los 10.000 observaciones en el archivo test.tfrecord . Cada observación se convierte en un tf.train.Example mensaje, a continuación, escribe en el archivo. A continuación, puede comprobar que el archivo test.tfrecord ha sido creado:

# 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

Leer un archivo TFRecord

Estos tensores serializados se pueden analizar fácilmente usando 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
      }
    }
  }
}

Que devuelve un tf.train.Example proto que es dificil de uso como es, pero es fundamentalmente una representación de una:

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

El siguiente código convierte manualmente el Example a un diccionario de arrays NumPy, sin utilizar Operaciones TensorFlow. Consulte el archivo de PROTO 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])}

Tutorial: lectura y escritura de datos de imagen

Este es un ejemplo completo de cómo leer y escribir datos de imágenes usando TFRecords. Usando una imagen como datos de entrada, escribirá los datos como un archivo TFRecord, luego volverá a leer el archivo y mostrará la imagen.

Esto puede resultar útil si, por ejemplo, desea utilizar varios modelos en el mismo conjunto de datos de entrada. En lugar de almacenar los datos de la imagen sin procesar, se pueden preprocesar en el formato TFRecords, y eso se puede utilizar en todos los procesos y modelos posteriores.

En primer lugar, vamos a descargar esta imagen de un gato en la nieve y esta foto del puente de Williamsburg, Nueva York en construcción.

Obtener las imágenes

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

Escribe el archivo TFRecord

Al igual que antes, codificar las características como tipos compatibles con tf.train.Example . Esto almacena el característica prima cadena de imagen, así como la altura, anchura, profundidad, y arbitraria label de características. Este último se usa cuando escribe el archivo para distinguir entre la imagen del gato y la imagen del puente. Utilice 0 imagen del gato por, y 1 del puente por:

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

Tenga en cuenta que todas las funciones se almacenan ahora en el tf.train.Example mensaje. A continuación, funcionalizar el código anterior y escribir los mensajes de ejemplo en un archivo denominado 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

Leer el archivo TFRecord

Ahora tiene las Archivo- images.tfrecords -y ahora se puede iterar sobre los registros en que volver a leer lo que ha escrito. Dado que en este ejemplo solo reproducirá la imagen, la única característica que necesitará es la cadena de imagen sin procesar. Extraer mediante los getters descritas anteriormente, a saber example.features.feature['image_raw'].bytes_list.value[0] . También puede usar las etiquetas para determinar qué registro es el gato y cuál es el puente:

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

Recupere las imágenes del archivo TFRecord:

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

jpeg

jpeg