सहायता Kaggle पर TensorFlow साथ ग्रेट बैरियर रीफ की रक्षा चैलेंज में शामिल हों

डीप कनवल्शनल जनरेटिव एडवरसैरियल नेटवर्क

TensorFlow.org पर देखें GitHub पर स्रोत देखें नोटबुक डाउनलोड करें

इस ट्यूटोरियल दर्शाता है कि कैसे एक का उपयोग कर हस्तलिखित अंकों की छवियों उत्पन्न करने के लिए दीप Convolutional उत्पादक विरोधात्मक नेटवर्क (DCGAN)। कोड का उपयोग कर लिखा है Keras अनुक्रमिक एपीआई एक साथ tf.GradientTape प्रशिक्षण पाश।

जीएएन क्या हैं?

उत्पादक विरोधात्मक नेटवर्क (Gans) कंप्यूटर विज्ञान में सबसे दिलचस्प विचार, आज से एक हैं। दो मॉडलों को एक साथ एक प्रतिकूल प्रक्रिया द्वारा प्रशिक्षित किया जाता है। जबकि एक discriminator ( "कला समीक्षक") सीखता नकली से अलग वास्तविक छवियों को बताने के लिए एक जनरेटर ( "कलाकार"), छवियों कि असली लग रहे बनाने के लिए सीखता है।

एक जनरेटर और विवेचक का आरेख

प्रशिक्षण के दौरान, जनरेटर उत्तरोत्तर छवियों कि असली लग रहे बनाने में बेहतर हो जाता है, जबकि discriminator उन्हें अलग बता में बेहतर हो जाता है। प्रक्रिया पहुँच संतुलित रूप जब discriminator अब नकली से असली छवियों भेद कर सकते हैं।

जनरेटर और विवेचक का दूसरा आरेख

यह नोटबुक MNIST डेटासेट पर इस प्रक्रिया को प्रदर्शित करती है। निम्नलिखित एनीमेशन शो छवियों की एक श्रृंखला जनरेटर द्वारा उत्पादित के रूप में यह 50 अवधियों के लिए प्रशिक्षित किया गया था। छवियां यादृच्छिक शोर के रूप में शुरू होती हैं, और समय के साथ हाथ से लिखे अंकों के समान होती जाती हैं।

नमूना आउटपुट

Gans के बारे में अधिक जानने के लिए एमआईटी के देखने के दीप लर्निंग का परिचय पाठ्यक्रम।

सेट अप

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)

मॉडल बनाएं

दोनों जनरेटर और discriminator का उपयोग कर परिभाषित कर रहे हैं 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>

पीएनजी

भेदभाव करने वाला

विभेदक एक सीएनएन-आधारित छवि क्लासिफायरियर है।

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 की एक सरणी से करता है, और विवेचक की भविष्यवाणियों की नकली (उत्पन्न) छवियों पर 0s की एक सरणी से तुलना करता है।

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) के रूप में वर्गीकृत करेगा। यहां, उत्पन्न छवियों पर भेदभाव करने वालों के निर्णयों की तुलना 1s की एक सरणी से करें।

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() विधि ऊपर परिभाषित एक साथ जनरेटर और discriminator प्रशिक्षित करने के लिए। ध्यान दें, GAN को प्रशिक्षित करना मुश्किल हो सकता है। यह महत्वपूर्ण है कि जनरेटर और विवेचक एक-दूसरे पर हावी न हों (उदाहरण के लिए, कि वे समान दर से प्रशिक्षण लेते हैं)।

प्रशिक्षण की शुरुआत में, उत्पन्न छवियां यादृच्छिक शोर की तरह दिखती हैं। जैसे-जैसे प्रशिक्षण आगे बढ़ेगा, उत्पन्न अंक तेजी से वास्तविक दिखाई देंगे। लगभग 50 युगों के बाद, वे MNIST अंकों के समान होते हैं। Colab पर डिफ़ॉल्ट सेटिंग के साथ इसमें लगभग एक मिनट/युग लग सकता है।

train(train_dataset, EPOCHS)

पीएनजी

नवीनतम चेकपॉइंट को पुनर्स्थापित करें।

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

जीआईएफ बनाएं

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

पीएनजी

उपयोग 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 चेहरे गुण (CelebA) डाटासेट Kaggle पर उपलब्ध । अधिक जानने के लिए के बारे में Gans देख nips 2016 ट्यूटोरियल: उत्पादक विरोधात्मक नेटवर्क