Cette page a été traduite par l'API Cloud Translation.
Switch to English

Augmentation des données

Voir sur TensorFlow.org Exécuter dans Google Colab Afficher la source sur GitHub Télécharger le carnet

Aperçu

Ce didacticiel présente l'augmentation des données: une technique pour augmenter la diversité de votre ensemble d'entraînement en appliquant des transformations aléatoires (mais réalistes) telles que la rotation d'image. Vous apprendrez à appliquer l'augmentation des données de deux manières. Tout d'abord, vous utiliserez les couches de prétraitement Keras . Ensuite, vous utiliserez tf.image .

Installer

pip install -q tf-nightly
WARNING: You are using pip version 20.2.2; however, version 20.2.3 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds

from tensorflow.keras import layers
from tensorflow.keras.datasets import mnist

Télécharger un jeu de données

Ce didacticiel utilise l' ensemble de données tf_flowers . Pour plus de commodité, téléchargez l'ensemble de données à l'aide des ensembles de données TensorFlow . Si vous souhaitez en savoir plus sur les autres méthodes d'importation de données, consultez le didacticiel de chargement d'images .

(train_ds, val_ds, test_ds), metadata = tfds.load(
    'tf_flowers',
    split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
    with_info=True,
    as_supervised=True,
)
Downloading and preparing dataset tf_flowers/3.0.1 (download: 218.21 MiB, generated: 221.83 MiB, total: 440.05 MiB) to /home/kbuilder/tensorflow_datasets/tf_flowers/3.0.1...

Warning:absl:Dataset tf_flowers is hosted on GCS. It will automatically be downloaded to your
local data directory. If you'd instead prefer to read directly from our public
GCS bucket (recommended if you're running on GCP), you can instead pass
`try_gcs=True` to `tfds.load` or set `data_dir=gs://tfds-data/datasets`.


Dataset tf_flowers downloaded and prepared to /home/kbuilder/tensorflow_datasets/tf_flowers/3.0.1. Subsequent calls will reuse this data.

L'ensemble de données des fleurs comprend cinq classes.

num_classes = metadata.features['label'].num_classes
print(num_classes)
5

Récupérons une image de l'ensemble de données et utilisons-la pour démontrer l'augmentation des données.

get_label_name = metadata.features['label'].int2str

image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))

png

Utiliser les couches de prétraitement Keras

Redimensionner et redimensionner

Vous pouvez utiliser des calques de prétraitement pour redimensionner vos images en une forme cohérente et pour redimensionner les valeurs de pixels.

IMG_SIZE = 180

resize_and_rescale = tf.keras.Sequential([
  layers.experimental.preprocessing.Resizing(IMG_SIZE, IMG_SIZE),
  layers.experimental.preprocessing.Rescaling(1./255)
])

Vous pouvez voir le résultat de l'application de ces calques à une image.

result = resize_and_rescale(image)
_ = plt.imshow(result)

png

Vous pouvez vérifier que les pixels sont entre [0-1] .

print("Min and max pixel values:", result.numpy().min(), result.numpy().max())
Min and max pixel values: 0.0 1.0

Augmentation des données

Vous pouvez également utiliser des couches de prétraitement pour l'augmentation des données.

Créons quelques couches de prétraitement et appliquons-les à plusieurs reprises à la même image.

data_augmentation = tf.keras.Sequential([
  layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
  layers.experimental.preprocessing.RandomRotation(0.2),
])
# Add the image to a batch
image = tf.expand_dims(image, 0)
plt.figure(figsize=(10, 10))
for i in range(9):
  augmented_image = data_augmentation(image)
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(augmented_image[0])
  plt.axis("off")

png

Il existe une variété de couches de prétraitement que vous pouvez utiliser pour l'augmentation des données, y compris les layers.RandomContrast , les layers.RandomCrop , les layers.RandomZoom , etc.

Deux options pour utiliser les couches de prétraitement

Vous pouvez utiliser ces couches de prétraitement de deux manières, avec des compromis importants.

Option 1: intégrez les couches de prétraitement à votre modèle

model = tf.keras.Sequential([
  resize_and_rescale,
  data_augmentation,
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  # Rest of your model
])

Il y a deux points importants à prendre en compte dans ce cas:

  • L'augmentation des données s'exécutera sur l'appareil, de manière synchrone avec le reste de vos couches, et bénéficiera de l'accélération GPU.

  • Lorsque vous exportez votre modèle à l'aide de model.save , les couches de prétraitement seront enregistrées avec le reste de votre modèle. Si vous déployez ultérieurement ce modèle, il standardisera automatiquement les images (selon la configuration de vos couches). Cela peut vous éviter d'avoir à réimplémenter cette logique côté serveur.

