이 페이지는 Cloud Translation API를 통해 번역되었습니다.
Switch to English

TFRecord 및 tf.train.Example

TensorFlow.org에서보기 Google Colab에서 실행 GitHub에서 소스보기 노트북 다운로드

TFRecord 형식은 이진 레코드 시퀀스를 저장하기위한 간단한 형식입니다.

프로토콜 버퍼 는 구조화 된 데이터의 효율적인 직렬화를위한 플랫폼 간, 언어 간 라이브러리입니다.

프로토콜 메시지는 .proto 파일로 정의되며 메시지 유형을 이해하는 가장 쉬운 방법입니다.

tf.train.Example 메시지 (또는 protobuf)는 {"string": value} 매핑을 나타내는 유연한 메시지 유형입니다. TensorFlow와 함께 사용하도록 설계되었으며 TFX 와 같은 상위 수준 API 전체에서 사용됩니다.

이 노트북은, 구문 분석을 생성하고 사용하는 방법을 보여줍니다 tf.train.Example , 직렬화 다음 쓰기 메시지를, 그리고 읽기 tf.train.Example 와 메시지를 .tfrecord 파일.

설정

import tensorflow as tf

import numpy as np
import IPython.display as display

tf.train.Example

tf.train.Example 데이터 유형

기본적으로 tf.train.Example{"string": tf.train.Feature} 매핑입니다.

tf.train.Feature 메시지 유형은 다음 세 가지 유형 중 하나를 허용 할 수 있습니다 (참조는 .proto 파일 참조). 대부분의 다른 일반 유형은 다음 중 하나로 강제 변환 될 수 있습니다.

  1. tf.train.BytesList (다음 유형을 강제 변환 할 수 있음)

    • string
    • byte
  2. tf.train.FloatList (다음 유형을 강제 변환 할 수 있음)

    • float ( float32 )
    • double ( float64 )
  3. tf.train.Int64List (다음 유형을 강제 변환 할 수 있음)

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

표준 TensorFlow 유형을 tf.train.Example 호환 tf.train.Feature 로 변환하려면 아래 바로 가기 함수를 사용할 수 있습니다. 각 함수는 스칼라 입력 값을 취하고 위의 세 가지 list 유형 중 하나를 포함하는 tf.train.Feature 를 반환합니다.

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

다음은 이러한 기능의 작동 방식에 대한 몇 가지 예입니다. 다양한 입력 유형과 표준화 된 출력 유형에 유의하십시오. 함수의 입력 유형이 위에서 언급 한 강제 유형 중 하나와 일치하지 않으면 함수는 예외를 발생 _int64_feature(1.0) 예 : 1.0 은 부동 소수점이므로 _int64_feature(1.0) 은 오류가 발생하므로 대신 _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
}


모든 proto 메시지는 .SerializeToString 메서드를 사용하여 이진 문자열로 직렬화 할 수 있습니다.

feature = _float_feature(np.exp(1))

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

tf.train.Example 메시지 만들기

기존 데이터에서 tf.train.Example 메시지를 생성한다고 가정합니다. 실제로 데이터 세트는 어디에서나 올 수 있지만 단일 관찰에서 tf.train.Example 메시지를 만드는 절차는 동일합니다.

  1. 각 관찰 내에서 각 값은 위의 함수 중 하나를 사용하여 3 가지 호환 유형 중 하나를 포함하는 tf.train.Feature 로 변환되어야합니다.

  2. 기능 이름 문자열에서 # 1에서 생성 된 인코딩 된 기능 값으로 맵 (사전)을 만듭니다.

  3. 2 단계에서 생성 된 맵은 Features 메시지 로 변환됩니다.

이 노트북에서는 NumPy를 사용하여 데이터 세트를 생성합니다.

이 데이터 세트에는 4 가지 기능이 있습니다.

  • 부울 기능, 같은 확률의 False 또는 True
  • [0, 5] 에서 균일하게 무작위로 선택된 정수 특징
  • 정수 기능을 인덱스로 사용하여 문자열 테이블에서 생성 된 문자열 기능
  • 표준 정규 분포의 부동 특성

위의 각 분포에서 독립적으로 동일하게 분포 된 10,000 개의 관측치로 구성된 표본을 고려하십시오.

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

이러한 각 기능은 _bytes_feature , _float_feature , _int64_feature 중 하나를 사용하여 tf.train.Example 호환 유형으로 강제 변환 할 수 있습니다. 그런 다음 이러한 인코딩 된 기능에서 tf.train.Example 메시지를 만들 수 있습니다.

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

예를 들어 데이터 세트에서 단일 관측치가 있다고 가정합니다. [False, 4, bytes('goat'), 0.9876] . create_message() 사용 create_message() 관찰에 대한 tf.train.Example 메시지를 만들고 인쇄 할 수 있습니다. 각각의 관찰은 위와 같이 Features 메시지로 작성됩니다. tf.train.Example 메시지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'

메시지를 디코딩하려면 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
      }
    }
  }
}

TFRecords 형식 세부 정보

TFRecord 파일에는 일련의 레코드가 포함됩니다. 파일은 순차적으로 만 읽을 수 있습니다.

각 레코드에는 데이터 페이로드 용 바이트 문자열과 데이터 길이, 무결성 검사 용 CRC32C (Castagnoli 다항식을 사용하는 32 비트 CRC) 해시가 포함됩니다.

각 레코드는 다음 형식으로 저장됩니다.

uint64 length
uint32 masked_crc32_of_length
byte   data[length]
uint32 masked_crc32_of_data

