کمک به حفاظت از دیواره بزرگ مرجانی با TensorFlow در Kaggle اضافه کردن چالش

شبکه متخاصم مولد Deep Convolutional

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

این آموزش نشان می دهد که چگونه برای تولید تصاویر از ارقام دست نویس با استفاده از یک عمیق کانولوشن زایشی خصمانه شبکه (DCGAN). کد با استفاده از نوشته شده است API Keras متوالی با tf.GradientTape حلقه آموزش.

GAN چیست؟

مولد خصمانه شبکه (گانز) یکی از مهمترین ایده های جالب در علوم کامپیوتر هستند. دو مدل به طور همزمان توسط یک فرآیند متخاصم آموزش داده می شوند. ژنراتور ( "هنرمند") یاد می گیرد به ایجاد تصاویری که واقعی نگاه کنید، در حالی که یک ممیز ( "منتقد هنری") یاد می گیرد به تصاویر واقعی جدا از تقلبی باشید.

نمودار یک مولد و تفکیک کننده

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

نمودار دوم مولد و ممیز

این نوت بوک این فرآیند را در مجموعه داده MNIST نشان می دهد. انیمیشن زیر نشان می دهد یک سری از تصاویر تولید شده توسط ژنراتور به عنوان آن را برای 50 دوره آموزش دید. تصاویر به صورت نویز تصادفی شروع می شوند و با گذشت زمان به طور فزاینده ای به ارقام دست نوشته شده شبیه می شوند.

خروجی نمونه

برای کسب اطلاعات بیشتر در مورد گانز، MIT ببینید معرفی به یادگیری عمیق شود.

برپایی

import tensorflow as tf
tf.__version__
'2.5.0'
# To generate GIFs
pip install imageio
pip install git+https://github.com/tensorflow/docs
import glob
import imageio
import matplotlib.pyplot as plt
import numpy as np
import os
import PIL
from tensorflow.keras import layers
import time

from IPython import display

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

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

(train_images, train_labels), (_, _) = tf.keras.datasets.mnist.load_data()
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
train_images = (train_images - 127.5) / 127.5  # Normalize the images to [-1, 1]
BUFFER_SIZE = 60000
BATCH_SIZE = 256
# Batch and shuffle the data
train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)

مدل ها را ایجاد کنید

هر دو ژنراتور و تمیز دهنده با استفاده از تعریف API Keras متوالی .

ژنراتور

ژنراتور با استفاده از tf.keras.layers.Conv2DTranspose (upsampling) لایه برای تولید یک تصویر از یک دانه (نویز تصادفی). شروع با یک Dense لایه است که طول می کشد این دانه به عنوان ورودی، پس از آن upsample چند بار تا زمانی که شما رسیدن به اندازه تصویر مورد نظر را از 28x28x1. توجه داشته باشید که tf.keras.layers.LeakyReLU فعال برای هر لایه، به جز لایه خروجی که با استفاده از tanh.

def make_generator_model():
    model = tf.keras.Sequential()
    model.add(layers.Dense(7*7*256, use_bias=False, input_shape=(100,)))
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())

    model.add(layers.Reshape((7, 7, 256)))
    assert model.output_shape == (None, 7, 7, 256)  # Note: None is the batch size

    model.add(layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False))
    assert model.output_shape == (None, 7, 7, 128)
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())

    model.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False))
    assert model.output_shape == (None, 14, 14, 64)
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())

    model.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh'))
    assert model.output_shape == (None, 28, 28, 1)

    return model

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

generator = make_generator_model()

noise = tf.random.normal([1, 100])
generated_image = generator(noise, training=False)

plt.imshow(generated_image[0, :, :, 0], cmap='gray')
<matplotlib.image.AxesImage at 0x7f7322b54fd0>

png

تبعیض کننده

تمایز کننده یک طبقه بندی کننده تصویر مبتنی بر CNN است.

def make_discriminator_model():
    model = tf.keras.Sequential()
    model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same',
                                     input_shape=[28, 28, 1]))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.3))

    model.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.3))

    model.add(layers.Flatten())
    model.add(layers.Dense(1))

    return model

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

discriminator = make_discriminator_model()
decision = discriminator(generated_image)
print (decision)
tf.Tensor([[-0.00085865]], shape=(1, 1), dtype=float32)

ضرر و بهینه ساز را تعریف کنید

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

# This method returns a helper function to compute cross entropy loss
cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)

ضرر تبعیض

این روش کمیت می‌کند که تمایزکننده چقدر می‌تواند تصاویر واقعی را از تقلبی تشخیص دهد. پیش‌بینی‌های تشخیص‌دهنده روی تصاویر واقعی را با آرایه‌ای از 1s و پیش‌بینی‌های تشخیص‌دهنده روی تصاویر جعلی (تولید شده) را با آرایه‌ای از 0 مقایسه می‌کند.

def discriminator_loss(real_output, fake_output):
    real_loss = cross_entropy(tf.ones_like(real_output), real_output)
    fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)
    total_loss = real_loss + fake_loss
    return total_loss

از دست دادن ژنراتور

از دست دادن ژنراتور نشان می دهد که چقدر توانسته است متمایز کننده را فریب دهد. بطور شهودی، اگر مولد به خوبی عمل کند، تشخیص دهنده تصاویر جعلی را به عنوان واقعی (یا 1) طبقه بندی می کند. در اینجا، تصمیمات متمایز کننده ها را در تصاویر تولید شده با آرایه ای از 1 مقایسه کنید.