Option 2: appliquer les couches de prétraitement à votre jeu de données

aug_ds = train_ds.map(
  lambda x, y: (resize_and_rescale(x, training=True), y))

Avec cette approche, vous utilisez Dataset.map pour créer un ensemble de données qui produit des lots d'images augmentées. Dans ce cas:

  • L'augmentation des données se produira de manière asynchrone sur le processeur et n'est pas bloquante. Vous pouvez chevaucher l'entraînement de votre modèle sur le GPU avec le prétraitement des données, à l'aide de Dataset.prefetch , illustré ci-dessous.
  • Dans ce cas, les couches de pré-traitement ne seront pas exportées avec le modèle lorsque vous appelez model.save . Vous devrez les attacher à votre modèle avant de l'enregistrer ou de les réimplémenter côté serveur. Après l'entraînement, vous pouvez attacher les couches de prétraitement avant l'exportation.

Vous pouvez trouver un exemple de la première option dans le didacticiel de classification d'images . Démontrons ici la deuxième option.

Appliquer les couches de prétraitement aux jeux de données

Configurez les ensembles de données de train, de validation et de test avec les couches de prétraitement que vous avez créées ci-dessus. Vous allez également configurer les ensembles de données pour les performances, en utilisant des lectures parallèles et une prélecture tamponnée pour générer des lots à partir du disque sans que les E / S deviennent bloquantes. Vous pouvez en savoir plus sur les performances de l'ensemble de données dans le guide Meilleures performances avec l'API tf.data .

batch_size = 32
AUTOTUNE = tf.data.experimental.AUTOTUNE

def prepare(ds, shuffle=False, augment=False):
  # Resize and rescale all datasets
  ds = ds.map(lambda x, y: (resize_and_rescale(x), y), 
              num_parallel_calls=AUTOTUNE)

  if shuffle:
    ds = ds.shuffle(1000)

  # Batch all datasets
  ds = ds.batch(batch_size)

  # Use data augmentation only on the training set
  if augment:
    ds = ds.map(lambda x, y: (data_augmentation(x, training=True), y), 
                num_parallel_calls=AUTOTUNE)

  # Use buffered prefecting on all datasets
  return ds.prefetch(buffer_size=AUTOTUNE)
train_ds = prepare(train_ds, shuffle=True, augment=True)
val_ds = prepare(val_ds)
test_ds = prepare(test_ds)

Former un mannequin

Par souci d'exhaustivité, vous allez maintenant entraîner un modèle à l'aide de ces jeux de données. Ce modèle n'a pas été réglé pour la précision (le but est de vous montrer la mécanique).

model = tf.keras.Sequential([
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(64, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Flatten(),
  layers.Dense(128, activation='relu'),
  layers.Dense(num_classes)
])
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
epochs=5
history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)
Epoch 1/5
92/92 [==============================] - 30s 315ms/step - loss: 1.5078 - accuracy: 0.3428 - val_loss: 1.0809 - val_accuracy: 0.6240
Epoch 2/5
92/92 [==============================] - 28s 303ms/step - loss: 1.0781 - accuracy: 0.5724 - val_loss: 0.9762 - val_accuracy: 0.6322
Epoch 3/5
92/92 [==============================] - 28s 295ms/step - loss: 1.0083 - accuracy: 0.5900 - val_loss: 0.9570 - val_accuracy: 0.6376
Epoch 4/5
92/92 [==============================] - 28s 300ms/step - loss: 0.9537 - accuracy: 0.6116 - val_loss: 0.9081 - val_accuracy: 0.6485
Epoch 5/5
92/92 [==============================] - 28s 301ms/step - loss: 0.8816 - accuracy: 0.6525 - val_loss: 0.8353 - val_accuracy: 0.6594

loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)
12/12 [==============================] - 1s 83ms/step - loss: 0.8226 - accuracy: 0.6567
Accuracy 0.6566757559776306

Augmentation des données personnalisées

Vous pouvez également créer des couches d'augmentation de données personnalisées. Ce didacticiel montre deux façons de procéder. Tout d'abord, vous allez créer une couche layers.Lambda . C'est un bon moyen d'écrire du code concis. Ensuite, vous allez écrire une nouvelle couche via la sous - classification , ce qui vous donne plus de contrôle. Les deux couches inverseront de manière aléatoire les couleurs d'une image, selon une certaine probabilité.

def random_invert_img(x, p=0.5):
  if  tf.random.uniform([]) < p:
    x = (255-x)
  else:
    x
  return x
def random_invert(factor=0.5):
  return layers.Lambda(lambda x: random_invert_img(x, factor))

random_invert = random_invert()
plt.figure(figsize=(10, 10))
for i in range(9):
  augmented_image = random_invert(image)
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(augmented_image[0].numpy().astype("uint8"))
  plt.axis("off")

