تاریخ را ذخیره کنید! Google I / O 18-20 مه بازمی گردد اکنون ثبت نام کنید
این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

افزایش داده ها

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub دانلود دفترچه یادداشت

بررسی اجمالی

این آموزش افزایش داده را نشان می دهد: روشی برای افزایش تنوع مجموعه آموزش شما با استفاده از تغییر شکل تصادفی (اما واقع بینانه) مانند چرخش تصویر. شما یاد خواهید گرفت که چگونه به دو روش افزایش داده را اعمال کنید. ابتدا از لایه های پیش پردازش Keras استفاده خواهید کرد. بعد ، شما از tf.image استفاده tf.image .

برپایی

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

یک مجموعه داده را بارگیری کنید

این آموزش از مجموعه داده tf_flowers استفاده می کند. برای راحتی کار ، مجموعه داده را با استفاده از مجموعه داده TensorFlow بارگیری کنید. اگر می خواهید با روش های وارد کردن داده ها درباره دیگران آشنا شوید ، به آموزش بارگذاری تصاویر مراجعه کنید .

(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 218.21 MiB (download: 218.21 MiB, generated: 221.83 MiB, total: 440.05 MiB) to /home/kbuilder/tensorflow_datasets/tf_flowers/3.0.1...
Dataset tf_flowers downloaded and prepared to /home/kbuilder/tensorflow_datasets/tf_flowers/3.0.1. Subsequent calls will reuse this data.

مجموعه داده گلها پنج کلاس دارد.

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

بیایید تصویری را از مجموعه داده بازیابی کرده و از آن برای نشان دادن افزایش داده استفاده کنیم.

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

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

png

از لایه های پیش پردازش Keras استفاده کنید

تغییر اندازه و کوچک کردن

می توانید از لایه های پیش پردازش برای تغییر اندازه تصاویر خود به یک شکل ثابت و تجدید مقادیر پیکسل استفاده کنید.

IMG_SIZE = 180

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

می توانید نتیجه اعمال این لایه ها روی یک تصویر را مشاهده کنید.

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

png

می توانید پیکسل ها را در [0-1] .

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

افزایش داده ها

برای بزرگ کردن داده ها می توانید از لایه های پیش پردازش نیز استفاده کنید.

بیایید چند لایه پیش پردازش ایجاد کنیم و آنها را به طور مکرر روی همان تصویر اعمال کنیم.

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

لایه های پیش پردازش متنوعی وجود دارد که می توانید برای افزایش داده از جمله لایه ها استفاده کنید. layers.RandomContrast ، layers.RandomCrop . layers.RandomZoom layers.RandomContrast ، layers.RandomCrop . layers.RandomZoom و سایر موارد.

دو گزینه برای استفاده از لایه های پیش پردازش

به دو روش می توانید از این لایه های پیش پردازش ، با مبادله های مهم استفاده کنید.

گزینه 1: لایه های پیش پردازش را بخشی از مدل خود کنید

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

در این مورد باید از دو نکته مهم آگاه باشید:

  • افزایش داده روی دستگاه انجام می شود ، همزمان با بقیه لایه های شما و از شتاب GPU بهره مند می شود.

  • وقتی مدل خود را با استفاده از model.save صادر می کنید ، لایه های پیش پردازش به همراه بقیه مدل شما ذخیره می شوند. اگر بعداً این مدل را پیاده کنید ، به طور خودکار تصاویر (با توجه به پیکربندی لایه های شما) استاندارد می شود. این می تواند شما را از تلاش برای اجرای مجدد آن سمت سرور منطقی نجات دهد.

گزینه 2: لایه های پیش پردازش را روی مجموعه داده خود اعمال کنید

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

با استفاده از این روش ، از Dataset.map برای ایجاد یک مجموعه داده استفاده می کنید که دسته ای از تصاویر افزوده را تولید می کند. در این مورد:

  • افزایش داده ها به طور همزمان در CPU اتفاق می افتد و مسدود کننده نیست. با استفاده از Dataset.prefetch ، که در زیر نشان داده شده است ، می توانید آموزش مدل خود را در پردازنده گرافیکی با پردازش داده ها Dataset.prefetch کنید.
  • در این حالت وقتی تماس بگیرید model.save لایه های پیش پردازش با مدل صادر نمی شوند. شما باید قبل از ذخیره مدل خود را به آن متصل کنید یا در سمت سرور دوباره اجرا کنید. پس از آموزش ، می توانید لایه های پیش پردازش را قبل از صادرات وصل کنید.

نمونه ای از اولین گزینه را می توانید در آموزش طبقه بندی تصاویر بیابید. بیایید گزینه دوم را در اینجا نشان دهیم.

لایه های پیش پردازش را روی مجموعه داده ها اعمال کنید

مجموعه داده های قطار ، اعتبارسنجی و آزمون را با لایه های پیش پردازش که در بالا ایجاد کرده اید ، پیکربندی کنید. همچنین می توانید مجموعه داده ها را برای کارایی پیکربندی کنید ، با استفاده از خواندن های موازی و پیش تنظیم بافر برای تولید دسته ها از دیسک بدون مسدود شدن ورودی / خروجی با راهنمای tf.data API می توانید عملکرد مجموعه داده های بیشتری را در عملکرد بهتر یاد بگیرید.

batch_size = 32
AUTOTUNE = tf.data.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)

