Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

TFRecord e tf.train.Example

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza sorgente su GitHub Scarica notebook

Il formato TFRecord è un formato semplice per memorizzare una sequenza di record binari.

I buffer di protocollo sono una libreria multipiattaforma e multilingue per una serializzazione efficiente dei dati strutturati.

I messaggi di protocollo sono definiti da file .proto , questi sono spesso il modo più semplice per comprendere un tipo di messaggio.

Il messaggio tf.train.Example (o protobuf) è un tipo di messaggio flessibile che rappresenta una mappatura {"string": value} . È progettato per essere utilizzato con TensorFlow e viene utilizzato in tutte le API di livello superiore come TFX .

Questo tf.train.Example note mostrerà come creare, analizzare e utilizzare il messaggio tf.train.Example , quindi serializzare, scrivere e leggere i messaggi tf.train.Example da e .tfrecord file .tfrecord .

Impostare

import tensorflow as tf

import numpy as np
import IPython.display as display

tf.train.Example

Tipi di dati per tf.train.Example

Fondamentalmente, un tf.train.Example è una mappatura {"string": tf.train.Feature} .

Il tipo di messaggio tf.train.Feature può accettare uno dei tre tipi seguenti (vedere il file .proto per riferimento). La maggior parte degli altri tipi generici può essere forzata in uno di questi:

  1. tf.train.BytesList (i seguenti tipi possono essere forzati)

    • string
    • byte
  2. tf.train.FloatList (i seguenti tipi possono essere forzati)

    • float ( float32 )
    • double ( float64 )
  3. tf.train.Int64List (i seguenti tipi possono essere forzati)

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

Per convertire un tipo TensorFlow standard in un tf.train.Example compatibile con tf.train.Feature , puoi utilizzare le funzioni di scelta rapida di seguito. Nota che ogni funzione accetta un valore di input scalare e restituisce una funzione tf.train.Feature contenente uno dei tre tipi di list sopra:

# 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 seguito sono riportati alcuni esempi di come funzionano queste funzioni. Notare i diversi tipi di input e i tipi di output standardizzati. Se il tipo di input per una funzione non corrisponde a uno dei tipi coercibili sopra indicati, la funzione solleverà un'eccezione (ad es. _int64_feature(1.0) verrà visualizzato in errore, poiché 1.0 è un float, quindi dovrebbe essere usato con la funzione _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
}


Tutti i messaggi proto possono essere serializzati in una stringa binaria utilizzando il metodo .SerializeToString :

feature = _float_feature(np.exp(1))

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

Creazione di un messaggio tf.train.Example

Supponi di voler creare un messaggio tf.train.Example da dati esistenti. In pratica, il set di dati può provenire da qualsiasi luogo, ma la procedura per creare il messaggio tf.train.Example da una singola osservazione sarà la stessa:

  1. All'interno di ogni osservazione, ogni valore deve essere convertito in un tf.train.Feature contenente uno dei 3 tipi compatibili, utilizzando una delle funzioni sopra.

  2. Si crea una mappa (dizionario) dalla stringa del nome dell'elemento al valore dell'elemento codificato prodotto in # 1.

  3. La mappa prodotta nel passaggio 2 viene convertita in un messaggio Features .

In questo taccuino creerai un set di dati usando NumPy.

Questo set di dati avrà 4 caratteristiche:

  • una caratteristica booleana, False o True con uguale probabilità
  • una caratteristica intera scelta casualmente in modo uniforme da [0, 5]
  • una funzione di stringa generata da una tabella di stringhe utilizzando la funzione di numero intero come indice
  • una funzione float da una distribuzione normale standard

Considera un campione composto da 10.000 osservazioni distribuite in modo indipendente e identico da ciascuna delle distribuzioni di cui sopra:

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

Ciascuna di queste funzionalità può essere tf.train.Example in un tipo tf.train.Example tf.train.Example utilizzando uno di _bytes_feature , _float_feature , _int64_feature . È quindi possibile creare un messaggio tf.train.Example da queste funzionalità codificate:

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

