Visualizza su TensorFlow.org | Esegui in Google Colab | Visualizza l'origine su GitHub | Scarica quaderno |
Il formato TFRecord è un formato semplice per la memorizzazione di una sequenza di record binari.
I buffer di protocollo sono una libreria multipiattaforma e multilingua per una serializzazione efficiente di 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 l'uso con TensorFlow e viene utilizzato in tutte le API di livello superiore come TFX .
Questo blocco appunti mostra come creare, analizzare e utilizzare il messaggio tf.train.Example
, quindi serializzare, scrivere e leggere i messaggi tf.train.Example
da e verso i 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 (consultare il file .proto
per riferimento). La maggior parte degli altri tipi generici possono essere forzati in uno di questi:
tf.train.BytesList
(i seguenti tipi possono essere forzati)-
string
-
byte
-
tf.train.FloatList
(i seguenti tipi possono essere forzati)-
float
(float32
) -
double
(float64
)
-
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
-compatible tf.train.Feature
, puoi utilizzare le funzioni di scelta rapida di seguito. Si noti che ogni funzione prende un valore di input scalare e restituisce un 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)
emetterà un errore perché 1.0
è un float, quindi dovrebbe essere usato invece 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
Si supponga di voler creare un messaggio tf.train.Example
dai dati esistenti. In pratica, il dataset può provenire da qualsiasi luogo, ma la procedura per creare il messaggio tf.train.Example
da una singola osservazione sarà la stessa:
All'interno di ogni osservazione, ogni valore deve essere convertito in una
tf.train.Feature
contenente uno dei 3 tipi compatibili, utilizzando una delle funzioni precedenti.Si crea una mappa (dizionario) dalla stringa del nome dell'elemento al valore dell'elemento codificato prodotto in #1.
La mappa prodotta nel passaggio 2 viene convertita in un messaggio
Features
.
In questo notebook creerai un set di dati usando NumPy.
Questo set di dati avrà 4 caratteristiche:
- una caratteristica booleana,
False
oTrue
con uguale probabilità - una caratteristica intera scelta in modo uniforme e casuale da
[0, 5]
- una funzione stringa generata da una tabella di stringhe utilizzando la funzione intera 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)
Ognuna di queste funzionalità può essere forzata in un tipo compatibile con 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]
. Puoi creare e stampare il messaggio tf.train.Example
per questa osservazione usando create_message()
. Ogni singola osservazione verrà scritta come messaggio di 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\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|?'
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 carico utile dei dati, più la lunghezza dei dati e gli hash CRC-32C ( CRC a 32 bit utilizzando il polinomio di Castagnoli ) per il controllo dell'integrità.
Ogni record è memorizzato 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 TFRecord utilizzando tf.data
Il modulo tf.data
fornisce anche strumenti per leggere e scrivere dati in TensorFlow.
Scrivere un file TFRecord
Il modo più semplice per ottenere 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 element_spec=TensorSpec(shape=(), dtype=tf.int64, name=None)>
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 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)
Utilizzare il metodo tf.data.Dataset.map
per applicare una funzione a ciascun elemento di un Dataset
.
La funzione mappata deve funzionare in modalità grafico TensorFlow: deve funzionare e restituire tf.Tensors
. Una funzione non tensoriale, come serialize_example
, può essere racchiusa in tf.py_function
per renderla compatibile.
L'utilizzo di tf.py_function
richiede di specificare la forma e le informazioni 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'\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'>
Applica questa funzione a ogni elemento nel set di dati:
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)>
E scrivili in un 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`
Lettura di un file TFRecord
Puoi anche leggere il file TFRecord usando la classe tf.data.TFRecordDataset
.
Ulteriori informazioni sul consumo di file TFRecord utilizzando tf.data
sono disponibili in tf.data: Build TensorFlow input pipelines guide.
L'uso di TFRecordDataset
s può essere utile per standardizzare i dati di input e ottimizzare le prestazioni.
filenames = [filename]
raw_dataset = tf.data.TFRecordDataset(filenames)
raw_dataset
<TFRecordDatasetV2 element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>
A questo punto il set di dati contiene messaggi serializzati tf.train.Example
. Quando viene ripetuto, 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'\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'>
Questi tensori possono essere analizzati utilizzando la funzione seguente. Nota che la feature_description
è necessaria qui perché i tf.data.Dataset
usano l'esecuzione del grafico e hanno bisogno 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, utilizzare tf.parse example
per analizzare l'intero batch in una volta. Applicare 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 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)}>
Usa l'esecuzione desiderosa 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=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>}
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 in puro Python per leggere e scrivere file TFRecord.
Scrivere 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. Puoi quindi 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 usando 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 } } } }
Ciò restituisce un proto tf.train.Example
che è difficile da usare così com'è, ma è fondamentalmente una rappresentazione di a:
Dict[str,
Union[List[float],
List[int],
List[str]]]
Il codice seguente converte manualmente l' Example
in un dizionario di matrici NumPy, senza usare TensorFlow Ops. Fare riferimento al file PROTO per i dettagli.
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')}
Procedura dettagliata: lettura e scrittura dei dati dell'immagine
Questo è un esempio completo di come leggere e scrivere dati di immagine utilizzando TFRecords. Usando un'immagine come dati di input, scriverai i dati come file TFRecord, quindi rileggerai il file e visualizzerai l'immagine.
Ciò può essere utile se, ad esempio, si desidera utilizzare più modelli sullo stesso set di dati di input. Invece di memorizzare i dati dell'immagine grezzi, possono essere preelaborati nel formato TFRecords e possono essere utilizzati in tutte le ulteriori elaborazioni e modellazioni.
Per prima cosa, scarichiamo questa immagine di un gatto nella neve e questa foto del ponte di Williamsburg, New York in costruzione.
Prendi 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 32768/17858 [=======================================================] - 0s 0us/step Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg 16384/15477 [===============================] - 0s 0us/step 24576/15477 [===============================================] - 0s 0us/step
display.display(display.Image(filename=cat_in_snow))
display.display(display.HTML('Image cc-by: <a "href=https://commons.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpg">Von.grzanka</a>'))
display.display(display.Image(filename=williamsburg_bridge))
display.display(display.HTML('<a "href=https://commons.wikimedia.org/wiki/File:New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg">From Wikimedia</a>'))
Scrivi il file TFRecord
Come prima, codifica le funzionalità come tipi compatibili con tf.train.Example
. Ciò memorizza la funzione della stringa di immagine grezza, nonché la funzione di altezza, larghezza, profondità e label
arbitraria. Quest'ultimo viene utilizzato quando si scrive il file per distinguere tra l'immagine cat e l'immagine bridge. 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.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 } ...
Si noti che tutte le funzionalità sono ora archiviate nel messaggio tf.train.Example
. Quindi, 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 scorrere 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 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)}>
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))