یک مدل آموزش دهید

برای کامل بودن ، اکنون یک مدل را با استفاده از این مجموعه داده ها آموزش خواهید داد. این مدل برای دقت تنظیم نشده است (هدف نشان دادن مکانیک به شما است).

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 [==============================] - 17s 47ms/step - loss: 1.6206 - accuracy: 0.2998 - val_loss: 1.1271 - val_accuracy: 0.5613
Epoch 2/5
92/92 [==============================] - 3s 28ms/step - loss: 1.0935 - accuracy: 0.5384 - val_loss: 1.0343 - val_accuracy: 0.5858
Epoch 3/5
92/92 [==============================] - 3s 27ms/step - loss: 0.9785 - accuracy: 0.6022 - val_loss: 0.8810 - val_accuracy: 0.6540
Epoch 4/5
92/92 [==============================] - 3s 27ms/step - loss: 0.9167 - accuracy: 0.6399 - val_loss: 0.8247 - val_accuracy: 0.6594
Epoch 5/5
92/92 [==============================] - 3s 27ms/step - loss: 0.8545 - accuracy: 0.6615 - val_loss: 0.8591 - val_accuracy: 0.6458
loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)
12/12 [==============================] - 0s 13ms/step - loss: 0.9010 - accuracy: 0.6131
Accuracy 0.6130790114402771

افزایش داده های سفارشی

همچنین می توانید لایه های افزودنی داده های سفارشی ایجاد کنید. این آموزش دو روش انجام این کار را نشان می دهد. ابتدا یک لایه ایجاد خواهید کرد. لایه layers.Lambda . این روش خوبی برای نوشتن کد مختصر است. بعد ، شما یک لایه جدید از طریق طبقه بندی فرعی می نویسید ، که به شما امکان کنترل بیشتری می دهد. بنا به احتمال زیاد ، هر دو لایه به طور تصادفی رنگهای یک عکس را معکوس می کنند.

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

در مرحله بعد ، یک لایه سفارشی را با طبقه بندی فرعی پیاده سازی کنید.

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

هر دو این لایه ها را می توان همانطور که در گزینه های 1 و 2 بالا توضیح داده شده استفاده کرد.

با استفاده از tf.image

layers.preprocessing فوق. ابزارهای پیش layers.preprocessing مناسب هستند. برای کنترل دقیق تر ، می توانید خطوط لوله یا لایه های افزایش داده خود را با استفاده از tf.data و tf.image . همچنین ممکن است بخواهید TensorFlow Addons Image: Operations و TensorFlow I / O: تبدیل فضای رنگی را بررسی کنید.

از آنجا که مجموعه داده گلها قبلاً با افزایش داده پیکربندی شده بود ، بیایید آن را مجدداً وارد کنیم تا تازه شروع شود.

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

تصویری را برای کار با آن بازیابی کنید.

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

png

بیایید از عملکرد زیر برای تجسم و مقایسه تصاویر اصلی و افزوده شده در کنار هم استفاده کنیم.

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)

افزایش داده ها

برگرداندن تصویر

تصویر را به صورت عمودی یا افقی بچرخانید.

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

png

مقیاس خاکستری تصویر

مقیاس خاکستری یک تصویر.

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

png

اشباع تصویر

با ارائه یک عامل اشباع ، یک تصویر را اشباع کنید.

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

png

روشنایی تصویر را تغییر دهید

با ارائه یک عامل روشنایی ، روشنایی تصویر را تغییر دهید.

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

png

مرکز تصویر را برش دهید

تصویر را از مرکز به قسمت تصویری مورد نظر خود برش دهید.

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

png

تصویر را بچرخانید

یک تصویر را 90 درجه بچرخانید.

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

png

تحولات تصادفی

اعمال تغییرات تصادفی در تصاویر می تواند به تعمیم و گسترش مجموعه داده کمک کند. tf.image API فعلی 8 عملیات تصادفی تصویری از این دست را ارائه می دهد:

این گزینه های تصادفی تصویری کاملاً کاربردی هستند: خروجی فقط به ورودی بستگی دارد. این امر استفاده از آنها را در خطوط لوله ورودی قطعی با کارایی بالا ساده می کند. هر مرحله نیاز به مقدار seed دارند. با توجه به seed یکسان ، آنها نتایج مشابهی را بدون توجه به اینکه چند بار فراخوانی می شوند ، برمی گردانند.

در بخش های زیر ، ما:

  1. نمونه هایی از استفاده از عملیات تصادفی تصویری برای تبدیل تصویر را مرور کنید ، و
  2. نحوه اعمال تغییرات تصادفی در مجموعه داده های آموزشی را نشان دهید.

به طور تصادفی روشنایی تصویر را تغییر دهید

با تهیه یک عامل روشنایی و seed به طور تصادفی روشنایی image تغییر دهید. عامل روشنایی به طور تصادفی در محدوده [-max_delta, max_delta) و با seed داده شده مرتبط است.