Ad esempio, supponiamo di avere una singola osservazione dal set di dati, [False, 4, bytes('goat'), 0.9876] . È possibile creare e stampare il messaggio tf.train.Example per questa osservazione utilizzando create_message() . Ogni singola osservazione verrà scritta come un messaggio Features come sopra. Nota che il messaggio tf.train.Example è solo un wrapper attorno al messaggio 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\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04[\xd3|?\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat'

Per decodificare il messaggio utilizzare il metodo 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
      }
    }
  }
}

Dettagli del formato TFRecords

Un file TFRecord contiene una sequenza di record. Il file può essere letto solo in sequenza.

Ogni record contiene una stringa di byte, per il payload dei dati, più la lunghezza dei dati e hash CRC32C (CRC a 32 bit che utilizza il polinomio Castagnoli) per il controllo dell'integrità.

Ogni record viene archiviato nei seguenti formati:

uint64 length
uint32 masked_crc32_of_length
byte   data[length]
uint32 masked_crc32_of_data

I record vengono concatenati insieme per produrre il file. I CRC sono descritti qui e la maschera di un CRC è:

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

File tf.data utilizzando tf.data

Il modulo tf.data fornisce anche strumenti per leggere e scrivere dati in TensorFlow.

Scrittura di un file TFRecord

Il modo più semplice per inserire i dati in un set di dati è utilizzare il metodo from_tensor_slices .

Applicato a un array, restituisce un set di dati di scalari:

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

Applicato a una tupla di array, restituisce un set di dati di tuple:

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(False, shape=(), dtype=bool)
tf.Tensor(0, shape=(), dtype=int64)
tf.Tensor(b'cat', shape=(), dtype=string)
tf.Tensor(-0.07564599618591197, shape=(), dtype=float64)

Utilizzare il metodo tf.data.Dataset.map per applicare una funzione a ogni elemento di un Dataset .

La funzione mappata deve operare in modalità grafico TensorFlow: deve operare e restituire tf.Tensors . Una funzione non tensore, come serialize_example , può essere racchiusa in tf.py_function per renderla compatibile.

L'utilizzo di tf.py_function richiede di specificare le informazioni sulla forma e sul tipo che altrimenti non sarebbero disponibili:

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\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04J\xec\x9a\xbd\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00'>

Applica questa funzione a ogni elemento nel set di dati:

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>

E scrivili in un file TFRecord:

filename = 'test.tfrecord'
writer = tf.data.experimental.TFRecordWriter(filename)
writer.write(serialized_features_dataset)

Lettura di un file TFRecord

È inoltre possibile leggere il file TFRecord utilizzando la classe tf.data.TFRecordDataset .

Ulteriori informazioni sul consumo di file tf.data utilizzando tf.data possono essere trovate qui .

L'uso di TFRecordDataset può essere utile per standardizzare i dati di input e ottimizzare le prestazioni.

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

A questo punto il set di dati contiene messaggi tf.train.Example serializzati. Quando viene iterato, restituisce questi come tensori di stringa scalari.

Usa il metodo .take per mostrare solo i primi 10 record.

for raw_record in raw_dataset.take(10):
  print(repr(raw_record))
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04J\xec\x9a\xbd\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nS\n\x15\n\x08feature2\x12\t\n\x07\n\x05horse\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x1f\xe0\xcb?\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x03'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04q\xa9\xb8>\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x93|+?\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xa0X}?\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat\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\x04[\x19\x11\xc0\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nS\n\x15\n\x08feature2\x12\t\n\x07\n\x05horse\n\x14\n\x08feature3\x12\x08\x12\x06\n\x0473\x12>\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x03\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x01\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xa2\xf7\xf9>'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nR\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\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xba\xf8\xb1?'>
<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\xb71\xe5>\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat'>

