Trả lời cho sự kiện TensorFlow Everywhere tại địa phương của bạn ngay hôm nay!
Trang này được dịch bởi Cloud Translation API.
Switch to English

TFRecord và tf.train.Example

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ tay

Định dạng TFRecord là một định dạng đơn giản để lưu trữ một chuỗi các bản ghi nhị phân.

Bộ đệm giao thức là một thư viện đa ngôn ngữ, đa nền tảng để tuần tự hóa dữ liệu có cấu trúc một cách hiệu quả.

Thông báo giao thức được xác định bởi các tệp .proto , đây thường là cách dễ nhất để hiểu một loại thông báo.

tf.train.Example báo tf.train.Example (hoặc protobuf) là một loại thông báo linh hoạt thể hiện ánh xạ {"string": value} . Nó được thiết kế để sử dụng với TensorFlow và được sử dụng trong các API cấp cao hơn như TFX .

tf.train.Example tay này sẽ trình bày cách tạo, phân tích cú pháp và sử dụng thông báo tf.train.Example , sau đó tuần tự hóa, viết và đọc các thông báo tf.train.Example đến và từ các tệp .tfrecord .

Thiết lập

import tensorflow as tf

import numpy as np
import IPython.display as display

tf.train.Example

Các kiểu dữ liệu cho tf.train.Example

Về cơ bản, một tf.train.Example là một ánh xạ {"string": tf.train.Feature} .

Loại thông báo tf.train.Feature có thể chấp nhận một trong ba loại sau (Xem tệp .proto để tham khảo). Hầu hết các loại chung khác có thể bị ép buộc vào một trong những loại sau:

  1. tf.train.BytesList (các loại sau có thể bị ép buộc)

    • string
    • byte
  2. tf.train.FloatList (các loại sau có thể bị ép buộc)

    • float ( float32 )
    • double ( float64 )
  3. tf.train.Int64List (các loại sau có thể bị ép buộc)

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

Để chuyển đổi loại TensorFlow tiêu chuẩn thành tf.train.Example tương thích với tf.train.Feature , bạn có thể sử dụng các hàm phím tắt bên dưới. Lưu ý rằng mỗi hàm nhận một giá trị đầu vào vô hướng và trả về một tf.train.Feature chứa một trong ba loại list ở trên:

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

Dưới đây là một số ví dụ về cách hoạt động của các hàm này. Lưu ý các loại đầu vào khác nhau và các loại đầu ra tiêu chuẩn hóa. Nếu kiểu đầu vào cho một hàm không khớp với một trong các kiểu bắt buộc đã nêu ở trên, hàm sẽ tạo ra một ngoại lệ (ví dụ: _int64_feature(1.0) sẽ bị lỗi, vì 1.0 là một float, vì vậy nên được sử dụng với hàm _float_feature để thay thế) :

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
}


Tất cả các thông báo proto có thể được tuần tự hóa thành chuỗi nhị phân bằng phương thức .SerializeToString :

feature = _float_feature(np.exp(1))

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

Tạo thông báo tf.train.Example

Giả sử bạn muốn tạo một thông báo tf.train.Example từ dữ liệu hiện có. Trên thực tế, tập dữ liệu có thể đến từ bất kỳ đâu, nhưng quy trình tạo thông báo tf.train.Example từ một lần quan sát sẽ giống nhau:

  1. Trong mỗi quan sát, mỗi giá trị cần được chuyển đổi thành tf.train.Feature chứa một trong 3 loại tương thích, sử dụng một trong các chức năng ở trên.

  2. Bạn tạo một bản đồ (từ điển) từ chuỗi tên đối tượng đến giá trị đối tượng địa lý được mã hóa trong # 1.

  3. Bản đồ được tạo ở bước 2 được chuyển đổi thành thông báo Features .

Trong sổ tay này, bạn sẽ tạo một tập dữ liệu bằng NumPy.