for i in range(3):
  seed = (i, 0)  # tuple of size (2,)
  stateless_random_brightness = tf.image.stateless_random_brightness(
      image, max_delta=0.95, seed=seed)
  visualize(image, stateless_random_brightness)

png

png

png

کنتراست تصویر را به طور تصادفی تغییر دهید

با تهیه محدوده کنتراست و seed به طور تصادفی کنتراست image تغییر دهید. محدوده کنتراست به طور تصادفی در فاصله [lower, upper] و با seed داده شده مرتبط است.

for i in range(3):
  seed = (i, 0)  # tuple of size (2,)
  stateless_random_contrast = tf.image.stateless_random_contrast(
      image, lower=0.1, upper=0.9, seed=seed)
  visualize(image, stateless_random_contrast)

png

png

png

برش تصادفی یک تصویر

به صورت تصادفی برش image با ارائه هدف size و seed . بخشی که از image خارج می شود در یک جفت تصادفی انتخاب شده و با seed داده شده مرتبط است.

for i in range(3):
  seed = (i, 0)  # tuple of size (2,)
  stateless_random_crop = tf.image.stateless_random_crop(
      image, size=[210, 300, 3], seed=seed)
  visualize(image, stateless_random_crop)

png

png

png

تقویت را روی یک مجموعه داده اعمال کنید

در صورت اصلاح در بخش های قبلی ، ابتدا مجموعه داده را بارگیری می کنیم.

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

بیایید یک تابع کمکی برای تغییر اندازه و کوچک کردن تصاویر تعریف کنیم. این تابع در یکسان سازی اندازه و مقیاس تصاویر در مجموعه داده استفاده خواهد شد:

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

بیایید همچنین تابع augment تعریف کنیم که می تواند تغییرات تصادفی را بر روی تصاویر اعمال کند. این مرحله در مرحله بعدی روی مجموعه داده استفاده خواهد شد.

def augment(image_label, seed):
  image, label = image_label
  image, label = resize_and_rescale(image, label)
  image = tf.image.resize_with_crop_or_pad(image, IMG_SIZE + 6, IMG_SIZE + 6)
  # Make a new seed
  new_seed = tf.random.experimental.stateless_split(seed, num=1)[0, :]
  # Random crop back to the original size
  image = tf.image.stateless_random_crop(
      image, size=[IMG_SIZE, IMG_SIZE, 3], seed=seed)
  # Random brightness
  image = tf.image.stateless_random_brightness(
      image, max_delta=0.5, seed=new_seed)
  image = tf.clip_by_value(image, 0, 1)
  return image, label

گزینه 1: استفاده از tf.data.experimental.Counter()

یک شی tf.data.experimental.Counter() (بیایید آن را counter tf.data.experimental.Counter() ) و مجموعه داده را با (counter, counter) zip . این اطمینان حاصل می کند که هر تصویر در مجموعه داده بر اساس counter با یک مقدار منحصر به فرد (شکل (2,) ) مرتبط می شود که بعداً می تواند به عنوان مقدار seed برای تبدیلات تصادفی به تابع augment منتقل شود.

# Create counter and zip together with train dataset
counter = tf.data.experimental.Counter()
train_ds = tf.data.Dataset.zip((train_datasets, (counter, counter)))

تابع augment را به مجموعه داده های آموزشی ترسیم کنید.

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

گزینه 2: استفاده از tf.random.Generator

یک شی tf.random.Generator با مقدار seed . فراخوانی عملکرد make_seeds روی همان شی make_seeds مولد ، همیشه یک مقدار seed جدید و منحصر به فرد برمی گرداند. یک تابع بسته بندی را تعریف کنید که 1) تابع make_seeds فراخوانی کند و 2) مقدار seed تولید شده جدید را به تابع augment برای تبدیل های تصادفی منتقل کند.

# Create a generator
rng = tf.random.Generator.from_seed(123, alg='philox')
# A wrapper function for updating seeds
def f(x, y):
  seed = rng.make_seeds(2)[0]
  image, label = augment((x, y), seed)
  return image, label

تابع wrapper f به مجموعه داده آموزش ترسیم کنید.

train_ds = (
    train_datasets
    .shuffle(1000)
    .map(f, 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)
)

اکنون می توان از این مجموعه های داده برای آموزش مدلی استفاده کرد که قبلاً نشان داده شده است.

مراحل بعدی

این آموزش افزایش داده ها را با استفاده از لایه های پیش پردازش Keras و tf.image نشان داده است. برای یادگیری نحوه قرار دادن لایه های پیش پردازش در داخل مدل خود ، به آموزش طبقه بندی تصویر مراجعه کنید. همچنین ممکن است شما علاقه مند باشید که یاد بگیرید چگونه لایه های پیش پردازش می توانند به شما در طبقه بندی متن کمک کنند ، همانطور که در آموزش طبقه بندی متن اصلی نشان داده شده است. در این راهنما می توانید اطلاعات بیشتری در مورد tf.data ، و نحوه پیکربندی خطوط لوله ورودی خود را برای عملکرد می توانید در اینجا بیاموزید.