Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Augmentasi data

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Gambaran

Tutorial ini mendemonstrasikan augmentasi data: teknik untuk meningkatkan keragaman set pelatihan Anda dengan menerapkan transformasi acak (tetapi realistis) seperti rotasi gambar. Anda akan mempelajari cara menerapkan augmentasi data dengan dua cara. Pertama, Anda akan menggunakan Lapisan Pra-pemrosesan Keras . Selanjutnya, Anda akan menggunakan tf.image .

Mempersiapkan

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

Unduh kumpulan data

Tutorial ini menggunakan kumpulan data tf_flowers . Untuk kenyamanan, download set data menggunakan TensorFlow Dataset . Jika Anda ingin mempelajari cara lain untuk mengimpor data, lihat tutorial memuat gambar .

(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.

Dataset bunga memiliki lima kelas.

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

Mari ambil gambar dari kumpulan data dan gunakan untuk mendemonstrasikan augmentasi data.

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

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

png

Gunakan lapisan preprocessing Keras

Mengubah ukuran dan mengubah skala

Anda dapat menggunakan preprocessing lapisan untuk mengubah ukuran gambar Anda ke bentuk yang konsisten, dan rescale nilai piksel.

IMG_SIZE = 180

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

Anda dapat melihat hasil penerapan lapisan ini ke gambar.

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

png

Anda dapat memverifikasi piksel dalam [0-1] .

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

Augmentasi data

Anda juga dapat menggunakan lapisan pra-pemrosesan untuk augmentasi data.

Mari buat beberapa layer preprocessing dan terapkan berulang kali ke gambar yang sama.

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

Ada berbagai macam lapisan layers.RandomContrast - layers.RandomCrop dapat Anda gunakan untuk augmentasi data termasuk layers.RandomContrast , layers.RandomCrop , layers.RandomZoom , dan lainnya.

Dua opsi untuk menggunakan lapisan pra-pemrosesan

Ada dua cara Anda dapat menggunakan lapisan pra-pemrosesan ini, dengan pengorbanan penting.

Opsi 1: Jadikan lapisan praproses sebagai bagian dari model Anda

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

Ada dua hal penting yang harus diperhatikan dalam kasus ini:

  • Augmentasi data akan berjalan di perangkat, selaras dengan seluruh lapisan Anda, dan mendapatkan keuntungan dari akselerasi GPU.

  • Saat Anda mengekspor model menggunakan model.save , lapisan model.save - model.save akan disimpan bersama dengan model Anda lainnya. Jika Anda kemudian menerapkan model ini, itu akan secara otomatis membakukan gambar (sesuai dengan konfigurasi lapisan Anda). Ini dapat menyelamatkan Anda dari upaya harus menerapkan ulang logika sisi server itu.

Opsi 2: Terapkan lapisan pra-pemrosesan ke kumpulan data Anda

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

Dengan pendekatan ini, Anda menggunakan Dataset.map untuk membuat kumpulan data yang menghasilkan kumpulan gambar yang ditambah. Pada kasus ini:

  • Augmentasi data akan terjadi secara asinkron di CPU, dan tidak memblokir. Anda dapat tumpang tindih pelatihan model Anda di GPU dengan prapemrosesan data, menggunakan Dataset.prefetch , yang ditunjukkan di bawah ini.
  • Dalam hal ini lapisan prepreprocessing tidak akan diekspor dengan model saat Anda memanggil model.save . Anda harus melampirkannya ke model Anda sebelum menyimpannya atau menerapkannya kembali di sisi server. Setelah pelatihan, Anda dapat melampirkan lapisan pra-pemrosesan sebelum mengekspor.

Anda dapat menemukan contoh opsi pertama di tutorial klasifikasi gambar . Mari kita tunjukkan opsi kedua di sini.

Menerapkan lapisan preprocessing ke dataset

Konfigurasikan kumpulan data train, validasi, dan pengujian dengan lapisan pra-pemrosesan yang Anda buat di atas. Anda juga akan mengonfigurasi set data untuk performa, menggunakan pembacaan paralel dan buffering prefetching untuk menghasilkan batch dari disk tanpa pemblokiran I / O. Anda dapat mempelajari lebih lanjut performa set data di Better performance dengan panduan 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)

Latih model

Untuk kelengkapan, Anda sekarang akan melatih model menggunakan kumpulan data ini. Model ini belum disetel keakuratannya (tujuannya adalah untuk menunjukkan kepada Anda mekaniknya).

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

Augmentasi data kustom

Anda juga dapat membuat lapisan augmenasi data kustom. Tutorial ini menunjukkan dua cara untuk melakukannya. Pertama, Anda akan membuat layers.Lambda layer. Ini adalah cara yang bagus untuk menulis kode yang ringkas. Selanjutnya, Anda akan menulis layer baru melalui subclassing , yang memberi Anda kontrol lebih. Kedua lapisan akan secara acak membalik warna pada gambar, menurut beberapa kemungkinan.

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

Selanjutnya, terapkan lapisan khusus dengan membuat subkelas .

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

Kedua lapisan ini dapat digunakan seperti yang dijelaskan pada opsi 1 dan 2 di atas.

Menggunakan tf.image

Utilitas layers.preprocessing atas nyaman digunakan. Untuk kontrol yang lebih baik, Anda dapat menulis pipeline atau lapisan augmentasi data Anda sendiri menggunakan tf.data dan tf.image . Anda mungkin juga ingin melihat TensorFlow Addons Image: Operations dan TensorFlow I / O: Color Space Conversions

Karena kumpulan data bunga sebelumnya dikonfigurasi dengan augmentasi data, mari kita impor ulang untuk memulai dari awal.

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

Ambil gambar untuk dikerjakan.

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

png

Mari gunakan fungsi berikut untuk memvisualisasikan dan membandingkan gambar asli dan gambar yang diperbesar secara berdampingan.

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)

Augmentasi data

Membalik gambar

Balikkan gambar secara vertikal atau horizontal.

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

png

Gambar menjadi abu-abu

Gambar menjadi abu-abu.

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

png

Saturasikan gambar

Saturasi gambar dengan memberikan faktor saturasi.

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

png

Ubah kecerahan gambar

Ubah kecerahan gambar dengan memberikan faktor kecerahan.

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

png

Pangkas gambar di tengah

Pangkas gambar dari tengah ke atas ke bagian gambar yang Anda inginkan.

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

png

Putar gambar

Putar gambar 90 derajat.

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

png

Terapkan augmentasi ke kumpulan data

Seperti sebelumnya, terapkan augmentasi data ke kumpulan data menggunakan 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

Konfigurasikan kumpulan data

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

Kumpulan data ini sekarang dapat digunakan untuk melatih model seperti yang ditunjukkan sebelumnya.

Langkah selanjutnya

Tutorial ini mendemonstrasikan augmentasi data menggunakan Keras Preprocessing Layers dan tf.image . Untuk mempelajari cara menyertakan lapisan praproses di dalam model Anda, lihat tutorial klasifikasi gambar . Anda mungkin juga tertarik mempelajari bagaimana lapisan pra-pemrosesan dapat membantu Anda mengklasifikasikan teks, seperti yang ditunjukkan dalam tutorial klasifikasi teks Dasar . Anda dapat mempelajari lebih lanjut tentang tf.data dalam panduan ini, dan Anda dapat mempelajari cara mengonfigurasi pipeline input Anda untuk performanya di sini .