Google I / O 18 تا 20 مه بازگشت دارد! فضا را ذخیره کنید و برنامه خود را بسازید اکنون ثبت نام کنید

شبکه خصمانه تولید همبستگی عمیق

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

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

GAN چیست؟

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

نمودار یک ژنراتور و یک تبعیض

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

نمودار دوم یک مولد و یک تبعیض

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

خروجی نمونه

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

برپایی

import tensorflow as tf
tf.__version__
'2.4.1'
# To generate GIFs
pip install -q imageio
pip install -q 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()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
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)

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

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

ژنراتور

مولد از لایه های tf.keras.layers.Conv2DTranspose (upsampling) برای تولید یک تصویر از یک دانه (نویز تصادفی) استفاده می کند. با یک لایه Dense شروع کنید که این دانه را به عنوان ورودی می گیرد ، سپس چندین بار نمونه برداری کنید تا به اندازه تصویر دلخواه 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 0x7f3740747390>

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.00033125]], 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)

ضرر تبعیض آمیز

این روش میزان کمی را تشخیص می دهد که تفکیک کننده می تواند تصاویر واقعی را از جعلی تشخیص دهد. این پیش بینی های تبعیض آمیز در تصاویر واقعی را با آرایه ای از 1 ها و پیش بینی های تبعیض آمیز در مورد تصاویر جعلی (تولید شده) را با آرایه ای از 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 0x7f371f792c88>

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)

گیف

مراحل بعدی

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