레코드는 함께 연결되어 파일을 생성합니다. CRC는 여기설명 되어 있으며 CRC의 마스크는 다음과 같습니다.

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

TFRecord 사용하여 파일을 tf.data

tf.data 모듈은 TensorFlow에서 데이터를 읽고 쓰는 도구도 제공합니다.

TFRecord 파일 작성

데이터를 데이터 세트로 가져 오는 가장 쉬운 방법은 from_tensor_slices 메서드를 사용하는 from_tensor_slices 입니다.

배열에 적용하면 스칼라 데이터 집합을 반환합니다.

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

배열의 튜플에 적용하면 튜플의 데이터 세트를 반환합니다.

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)

tf.data.Dataset.map 메서드를 사용하여 Dataset 각 요소에 함수를 적용합니다.

매핑 된 함수는 TensorFlow 그래프 모드에서 작동해야하며 tf.Tensors 에서 작동하고 반환해야합니다. serialize_example 과 같은 비 텐서 함수는 tf.py_function 으로 래핑하여 호환되도록 할 수 있습니다.

tf.py_function 사용하려면 다른 방법으로는 사용할 수없는 모양 및 유형 정보를 지정해야합니다.

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

이 함수를 데이터 세트의 각 요소에 적용합니다.

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>

그리고 TFRecord 파일에 씁니다.

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

TFRecord 파일 읽기

tf.data.TFRecordDataset 클래스를 사용하여 TFRecord 파일을 읽을 수도 있습니다.

사용 TFRecord 파일 소모에 대한 자세한 내용 tf.data 찾을 수 있습니다 여기에 .

TFRecordDataset 사용하면 입력 데이터를 표준화하고 성능을 최적화하는 데 유용 할 수 있습니다.

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

이 시점에서 데이터 세트에는 직렬화 된 tf.train.Example 메시지가 포함됩니다. 반복하면이를 스칼라 문자열 텐서로 반환합니다.

.take 메서드를 사용하여 처음 10 개의 레코드 만 표시합니다.

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

이 텐서는 아래 함수를 사용하여 구문 분석 할 수 있습니다. 여기서 feature_description 은 데이터 셋이 그래프 실행을 사용하기 때문에 필요하며, 모양 및 유형 서명을 빌드하려면이 설명이 필요합니다.

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

또는 tf.parse example 를 사용하여 전체 일괄 처리를 한 번에 구문 분석합니다. 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}>

즉시 실행을 사용하여 데이터 세트의 관찰을 표시합니다. 이 데이터 세트에는 10,000 개의 관측치가 있지만 처음 10 개만 표시합니다. 데이터는 기능 사전으로 표시됩니다. 각 항목은 tf.Tensor 텐서의 numpy 요소는 기능의 값을 표시합니다.

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

여기서 tf.parse_example 함수는 tf.train.Example 필드를 표준 텐서로 압축을 풉니 다.

Python의 TFRecord 파일

tf.io 모듈에는 TFRecord 파일을 읽고 쓰기위한 순수 Python 함수도 포함되어 있습니다.

TFRecord 파일 작성

다음으로 10,000 개의 관측치를 test.tfrecord 파일에 test.tfrecord . 각 관찰은 tf.train.Example 메시지로 변환 된 다음 파일에 기록됩니다. 그런 다음 test.tfrecord 파일이 생성되었는지 확인할 수 있습니다.

# 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

TFRecord 파일 읽기

이러한 직렬화 된 텐서는 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
      }
    }
  }
}


연습 : 이미지 데이터 읽기 및 쓰기

이것은 TFRecords를 사용하여 이미지 데이터를 읽고 쓰는 방법에 대한 종단 간 예제입니다. 이미지를 입력 데이터로 사용하여 데이터를 TFRecord 파일로 쓴 다음 파일을 다시 읽고 이미지를 표시합니다.

예를 들어 동일한 입력 데이터 세트에서 여러 모델을 사용하려는 경우 유용 할 수 있습니다. 원시 이미지 데이터를 저장하는 대신 TFRecords 형식으로 사전 처리 할 수 ​​있으며 모든 추가 처리 및 모델링에 사용할 수 있습니다.

먼저 눈 속의 고양이 이미지 와 공사중인 뉴욕의 ​​윌리엄스 버그 다리 사진 을 다운로드 보겠습니다.

이미지 가져 오기

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

TFRecord 파일 작성

이전과 마찬가지로 기능을 tf.train.Example 과 호환되는 유형으로 인코딩합니다. 이것은 원시 이미지 문자열 기능뿐만 아니라 높이, 너비, 깊이 및 임의의 label 기능을 저장합니다. 후자는 파일을 작성하여 고양이 이미지와 브리지 이미지를 구분하는 데 사용됩니다. 고양이 이미지에 0 을 사용하고 브리지 이미지에 1 을 사용합니다.

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

이제 모든 기능이 tf.train.Example 메시지에 저장됩니다. 다음으로 위의 코드를 기능화하고 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

TFRecord 파일 읽기

이제 images.tfrecords 파일을 images.tfrecords 이제 그 안에있는 레코드를 반복하여 작성한 내용을 다시 읽을 수 있습니다. 이 예에서는 이미지 만 재현 할 것이므로 필요한 기능은 원시 이미지 문자열뿐입니다. 위에서 설명한 getter, 즉 example.features.feature['image_raw'].bytes_list.value[0] 사용하여 추출합니다. 레이블을 사용하여 어떤 레코드가 고양이이고 어느 레코드가 브리지인지 확인할 수도 있습니다.

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

TFRecord 파일에서 이미지를 복구합니다.

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

jpeg

jpeg