png

Ensuite, implémentez une couche personnalisée par sous-classification .

class RandomInvert(layers.Layer):
  def __init__(self, factor=0.5, **kwargs):
    super().__init__(**kwargs)
    self.factor = factor

  def call(self, x):
    return random_invert_img(x)
_ = plt.imshow(RandomInvert()(image)[0])

png

Ces deux couches peuvent être utilisées comme décrit dans les options 1 et 2 ci-dessus.

Utilisation de tf.image

Les utilitaires de layers.preprocessing - layers.preprocessing ci-dessus sont pratiques. Pour un contrôle plus fin, vous pouvez écrire vos propres pipelines ou couches d'augmentation de données à l'aide de tf.data et tf.image . Vous pouvez également consulter TensorFlow Addons Image: Operations and TensorFlow I / O: Color Space Conversions

Étant donné que le jeu de données Flowers a été précédemment configuré avec l'augmentation des données, réimportons-le pour recommencer.

(train_ds, val_ds, test_ds), metadata = tfds.load(
    'tf_flowers',
    split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
    with_info=True,
    as_supervised=True,
)

Récupérez une image avec laquelle travailler.

image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))

png

Utilisons la fonction suivante pour visualiser et comparer côte à côte les images originales et augmentées.

def visualize(original, augmented):
  fig = plt.figure()
  plt.subplot(1,2,1)
  plt.title('Original image')
  plt.imshow(original)

  plt.subplot(1,2,2)
  plt.title('Augmented image')
  plt.imshow(augmented)

Augmentation des données

Retourner l'image

Retourner l'image verticalement ou horizontalement.

flipped = tf.image.flip_left_right(image)
visualize(image, flipped)

png

Niveaux de gris de l'image

Niveaux de gris d'une image.

grayscaled = tf.image.rgb_to_grayscale(image)
visualize(image, tf.squeeze(grayscaled))
_ = plt.colorbar()

png

Saturer l'image

Saturez une image en fournissant un facteur de saturation.

saturated = tf.image.adjust_saturation(image, 3)
visualize(image, saturated)

png

Changer la luminosité de l'image

Modifiez la luminosité de l'image en fournissant un facteur de luminosité.

bright = tf.image.adjust_brightness(image, 0.4)
visualize(image, bright)

png

Centrer recadrer l'image

Recadrez l'image du centre jusqu'à la partie d'image que vous désirez.

cropped = tf.image.central_crop(image, central_fraction=0.5)
visualize(image,cropped)

png

Faire pivoter l'image

Faites pivoter une image de 90 degrés.

rotated = tf.image.rot90(image)
visualize(image, rotated)

png

Appliquer l'augmentation à un jeu de données

Comme précédemment, appliquez l'augmentation des données à un ensemble de données à l'aide de Dataset.map .

def resize_and_rescale(image, label):
  image = tf.cast(image, tf.float32)
  image = tf.image.resize(image, [IMG_SIZE, IMG_SIZE])
  image = (image / 255.0)
  return image, label
def augment(image,label):
  image, label = resize_and_rescale(image, label)
  # Add 6 pixels of padding
  image = tf.image.resize_with_crop_or_pad(image, IMG_SIZE + 6, IMG_SIZE + 6) 
   # Random crop back to the original size
  image = tf.image.random_crop(image, size=[IMG_SIZE, IMG_SIZE, 3])
  image = tf.image.random_brightness(image, max_delta=0.5) # Random brightness
  image = tf.clip_by_value(image, 0, 1)
  return image, label

Configurer les ensembles de données

train_ds = (
    train_ds
    .shuffle(1000)
    .map(augment, num_parallel_calls=AUTOTUNE)
    .batch(batch_size)
    .prefetch(AUTOTUNE)
) 
val_ds = (
    val_ds
    .map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
    .batch(batch_size)
    .prefetch(AUTOTUNE)
)
test_ds = (
    test_ds
    .map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
    .batch(batch_size)
    .prefetch(AUTOTUNE)
)

Ces ensembles de données peuvent désormais être utilisés pour entraîner un modèle comme indiqué précédemment.

Prochaines étapes

Ce didacticiel a tf.image augmentation des données à l'aide des couches de prétraitement Keras et de tf.image . Pour savoir comment inclure des couches de prétraitement dans votre modèle, consultez le didacticiel sur la classification d'images . Vous voudrez peut-être également apprendre comment le prétraitement des couches peut vous aider à classer le texte, comme indiqué dans le didacticiel de classification de texte de base . Vous pouvez en savoir plus sur tf.data dans ce guide , et vous pouvez apprendre comment configurer vos pipelines d'entrée pour les performances ici .