Tập dữ liệu này sẽ có 4 tính năng:

  • một tính năng boolean, False hoặc True với xác suất như nhau
  • một đối tượng số nguyên được chọn ngẫu nhiên thống nhất từ [0, 5]
  • tính năng chuỗi được tạo từ bảng chuỗi bằng cách sử dụng tính năng số nguyên làm chỉ mục
  • tính năng float từ phân phối chuẩn chuẩn

Hãy xem xét một mẫu bao gồm 10.000 quan sát được phân bố độc lập và giống hệt nhau từ mỗi phân bố trên:

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

Mỗi tính năng này có thể được ép buộc thành một loại tương thích tf.train.Example bằng cách sử dụng một trong các _bytes_feature , _float_feature , _int64_feature . Sau đó, bạn có thể tạo thông báo tf.train.Example từ các tính năng được mã hóa sau:

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

Ví dụ: giả sử bạn có một quan sát từ tập dữ liệu, [False, 4, bytes('goat'), 0.9876] . Bạn có thể tạo và in thông báo tf.train.Example cho quan sát này bằng cách sử dụng create_message() . Mỗi quan sát đơn lẻ sẽ được viết dưới dạng thông báo Features như ở trên. Lưu ý rằng thông báo tf.train.Example chỉ là một trình bao bọc xung quanh thông báo 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'

Để giải mã thông báo, hãy sử dụng phương thức 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
      }
    }
  }
}

Chi tiết định dạng TFRecords

Tệp TFRecord chứa một chuỗi các bản ghi. Tệp chỉ có thể được đọc tuần tự.

Mỗi bản ghi chứa một chuỗi byte, cho tải trọng dữ liệu, cộng với độ dài dữ liệu và hàm băm CRC32C (CRC 32 bit sử dụng đa thức Castagnoli) để kiểm tra tính toàn vẹn.

Mỗi bản ghi được lưu trữ ở các định dạng sau:

uint64 length
uint32 masked_crc32_of_length
byte   data[length]
uint32 masked_crc32_of_data

Các bản ghi được nối với nhau để tạo ra tệp. CRC được mô tả ở đây và mặt nạ của CRC là:

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

Tệp TFRecord sử dụng tf.data

Mô-đun tf.data cũng cung cấp các công cụ để đọc và ghi dữ liệu trong TensorFlow.

Viết tệp TFRecord

Cách dễ nhất để đưa dữ liệu vào tập dữ liệu là sử dụng phương thức from_tensor_slices .

Được áp dụng cho một mảng, nó trả về một tập dữ liệu vô hướng:

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

Được áp dụng cho một bộ nhiều mảng, nó trả về một tập dữ liệu gồm các bộ giá trị:

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)

Sử dụng phương thức tf.data.Dataset.map để áp dụng một hàm cho mỗi phần tử của Dataset .

Hàm được ánh xạ phải hoạt động ở chế độ đồ thị TensorFlow — nó phải hoạt động trên và trả về tf.Tensors . Một hàm không phải tensor, như serialize_example , có thể được bao bọc bằng tf.py_function để làm cho nó tương thích.

Việc sử dụng tf.py_function yêu cầu phải chỉ định hình dạng và loại thông tin không có sẵn:

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

Áp dụng hàm này cho từng phần tử trong tập dữ liệu:

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>

Và ghi chúng vào tệp TFRecord:

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

Đọc tệp TFRecord

Bạn cũng có thể đọc tệp TFRecord bằng lớp tf.data.TFRecordDataset .

tf.data có thể tìm thêm thông tin về cách sử dụng tệp tf.data bằng tf.data tại đây .

Sử dụng TFRecordDataset s có thể hữu ích để chuẩn hóa dữ liệu đầu vào và tối ưu hóa hiệu suất.

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

Tại thời điểm này, tập dữ liệu chứa các thông báo tf.train.Example được tuần tự hóa. Khi được lặp lại, nó sẽ trả về chúng dưới dạng các chuỗi vô hướng.

Sử dụng phương thức .take để chỉ hiển thị 10 bản ghi đầu tiên.

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

