This page was translated by the Cloud Translation API.
Switch to English

TFRecord i tf.Example

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Aby efektywnie czytać dane, pomocne może być serializowanie danych i przechowywanie ich w zestawie plików (po 100–200 MB każdy), z których każdy można odczytać liniowo. Jest to szczególnie ważne, jeśli dane są przesyłane strumieniowo przez sieć. Może to być również przydatne do buforowania dowolnego przetwarzania wstępnego danych.

Format TFRecord to prosty format do przechowywania sekwencji rekordów binarnych.

Bufory protokołów to wieloplatformowa, międzyjęzykowa biblioteka do wydajnej serializacji danych strukturalnych.

Komunikaty protokołów są definiowane przez pliki .proto , które często są najłatwiejszym sposobem zrozumienia typu wiadomości.

Wiadomość tf.Example (lub protobuf) to elastyczny typ wiadomości, który reprezentuje mapowanie {"string": value} . Jest przeznaczony do użytku z TensorFlow i jest używany w interfejsach API wyższego poziomu, takich jak TFX .

Ten notatnik pokaże, jak tworzyć, analizować i używać wiadomości tf.Example , a następnie serializować, zapisywać i czytać wiadomości tf.Example do iz plików .tfrecord .

Ustawiać

 import tensorflow as tf

import numpy as np
import IPython.display as display
 

tf.Example

Typy danych dla tf.Example

Zasadniczo tf.Example to tf.Example {"string": tf.train.Feature} .

Typ wiadomości tf.train.Feature może akceptować jeden z trzech następujących typów (zobacz plik .proto celu uzyskania informacji). Większość innych typów ogólnych można wymusić na jeden z poniższych:

  1. tf.train.BytesList (można tf.train.BytesList następujące typy)

    • string
    • byte
  2. tf.train.FloatList (można tf.train.FloatList następujące typy)

    • float ( float32 )
    • double ( float64 )
  3. tf.train.Int64List (można tf.train.Int64List następujące typy)

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

Aby przekonwertować standardowy typ TensorFlow na tf.Example tf.train.Feature , możesz użyć poniższych funkcji skrótów. Zauważ, że każda funkcja przyjmuje skalarną wartość wejściową i zwraca tf.train.Feature zawierającą jeden z trzech typów list powyżej:

 # The following functions can be used to convert a value to a type compatible
# with tf.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]))
 

Poniżej znajduje się kilka przykładów działania tych funkcji. Zwróć uwagę na różne typy wejść i ustandaryzowane typy wyjść. Jeśli typ wejścia dla funkcji nie pasuje do jednego z typów koercybilnych wymienionych powyżej, funkcja zgłosi wyjątek (np. _int64_feature(1.0) wyświetli błąd, ponieważ 1.0 jest zmiennoprzecinkową, więc należy go zamiast tego użyć z funkcją _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
}


Wszystkie wiadomości proto mogą być serializowane do łańcucha binarnego przy użyciu metody .SerializeToString :

 feature = _float_feature(np.exp(1))

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

Tworzenie wiadomości tf.Example

Załóżmy, że chcesz utworzyć wiadomość tf.Example podstawie istniejących danych. W praktyce zbiór danych może pochodzić z dowolnego miejsca, ale procedura tworzenia tf.Example wiadomość z pojedynczej obserwacji będzie taka sama:

  1. W każdej obserwacji każda wartość musi zostać przekonwertowana na tf.train.Feature zawierającą jeden z 3 kompatybilnych typów, przy użyciu jednej z powyższych funkcji.

  2. Tworzysz mapę (słownik) z ciągu nazwy elementu do zakodowanej wartości elementu wygenerowanej w # 1.

  3. Mapa utworzona w kroku 2 jest konwertowana na komunikat Features .

W tym notatniku utworzysz zestaw danych za pomocą NumPy.

Ten zestaw danych będzie miał 4 funkcje:

  • funkcja logiczna, False lub True z równym prawdopodobieństwem
  • cecha całkowita jednorodnie losowo wybrana z [0, 5]
  • funkcja ciągu generowana z tabeli ciągów przy użyciu funkcji liczby całkowitej jako indeksu
  • zmiennoprzecinkowa ze standardowego rozkładu normalnego

Rozważ próbkę składającą się z 10000 niezależnie i identycznie rozmieszczonych obserwacji z każdego z powyższych rozkładów:

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

