Bir sorunuz mu var? TensorFlow Forum Ziyaret Forumunda toplulukla bağlantı kurun

Derin Evrişimli Üretken Tartışmalı Ağ

TensorFlow.org'da görüntüleyin Kaynağı GitHub'da görüntüleyin Defteri indirin

Bu eğitim, bir Derin Evrişimli Üretken Karşıt Ağ (DCGAN) kullanılarak el yazısı rakamların nasıl oluşturulacağını gösterir. Kod,tf.GradientTape eğitim döngüsü iletf.GradientTape Sıralı API kullanılarak yazılır.

GAN'lar nedir?

Generative Adversarial Networks (GANs) günümüz bilgisayar bilimindeki en ilginç fikirlerden biridir. İki model, rakip bir süreçle aynı anda eğitilir. Discriminator ( "sanat eleştirmeni") öğrenir sahte dışında gerçek görüntülerini anlatmak için ise bir jeneratör ( "sanatçı"), gerçek bakmak görüntüler oluşturmak için öğrenir.

Bir jeneratör ve ayırıcı diyagramı

Ayırt edici birbirinden anlatarak daha iyi olur ise eğitim sırasında, jeneratör giderek, gerçek bakmak görüntüler oluştururken daha iyi olur. Ayrımcı artık gerçek görüntüleri sahtekarlıklardan ayırt edemediğinde süreç dengeye ulaşır.

Bir jeneratör ve ayırıcının ikinci diyagramı

Bu defter, bu işlemi MNIST veri kümesinde gösterir. Aşağıdaki animasyon, jeneratör tarafından 50 dönem için eğitildiği için üretilen bir dizi görüntüyü göstermektedir. Görüntüler rastgele gürültü olarak başlar ve zamanla giderek artan bir şekilde elle yazılmış rakamlara benzer.

örnek çıktı

GAN'lar hakkında daha fazla bilgi edinmek için MIT'nin Derin Öğrenmeye Giriş kursuna bakın.

Kurulum

import tensorflow as tf
tf.__version__
'2.5.0'
# 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

Veri kümesini yükleyin ve hazırlayın

MNIST veri kümesini, jeneratörü ve ayırıcıyı eğitmek için kullanacaksınız. Jeneratör, MNIST verilerine benzeyen el yazısı rakamları üretecektir.

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

Modelleri oluşturun

Hem oluşturucu hem de ayırıcı, Keras Sıralı API kullanılarak tanımlanır.

Jeneratör

Oluşturucu, bir tohumdan (rastgele gürültü) bir görüntü oluşturmak için tf.keras.layers.Conv2DTranspose ( tf.keras.layers.Conv2DTranspose örnekleme) katmanlarını kullanır. Bu çekirdeği girdi olarak alan Dense katmanla başlayın, ardından 28x28x1'lik istediğiniz görüntü boyutuna ulaşana kadar birkaç kez yukarı örnekleyin. tf.keras.layers.LeakyReLU kullanan çıktı katmanı dışında her katman için tf.keras.layers.LeakyReLU etkinleştirmesine dikkat edin.

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

Bir görüntü oluşturmak için (henüz eğitimsiz) oluşturucuyu kullanın.

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 0x7fd5dec2ba90>

png

Ayrımcı

Ayırıcı, CNN tabanlı bir görüntü sınıflandırıcıdır.

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

Oluşturulan görüntüleri gerçek veya sahte olarak sınıflandırmak için (henüz eğitimsiz) ayırıcıyı kullanın. Model, gerçek görüntüler için pozitif değerler ve sahte görüntüler için negatif değerler verecek şekilde eğitilecektir.

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

Kaybı ve optimize edicileri tanımlayın

Her iki model için kayıp fonksiyonlarını ve optimize edicileri tanımlayın.

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

Ayrımcı kaybı

Bu yöntem, ayırt edicinin gerçek görüntüleri sahtekarlıklardan ne kadar iyi ayırt edebildiğini ölçer. Ayrımcının gerçek görüntüler üzerindeki tahminlerini bir dizi 1'le ve ayırt edicinin sahte (oluşturulan) görüntüler üzerindeki tahminlerini bir dizi 0'la karşılaştırır.

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

Jeneratör kaybı

Jeneratörün kaybı, ayırıcıyı ne kadar iyi kandırabildiğini ölçüyor. Sezgisel olarak, jeneratör iyi performans gösteriyorsa, ayrımcı sahte görüntüleri gerçek (veya 1) olarak sınıflandıracaktır. Burada, üretilen görüntüler üzerindeki ayırt edici kararları 1s'lik bir diziyle karşılaştırın.

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

Ayırıcı ve jeneratör optimize ediciler, iki ağı ayrı ayrı eğiteceğiniz için farklıdır.

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

Kontrol noktalarını kaydedin

Bu defter aynı zamanda modellerin nasıl kaydedileceğini ve geri yükleneceğini de gösterir; bu, uzun süren bir eğitim görevinin kesintiye uğraması durumunda yardımcı olabilir.

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)

Eğitim döngüsünü tanımlayın

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

Eğitim döngüsü, jeneratörün girdi olarak rastgele bir tohum almasıyla başlar. Bu tohum bir görüntü oluşturmak için kullanılır. Ayırıcı daha sonra gerçek görüntüleri (eğitim setinden alınan) ve sahte görüntüleri (jeneratör tarafından üretilen) sınıflandırmak için kullanılır. Kayıp, bu modellerin her biri için hesaplanır ve gradyanlar, jeneratör ve ayırıcıyı güncellemek için kullanılır.

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

Görüntüleri oluşturun ve kaydedin

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

Modeli eğitin

Jeneratörü ve ayırıcıyı aynı anda eğitmek için yukarıda tanımlanan train() yöntemini çağırın. GAN'ları eğitmenin zor olabileceğini unutmayın. Jeneratör ve ayırt edicinin birbirlerini baskılamaması (örneğin, benzer bir hızda eğitim almaları) önemlidir.

Eğitimin başında, oluşturulan görüntüler rastgele gürültü gibi görünüyor. Eğitim ilerledikçe, üretilen rakamlar giderek daha gerçekçi görünecektir. Yaklaşık 50 dönem sonra MNIST rakamlarına benzerler. Bu, Colab'deki varsayılan ayarlarla yaklaşık bir dakika / epoch alabilir.

train(train_dataset, EPOCHS)

png

En son kontrol noktasını geri yükleyin.

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

GIF oluştur

# 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

Eğitim sırasında kaydedilen görüntüleri kullanarak animasyonlu bir gif oluşturmak için imageio kullanın.

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

Sonraki adımlar

Bu öğretici, bir GAN yazmak ve eğitmek için gereken tam kodu göstermiştir. Bir sonraki adım olarak, Kaggle'da bulunan Büyük Ölçekli Celeb Faces Attributes (CelebA) veri kümesi gibi farklı bir veri kümesini denemek isteyebilirsiniz . GAN'lar hakkında daha fazla bilgi edinmek için NIPS 2016 Eğitimi: Generative Adversarial Networks'e bakın .