def generator_loss(fake_output):
    return cross_entropy(tf.ones_like(fake_output), fake_output)

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

generator_optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)

ایست های بازرسی را ذخیره کنید

این نوت‌بوک همچنین نحوه ذخیره و بازیابی مدل‌ها را نشان می‌دهد، که می‌تواند در صورت قطع شدن یک کار آموزشی طولانی مفید باشد.

checkpoint_dir = './training_checkpoints'
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
checkpoint = tf.train.Checkpoint(generator_optimizer=generator_optimizer,
                                 discriminator_optimizer=discriminator_optimizer,
                                 generator=generator,
                                 discriminator=discriminator)

حلقه آموزش را تعریف کنید

EPOCHS = 50
noise_dim = 100
num_examples_to_generate = 16

# You will reuse this seed overtime (so it's easier)
# to visualize progress in the animated GIF)
seed = tf.random.normal([num_examples_to_generate, noise_dim])

حلقه آموزش با دریافت یک دانه تصادفی به عنوان ورودی ژنراتور آغاز می شود. از آن دانه برای تولید تصویر استفاده می شود. سپس از تمایزگر برای طبقه بندی تصاویر واقعی (برگرفته از مجموعه آموزشی) و تصاویر جعلی (تولید شده توسط ژنراتور) استفاده می شود. تلفات برای هر یک از این مدل ها محاسبه می شود و از گرادیان ها برای به روز رسانی مولد و تفکیک کننده استفاده می شود.

# Notice the use of `tf.function`
# This annotation causes the function to be "compiled".
@tf.function
def train_step(images):
    noise = tf.random.normal([BATCH_SIZE, noise_dim])

    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
      generated_images = generator(noise, training=True)

      real_output = discriminator(images, training=True)
      fake_output = discriminator(generated_images, training=True)

      gen_loss = generator_loss(fake_output)
      disc_loss = discriminator_loss(real_output, fake_output)

    gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
    gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)

    generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
    discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))
def train(dataset, epochs):
  for epoch in range(epochs):
    start = time.time()

    for image_batch in dataset:
      train_step(image_batch)

    # Produce images for the GIF as you go
    display.clear_output(wait=True)
    generate_and_save_images(generator,
                             epoch + 1,
                             seed)

    # Save the model every 15 epochs
    if (epoch + 1) % 15 == 0:
      checkpoint.save(file_prefix = checkpoint_prefix)

    print ('Time for epoch {} is {} sec'.format(epoch + 1, time.time()-start))

  # Generate after the final epoch
  display.clear_output(wait=True)
  generate_and_save_images(generator,
                           epochs,
                           seed)

تولید و ذخیره تصاویر

def generate_and_save_images(model, epoch, test_input):
  # Notice `training` is set to False.
  # This is so all layers run in inference mode (batchnorm).
  predictions = model(test_input, training=False)

  fig = plt.figure(figsize=(4, 4))

  for i in range(predictions.shape[0]):
      plt.subplot(4, 4, i+1)
      plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap='gray')
      plt.axis('off')

  plt.savefig('image_at_epoch_{:04d}.png'.format(epoch))
  plt.show()

مدل را آموزش دهید

تماس train() روش تعریف بالا برای آموزش ژنراتور و ممیز به طور همزمان. توجه داشته باشید، آموزش GAN ها می تواند مشکل باشد. مهم است که مولد و تمایز بر یکدیگر غلبه نکنند (به عنوان مثال، آنها با سرعت مشابهی تمرین می کنند).

در ابتدای آموزش، تصاویر تولید شده مانند نویز تصادفی به نظر می رسند. با پیشرفت آموزش، ارقام تولید شده به طور فزاینده ای واقعی به نظر می رسند. پس از حدود 50 دوره، آنها شبیه ارقام MNIST هستند. با تنظیمات پیش‌فرض در Colab ممکن است حدود یک دقیقه / دوره طول بکشد.

train(train_dataset, EPOCHS)

png

آخرین ایست بازرسی را بازیابی کنید.

checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))
<tensorflow.python.training.tracking.util.CheckpointLoadStatus at 0x7f72983d2bd0>

یک GIF ایجاد کنید

# Display a single image using the epoch number
def display_image(epoch_no):
  return PIL.Image.open('image_at_epoch_{:04d}.png'.format(epoch_no))
display_image(EPOCHS)

png

استفاده از imageio برای ایجاد یک انیمیشن های GIF با استفاده از تصاویر ذخیره شده در طول آموزش.

anim_file = 'dcgan.gif'

with imageio.get_writer(anim_file, mode='I') as writer:
  filenames = glob.glob('image*.png')
  filenames = sorted(filenames)
  for filename in filenames:
    image = imageio.imread(filename)
    writer.append_data(image)
  image = imageio.imread(filename)
  writer.append_data(image)
import tensorflow_docs.vis.embed as embed
embed.embed_file(anim_file)

gif

مراحل بعدی

این آموزش کد کامل لازم برای نوشتن و آموزش GAN را نشان داده است. به عنوان گام بعدی، شما ممکن است مانند به آزمایش با یک مجموعه داده های مختلف، به عنوان مثال بیان در مقیاس بزرگ چهره صفات (CelebA) مجموعه داده های موجود در Kaggle . برای کسب اطلاعات بیشتر در مورد گانز دیدن NIPS 2016 آموزش: مولد خصمانه شبکه .