Menyesuaikan decoding fitur

API tfds.decode memungkinkan Anda mengganti decoding fitur default. Kasus penggunaan utamanya adalah melewatkan decoding gambar untuk kinerja yang lebih baik.

Contoh penggunaan

Melewatkan decoding gambar

Untuk mempertahankan kontrol penuh atas alur dekode, atau untuk menerapkan filter sebelum gambar didekode (untuk performa lebih baik), Anda dapat melewati dekode gambar sepenuhnya. Ini berfungsi dengan tfds.features.Image dan tfds.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

Filter/acak kumpulan data sebelum gambar didekodekan

Mirip dengan contoh sebelumnya, Anda dapat menggunakan tfds.decode.SkipDecoding() untuk menyisipkan kustomisasi pipeline tf.data tambahan sebelum mendekode gambar. Dengan begitu, gambar yang difilter tidak akan didekodekan dan Anda dapat menggunakan buffer acak yang lebih besar.

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

Memotong dan mendekode secara bersamaan

Untuk mengganti operasi tf.io.decode_image default, Anda dapat membuat objek tfds.decode.Decoder baru menggunakan dekorator tfds.decode.make_decoder() .

@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(),
})

Yang setara dengan:

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

Menyesuaikan decoding video

Video adalah Sequence(Image()) . Saat menerapkan decoder khusus, dekoder tersebut akan diterapkan ke frame individual. Ini berarti decoder untuk gambar secara otomatis kompatibel dengan 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(),
})

Yang setara dengan:

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

Hanya memecahkan kode sub-kumpulan fitur.

Anda juga dapat melewatkan beberapa fitur sepenuhnya dengan menentukan hanya fitur yang Anda perlukan. Semua fitur lainnya akan diabaikan/dilewati.

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

TFDS akan memilih subset dari builder.info.features yang cocok dengan struktur tfds.decode.PartialDecoding yang diberikan.

Dalam kode di atas, fitur unggulan diekstraksi secara implisit agar cocok dengan builder.info.features . Dimungkinkan juga untuk mendefinisikan fitur-fiturnya secara eksplisit. Kode di atas setara dengan:

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=[]),
    }),
})

Metadata asli (nama label, bentuk gambar,...) secara otomatis digunakan kembali sehingga tidak perlu menyediakannya.

tfds.decode.SkipDecoding dapat diteruskan ke tfds.decode.PartialDecoding , melalui kwarg PartialDecoding(..., decoders={}) .