Tùy chỉnh giải mã tính năng

Các tfds.decode API cho phép bạn ghi đè lên giải mã tính năng mặc định. Trường hợp sử dụng chính là bỏ qua phần giải mã hình ảnh để có hiệu suất tốt hơn.

Các ví dụ sử dụng

Bỏ qua giải mã hình ảnh

Để giữ toàn quyền kiểm soát quy trình giải mã hoặc áp dụng bộ lọc trước khi hình ảnh được giải mã (để có hiệu suất tốt hơn), bạn có thể bỏ qua hoàn toàn việc giải mã hình ảnh. Này làm việc với cả hai tfds.features.Imagetfds.features.Video .

ds = tfds.load('imagenet2012', split='train', decoders={
    'image': tfds.decode.SkipDecoding(),
})

for example in ds.take(1):
  assert example['image'].dtype == tf.string  # Images are not decoded

Lọc / xáo trộn tập dữ liệu trước khi hình ảnh được giải mã

Tương tự như ví dụ trước, bạn có thể sử dụng tfds.decode.SkipDecoding() để chèn thêm tf.data chỉnh đường ống trước khi giải mã hình ảnh. Bằng cách đó, các hình ảnh được lọc sẽ không được giải mã và bạn có thể sử dụng bộ đệm xáo trộn lớn hơn.

# Load the base dataset without decoding
ds, ds_info = tfds.load(
    'imagenet2012',
    split='train',
    decoders={
        'image': tfds.decode.SkipDecoding(),  # Image won't be decoded here
    },
    as_supervised=True,
    with_info=True,
)
# Apply filter and shuffle
ds = ds.filter(lambda image, label: label != 10)
ds = ds.shuffle(10000)
# Then decode with ds_info.features['image']
ds = ds.map(
    lambda image, label: ds_info.features['image'].decode_example(image), label)

Cắt và giải mã cùng một lúc

Để ghi đè mặc định tf.io.decode_image hoạt động, bạn có thể tạo mới tfds.decode.Decoder đối tượng sử dụng tfds.decode.make_decoder() trang trí.

@tfds.decode.make_decoder()
def decode_example(serialized_image, feature):
  crop_y, crop_x, crop_height, crop_width = 10, 10, 64, 64
  return tf.image.decode_and_crop_jpeg(
      serialized_image,
      [crop_y, crop_x, crop_height, crop_width],
      channels=feature.feature.shape[-1],
  )

ds = tfds.load('imagenet2012', split='train', decoders={
    # With video, decoders are applied to individual frames
    'image': decode_example(),
})

Tương đương với:

def decode_example(serialized_image, feature):
  crop_y, crop_x, crop_height, crop_width = 10, 10, 64, 64
  return tf.image.decode_and_crop_jpeg(
      serialized_image,
      [crop_y, crop_x, crop_height, crop_width],
      channels=feature.shape[-1],
  )

ds, ds_info = tfds.load(
    'imagenet2012',
    split='train',
    with_info=True,
    decoders={
        'image': tfds.decode.SkipDecoding(),  # Skip frame decoding
    },
)
ds = ds.map(functools.partial(decode_example, feature=ds_info.features['image']))

Tùy chỉnh giải mã video

Video là Sequence(Image()) . Khi áp dụng bộ giải mã tùy chỉnh, chúng sẽ được áp dụng cho các khung riêng lẻ. Bộ giải mã trung bình này cho hình ảnh tự động tương thích với video.

@tfds.decode.make_decoder()
def decode_example(serialized_image, feature):
  crop_y, crop_x, crop_height, crop_width = 10, 10, 64, 64
  return tf.image.decode_and_crop_jpeg(
      serialized_image,
      [crop_y, crop_x, crop_height, crop_width],
      channels=feature.feature.shape[-1],
  )

ds = tfds.load('ucf101', split='train', decoders={
    # With video, decoders are applied to individual frames
    'video': decode_example(),
})

Tương đương với:

def decode_frame(serialized_image):
  """Decodes a single frame."""
  crop_y, crop_x, crop_height, crop_width = 10, 10, 64, 64
  return tf.image.decode_and_crop_jpeg(
      serialized_image,
      [crop_y, crop_x, crop_height, crop_width],
      channels=ds_info.features['video'].shape[-1],
  )


def decode_video(example):
  """Decodes all individual frames of the video."""
  video = example['video']
  video = tf.map_fn(
      decode_frame,
      video,
      dtype=ds_info.features['video'].dtype,
      parallel_iterations=10,
  )
  example['video'] = video
  return example


ds, ds_info = tfds.load('ucf101', split='train', with_info=True, decoders={
    'video': tfds.decode.SkipDecoding(),  # Skip frame decoding
})
ds = ds.map(decode_video)  # Decode the video

Chỉ giải mã một tập hợp con của các tính năng.

Cũng có thể bỏ qua hoàn toàn một số tính năng bằng cách chỉ xác định các tính năng bạn cần. Tất cả các tính năng khác sẽ bị bỏ qua / bỏ qua.

builder = tfds.builder('my_dataset')
builder.as_dataset(split='train', decoders=tfds.decode.PartialDecoding({
    'image': True,
    'metadata': {'num_objects', 'scene_name'},
    'objects': {'label'},
})

TFDS sẽ chọn tập hợp con của builder.info.features phù hợp với trao tfds.decode.PartialDecoding cấu trúc.

Trong đoạn mã trên, các tính năng được mặc nhiên được chiết xuất để phù hợp với builder.info.features . Nó cũng có thể xác định rõ ràng các tính năng. Đoạn mã trên tương đương với:

builder = tfds.builder('my_dataset')
builder.as_dataset(split='train', decoders=tfds.decode.PartialDecoding({
    'image': tfds.features.Image(),
    'metadata': {
        'num_objects': tf.int64,
        'scene_name': tfds.features.Text(),
    },
    'objects': tfds.features.Sequence({
        'label': tfds.features.ClassLabel(names=[]),
    }),
})

Siêu dữ liệu gốc (tên nhãn, hình ảnh, ...) được sử dụng lại tự động nên không bắt buộc phải cung cấp chúng.

tfds.decode.SkipDecoding thể được truyền cho tfds.decode.PartialDecoding , thông qua PartialDecoding(..., decoders={}) kwargs.