Настройка декодирования функций

tfds.decode API позволяет переопределить декодирование функций по умолчанию. Основной вариант использования - пропустить декодирование изображения для повышения производительности.

Примеры использования

Пропуск декодирования изображения

Чтобы сохранить полный контроль над конвейером декодирования или применить фильтр до декодирования изображений (для повышения производительности), вы можете полностью пропустить декодирование изображения. Это работает как с tfds.features.Image и 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

Фильтр / перемешивание набора данных перед декодированием изображений

Точно так же и в предыдущем примере, можно использовать tfds.decode.SkipDecoding() , чтобы вставить дополнительные tf.data настройки трубопровода перед декодированием изображения. Таким образом, отфильтрованные изображения не будут декодироваться, и вы можете использовать буфер перетасовки большего размера.

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

Обрезка и декодирование одновременно

Для переопределения по умолчанию tf.io.decode_image операции, вы можете создать новый tfds.decode.Decoder объект с помощью 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(),
})

Что эквивалентно:

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

Настройка декодирования видео

Видео является Sequence(Image()) . При применении пользовательских декодеров они будут применяться к отдельным кадрам. Это означает, что декодеры изображений автоматически совместимы с видео.

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

Что эквивалентно:

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

Расшифровать только часть функций.

Также можно полностью пропустить некоторые функции, указав только те функции, которые вам нужны. Все остальные функции будут проигнорированы / пропущены.

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

TFDS выберет подмножество builder.info.features , соответствующий данное tfds.decode.PartialDecoding структуру.

В приведенной выше коде признаки неявно извлеченные в соответствии builder.info.features . Также возможно явное определение функций. Приведенный выше код эквивалентен:

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

Исходные метаданные (имена меток, форма изображения и т. Д.) Автоматически повторно используются, поэтому их не требуется предоставлять.

tfds.decode.SkipDecoding могут быть переданы в tfds.decode.PartialDecoding , через PartialDecoding(..., decoders={}) kwargs.