Każdą z tych funkcji można przekształcić w tf.Example zgodny z _bytes_feature _float_feature przy użyciu jednej z funkcji _bytes_feature , _float_feature , _int64_feature . Następnie możesz utworzyć wiadomość tf.Example wiadomość z tych zakodowanych funkcji:

 def serialize_example(feature0, feature1, feature2, feature3):
  """
  Creates a tf.Example message ready to be written to a file.
  """
  # Create a dictionary mapping the feature name to the tf.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()
 

Na przykład załóżmy, że masz pojedynczą obserwację ze zbioru danych, [False, 4, bytes('goat'), 0.9876] . Możesz utworzyć i wydrukować wiadomość tf.Example dla tej obserwacji za pomocą funkcji create_message() . Każda pojedyncza obserwacja zostanie zapisany jako Features wiadomości zgodnie z powyższym. Zauważ, że wiadomość tf.Example jest tylko tf.Example wokół wiadomości 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\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[\xd3|?'

Aby zdekodować wiadomość, użyj metody 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
      }
    }
  }
}

Szczegóły formatu TFRecords

Plik TFRecord zawiera sekwencję rekordów. Plik można odczytać tylko sekwencyjnie.

Każdy rekord zawiera ciąg bajtów dla ładunku danych, a także długość danych i skróty CRC32C (32-bitowe CRC używające wielomianu Castagnoliego) do sprawdzania integralności.

Każdy rekord jest przechowywany w następujących formatach:

 uint64 length
uint32 masked_crc32_of_length
byte   data[length]
uint32 masked_crc32_of_data
 

Rekordy są łączone razem w celu utworzenia pliku. CRC są opisane tutaj , a maska ​​CRC to:

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

Pliki tf.data przy użyciu tf.data

Moduł tf.data udostępnia również narzędzia do odczytu i zapisu danych w TensorFlow.

Pisanie pliku TFRecord

Najłatwiejszym sposobem na pobranie danych do zbioru danych jest użycie metody from_tensor_slices .

Zastosowany do tablicy, zwraca zestaw danych skalarów:

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

Zastosowany do krotki tablic, zwraca zestaw danych krotek:

 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.7334449193276843, shape=(), dtype=float64)

Użyj metody tf.data.Dataset.map , aby zastosować funkcję do każdego elementu Dataset .

Odwzorowana funkcja musi działać w trybie wykresu TensorFlow - musi działać na tf.Tensors i zwracać tf.Tensors . Funkcję tf.py_function niż tensor, taką jak serialize_example , można tf.py_function w tf.py_function aby była zgodna.

Korzystanie z tf.py_function wymaga określenia informacji o kształcie i typie, które w innym przypadku są niedostępne:

 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\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x01\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x0c\xc3;\xbf'>

Zastosuj tę funkcję do każdego elementu w zbiorze danych:

 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>

I zapisz je do pliku TFRecord:

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

Czytanie pliku TFRecord

Plik TFRecord można również odczytać za pomocą klasy tf.data.TFRecordDataset .

Więcej informacji na temat korzystania z plików tf.data przy użyciu tf.data można znaleźć tutaj .

Korzystanie z TFRecordDataset s może być przydatne do standaryzacji danych wejściowych i optymalizacji wydajności.

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

W tym momencie zbiór danych zawiera zserializowane komunikaty tf.train.Example . Po iteracji zwraca je jako skalarne tensory łańcuchów.

Użyj metody .take , aby wyświetlić tylko pierwsze 10 rekordów.

 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\x03dog\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x0c\xc3;\xbf\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'\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\x08feature2\x12\x08\n\x06\n\x04goat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04Da=?'>
<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\x08feature2\x12\x08\n\x06\n\x04goat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xaaV\xa6>'>
<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\x04>\x95\r\xbc\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x01\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x14\n\x08feature3\x12\x08\x12\x06\n\x042\xb0\xbe\xbf'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x8a\x0c\x9e;'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nS\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x03\n\x15\n\x08feature2\x12\t\n\x07\n\x05horse\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x8c9S?'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xbdk_\xbc'>
<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\x01\n\x13\n\x08feature2\x12\x07\n\x05\n\x03dog\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04H~\xd8?'>
<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\x08feature2\x12\x08\n\x06\n\x04goat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04z\x08\x1c?'>