Các tensor này có thể được phân tích cú pháp bằng cách sử dụng hàm bên dưới. Lưu ý rằng feature_description là cần thiết ở đây vì tập dữ liệu sử dụng việc thực thi đồ thị và cần mô tả này để xây dựng hình dạng và chữ ký kiểu của chúng:

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

Ngoài ra, sử dụng tf.parse example để phân tích cú pháp toàn bộ lô cùng một lúc. Áp dụng chức năng này cho từng mục trong tập dữ liệu bằng phương thức 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}>

Sử dụng thực thi háo hức để hiển thị các quan sát trong tập dữ liệu. Có 10.000 quan sát trong tập dữ liệu này, nhưng bạn sẽ chỉ hiển thị 10. Dữ liệu đầu tiên được hiển thị dưới dạng từ điển các tính năng. Mỗi mục là một tf.Tensor và phần tử numpy của tensor này hiển thị giá trị của đối tượng địa lý:

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

Ở đây, hàm tf.parse_example giải nén các trường tf.train.Example thành các tensor tiêu chuẩn.

Tệp TFRecord bằng Python

Mô-đun tf.io cũng chứa các hàm thuần Python để đọc và ghi các tệp TFRecord.

Viết tệp TFRecord

Tiếp theo, ghi 10.000 quan sát vào tệp test.tfrecord . Mỗi quan sát được chuyển đổi thành một thông báo tf.train.Example , sau đó được ghi vào tệp. Sau đó, bạn có thể xác minh rằng tệp test.tfrecord đã được tạo:

# 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

Đọc tệp TFRecord

Các bộ căng được tuần tự hóa này có thể dễ dàng phân tích cú pháp bằng 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
      }
    }
  }
}


Hướng dẫn: Đọc và ghi dữ liệu hình ảnh

Đây là một ví dụ đầu cuối về cách đọc và ghi dữ liệu hình ảnh bằng TFRecords. Sử dụng hình ảnh làm dữ liệu đầu vào, bạn sẽ ghi dữ liệu dưới dạng tệp TFRecord, sau đó đọc lại tệp và hiển thị hình ảnh.

Điều này có thể hữu ích nếu, ví dụ, bạn muốn sử dụng một số mô hình trên cùng một tập dữ liệu đầu vào. Thay vì lưu trữ dữ liệu hình ảnh thô, nó có thể được xử lý trước thành định dạng TFRecords và có thể được sử dụng trong tất cả các quá trình xử lý và mô hình hóa tiếp theo.

Đầu tiên, hãy tải xuống hình ảnh một con mèo trong tuyết và bức ảnh này về Cầu Williamsburg, NYC đang được xây dựng.

Tìm nạp hình ảnh

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

Ghi tệp TFRecord

Như trước đây, hãy mã hóa các tính năng dưới dạng các loại tương thích với tf.train.Example . Điều này lưu trữ tính năng chuỗi hình ảnh thô, cũng như chiều cao, chiều rộng, chiều sâu và tính năng label tùy ý. Cái sau được sử dụng khi bạn viết tệp để phân biệt giữa hình ảnh con mèo và hình ảnh cây cầu. Sử dụng 0 cho hình ảnh con mèo và 1 cho hình ảnh cây cầu:

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

Lưu ý rằng tất cả các tính năng hiện được lưu trữ trong thông báo tf.train.Example . Tiếp theo, chức năng hóa đoạn mã trên và viết các thông báo mẫu vào tệp có tên 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

Đọc tệp TFRecord

Bây giờ bạn có images.tfrecords —và bây giờ có thể lặp lại các bản ghi trong đó để đọc lại những gì bạn đã viết. Giả sử trong ví dụ này, bạn sẽ chỉ tái tạo hình ảnh, tính năng duy nhất bạn cần là chuỗi hình ảnh thô. Giải nén nó bằng cách sử dụng getters được mô tả ở trên, cụ thể là example.features.feature['image_raw'].bytes_list.value[0] . Bạn cũng có thể sử dụng các nhãn để xác định bản ghi nào là mèo và bản ghi nào là cầu nối:

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

Khôi phục hình ảnh từ tệp TFRecord:

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

jpeg

jpeg