Questi tensori possono essere analizzati utilizzando la funzione seguente. Nota che feature_description è necessaria qui perché i set di dati usano l'esecuzione di grafici e necessitano di questa descrizione per costruire la loro forma e la firma del tipo:

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

In alternativa, usa tf.parse example per analizzare l'intero batch in una volta. Applica questa funzione a ogni elemento nel set di dati utilizzando il metodo 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}>

Usa un'esecuzione impaziente per visualizzare le osservazioni nel set di dati. Ci sono 10.000 osservazioni in questo set di dati, ma verranno visualizzate solo le prime 10. I dati vengono visualizzati come un dizionario di caratteristiche. Ogni elemento è un tf.Tensor e l'elemento numpy di questo tensore mostra il valore della caratteristica:

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=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-0.075646>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=1.5927771>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, '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.36066774>}
{'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.6698696>}
{'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.98963356>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=2>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'chicken'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-2.2671726>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, '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.1427735>}
{'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.4882174>}
{'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=1.390403>}
{'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.44764492>}

Qui, la funzione tf.parse_example decomprime i campi tf.train.Example in tensori standard.

File TFRecord in Python

Il modulo tf.io contiene anche funzioni pure-Python per leggere e scrivere file TFRecord.

Scrittura di un file TFRecord

Quindi, scrivi le 10.000 osservazioni nel file test.tfrecord . Ogni osservazione viene convertita in un messaggio tf.train.Example , quindi scritta su file. È quindi possibile verificare che il file test.tfrecord sia stato creato:

# 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

Lettura di un file TFRecord

Questi tensori serializzati possono essere facilmente analizzati utilizzando 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: 0
      }
    }
  }
  feature {
    key: "feature1"
    value {
      int64_list {
        value: 0
      }
    }
  }
  feature {
    key: "feature2"
    value {
      bytes_list {
        value: "cat"
      }
    }
  }
  feature {
    key: "feature3"
    value {
      float_list {
        value: -0.07564599812030792
      }
    }
  }
}


Procedura dettagliata: lettura e scrittura di dati di immagine

Questo è un esempio end-to-end di come leggere e scrivere dati di immagine utilizzando TFRecords. Utilizzando un'immagine come dati di input, scriverete i dati come file TFRecord, quindi rileggerete il file e visualizzerete l'immagine.

Ciò può essere utile se, ad esempio, si desidera utilizzare più modelli sullo stesso set di dati di input. Invece di archiviare i dati dell'immagine grezzi, possono essere preelaborati nel formato TFRecords e può essere utilizzato in tutte le ulteriori elaborazioni e modellazioni.

Per prima cosa, scarichiamo questa immagine di un gatto nella neve e questa foto del Williamsburg Bridge, NYC in costruzione.

Recupera le immagini

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

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

Scrivi il file TFRecord

Come prima, codifica le funzionalità come tipi compatibili con tf.train.Example . Memorizza la funzione di stringa dell'immagine non elaborata, nonché la funzione di altezza, larghezza, profondità e label arbitraria. Quest'ultimo viene utilizzato quando scrivi il file per distinguere tra l'immagine del gatto e l'immagine del ponte. Usa 0 per l'immagine del gatto e 1 per l'immagine del ponte:

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

Notare che tutte le funzionalità sono ora memorizzate nel messaggio tf.train.Example . Successivamente, funzionalizza il codice sopra e scrivi i messaggi di esempio in un file chiamato 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

Leggi il file TFRecord

Ora hai il file, images.tfrecords e ora puoi images.tfrecords i record in esso contenuti per rileggere ciò che hai scritto. Dato che in questo esempio riprodurrai solo l'immagine, l'unica caratteristica di cui avrai bisogno è la stringa dell'immagine grezza. Estrailo usando i getter descritti sopra, vale a dire example.features.feature['image_raw'].bytes_list.value[0] . Puoi anche utilizzare le etichette per determinare quale record è il gatto e quale è il bridge:

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

Recupera le immagini dal 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