Te tensory można przeanalizować za pomocą poniższej funkcji. Należy zauważyć, że feature_description jest konieczne tutaj, ponieważ zbiory danych użyć wykresu-wykonanie i potrzebują do tego opisu, aby zbudować swój kształt i typ podpisu:

 # 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.Example` proto using the dictionary above.
  return tf.io.parse_single_example(example_proto, feature_description)
 

Alternatywnie, użyj tf.parse example aby przeanalizować całą tf.parse example naraz. Zastosuj tę funkcję do każdego elementu w zbiorze danych za pomocą metody 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}>

Użyj przyspieszonego wykonania, aby wyświetlić obserwacje w zbiorze danych. W tym zbiorze danych znajduje się 10 000 obserwacji, ale wyświetlonych zostanie tylko pierwszych 10. Dane są wyświetlane jako słownik cech. Każda pozycja jest tf.Tensor , a element numpy tego tensora wyświetla wartość cechy:

 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.7334449>}
{'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.7397654>}
{'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.32487994>}
{'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.008641539>}
{'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.489752>}
{'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.004823272>}
{'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.82509685>}
{'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.013636527>}
{'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.6913538>}
{'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.60950434>}

W tym przypadku funkcja tf.parse_example rozpakowuje pola tf.Example do standardowych tensorów.

Pliki TFRecord w Pythonie

Moduł tf.io zawiera również funkcje czystego Pythona do odczytu i zapisu plików TFRecord.

Pisanie pliku TFRecord

Następnie zapisz 10 000 obserwacji do pliku test.tfrecord . Każda obserwacja jest konwertowana na wiadomość tf.Example , a następnie zapisywana do pliku. Następnie możesz sprawdzić, czy plik test.tfrecord został utworzony:

 # Write the `tf.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

Czytanie pliku TFRecord

Te serializowane tensory można łatwo przeanalizować przy użyciu 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.7334449291229248
      }
    }
  }
}


Przewodnik: odczyt i zapis danych obrazu

To jest kompleksowy przykład odczytu i zapisu danych obrazu przy użyciu TFRecords. Używając obrazu jako danych wejściowych, zapiszesz dane jako plik TFRecord, a następnie odczytasz plik z powrotem i wyświetlisz obraz.

Może to być przydatne, jeśli na przykład chcesz użyć kilku modeli w tym samym zestawie danych wejściowych. Zamiast przechowywać dane obrazu w stanie surowym, można je wstępnie przetworzyć w formacie TFRecords i wykorzystać we wszystkich dalszych procesach przetwarzania i modelowania.

Najpierw pobierzmy to zdjęcie kota na śniegu i to zdjęcie mostu Williamsburg w stanie Nowy Jork w budowie.

Pobierz obrazy

 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

Napisz plik TFRecord

Jak poprzednio, tf.Example funkcje jako typy zgodne z tf.Example . Przechowuje to funkcję nieprzetworzonego ciągu obrazu, a także wysokość, szerokość, głębokość i dowolną funkcję label . Ten ostatni jest używany podczas zapisywania pliku w celu rozróżnienia między obrazem kota a obrazem mostu. Użyj 0 dla obrazu kota i 1 dla obrazu przejściowego:

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

Zauważ, że wszystkie funkcje są teraz przechowywane w komunikacie tf.Example . Następnie sfunkcjonalizuj powyższy kod i zapisz przykładowe komunikaty do pliku o nazwie images.tfrecords :

 # Write the raw image files to `images.tfrecords`.
# First, process the two images into `tf.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

Przeczytaj plik TFRecord

Masz teraz plik - images.tfrecords - i możesz teraz iterować po zapisach w nim, aby przeczytać ponownie to, co napisałeś. Biorąc pod uwagę, że w tym przykładzie będziesz odtwarzać tylko obraz, jedyną potrzebną funkcją jest ciąg nieprzetworzonego obrazu. Wyodrębnij go za pomocą opisanych powyżej example.features.feature['image_raw'].bytes_list.value[0] , a mianowicie example.features.feature['image_raw'].bytes_list.value[0] . Możesz również użyć etykiet, aby określić, który rekord jest kotem, a który pomostem:

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

Odzyskaj obrazy z pliku TFRecord:

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

jpeg

jpeg