Как применить увеличение данных в TensorFlow 2.0 после tfds.load () - PullRequest
4 голосов
/ 13 марта 2019

Я следую этому руководству .

Показывает, как загружать наборы данных из новых наборов данных TensorFlow, используя метод tfds.load():

import tensorflow_datasets as tfds    
SPLIT_WEIGHTS = (8, 1, 1)
splits = tfds.Split.TRAIN.subsplit(weighted=SPLIT_WEIGHTS)

(raw_train, raw_validation, raw_test), metadata = tfds.load(
    'cats_vs_dogs', split=list(splits),
    with_info=True, as_supervised=True)

Следующие шаги показывают, как применить функцию к каждому элементу в наборе данных, используя метод карты:

def format_example(image, label):
    image = tf.cast(image, tf.float32)
    image = image / 255.0
    # Resize the image if required
    image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE))
    return image, label

train = raw_train.map(format_example)
validation = raw_validation.map(format_example)
test = raw_test.map(format_example)

Затем для доступа к элементам мы можем использовать:

for features in ds_train.take(1):
  image, label = features["image"], features["label"]

OR

for example in tfds.as_numpy(train_ds):
  numpy_images, numpy_labels = example["image"], example["label"]

Однако в руководстве ничего не говорится об увеличении данных. Я хочу использовать расширение данных в реальном времени, аналогичное классу Keras ImageDataGenerator. Я пытался использовать:

if np.random.rand() > 0.5:
    image = tf.image.flip_left_right(image)

и другие подобные функции дополнения в format_example(), но как я могу убедиться, что он выполняет увеличение в реальном времени и не заменяет исходное изображение в наборе данных?

Я мог бы преобразовать полный набор данных в массив Numpy, передав batch_size=-1 в tfds.load(), а затем использовать tfds.as_numpy(), но это загрузило бы все изображения в память, которая не нужна. Я должен быть в состоянии использовать train = train.prefetch(tf.data.experimental.AUTOTUNE), чтобы загрузить достаточно данных для следующего цикла обучения.

1 Ответ

2 голосов
/ 09 апреля 2019

Вы подходите к проблеме с неправильного направления.

Сначала загрузите данные, используя, например, tfds.load, cifar10 (для простоты мы будем использовать расщепления по умолчанию TRAIN и TEST):

import tensorflow_datasets as tfds

dataloader = tfds.load("cifar10", as_supervised=True)
train, test = dataloader["train"], dataloader["test"]

(вы можете использовать пользовательские tfds.Split объекты для создания проверочных наборов данных или другие, см. Документацию )

train и test являются объектами tf.data.Dataset, поэтому вы можете использовать map, apply, batch и аналогичные функции для каждого из них.

Ниже приведен пример, где я буду (в основном tf.image):

  • преобразовать каждое изображение в tf.float64 в диапазоне 0-1 (не используйте этот тупой фрагмент из официальных документов, таким образом обеспечивается правильный формат изображения)
  • cache() результаты, так как они могут использоваться повторно после каждого repeat
  • случайное отражение left_to_right каждое изображение
  • случайное изменение контрастности изображения
  • данные в случайном порядке и пакет
  • ВАЖНО: повторите все шаги, когда набор данных исчерпан. Это означает, что после одной эпохи все вышеупомянутые преобразования применяются снова (кроме тех, которые были кэшированы).

Вот код, выполняющий вышеописанное (вы можете изменить lambda s на функторы или функции):

train = train.map(
    lambda image, label: (tf.image.convert_image_dtype(image, tf.float32), label)
).cache().map(
    lambda image, label: (tf.image.random_flip_left_right(image), label)
).map(
    lambda image, label: (tf.image.random_contrast(image, lower=0.0, upper=1.0), label)
).shuffle(
    100
).batch(
    64
).repeat()

Такие tf.data.Dataset могут быть переданы непосредственно в методы Keras fit, evaluate и predict.

Проверка, что на самом деле это работает так

Я вижу, вы очень подозрительно относитесь к моим объяснениям, давайте рассмотрим пример:

1. Получить небольшое подмножество данных

Вот один из способов взять один элемент, по общему признанию, нечитаемый и не интуитивно понятный, но с ним все будет в порядке, если вы сделаете что-нибудь с Tensorflow:

# Horrible API is horrible
element = tfds.load(
    # Take one percent of test and take 1 element from it
    "cifar10",
    as_supervised=True,
    split=tfds.Split.TEST.subsplit(tfds.percent[:1]),
).take(1)

2. Повторите данные и проверьте, совпадают ли они:

Используя Tensorflow 2.0, на самом деле это можно сделать без глупых обходных путей (почти):

element = element.repeat(2)
# You can iterate through tf.data.Dataset now, finally...
images = [image[0] for image in element]
print(f"Are the same: {tf.reduce_all(tf.equal(images[0], images[1]))}")

И это неудивительно, что возвращается:

Are the same: True

3. Проверьте, отличаются ли данные после каждого повтора, со случайным увеличением

Ниже фрагмента repeat с одним элементом 5 раз и проверками, которые равны и которые различны.

element = (
    tfds.load(
        # Take one percent of test and take 1 element
        "cifar10",
        as_supervised=True,
        split=tfds.Split.TEST.subsplit(tfds.percent[:1]),
    )
    .take(1)
    .map(lambda image, label: (tf.image.random_flip_left_right(image), label))
    .repeat(5)
)

images = [image[0] for image in element]

for i in range(len(images)):
    for j in range(i, len(images)):
        print(
            f"{i} same as {j}: {tf.reduce_all(tf.equal(images[i], images[j]))}"
        )

Вывод (в моем случае каждый прогон будет разным):

0 same as 0: True
0 same as 1: False
0 same as 2: True
0 same as 3: False
0 same as 4: False
1 same as 1: True
1 same as 2: False
1 same as 3: True
1 same as 4: True
2 same as 2: True
2 same as 3: False
2 same as 4: False
3 same as 3: True
3 same as 4: True
4 same as 4: True

Вы можете также преобразовать каждое из этих изображений в numpy и посмотреть изображения для себя, используя skimage.io.imshow, matplotlib.pyplot.imshow или другие альтернативы.

Еще один пример визуализации дополнения данных в реальном времени

Этот ответ обеспечивает более полное и удобочитаемое представление об увеличении данных с использованием Tensorboard и MNIST, возможно, захотите проверить это (да, бесстыдный плагин, но, думаю, полезный).

...