مساعدة في حماية الحاجز المرجاني العظيم مع TensorFlow على Kaggle تاريخ التحدي

شبكة الخصومة التلافيفية التوليفية العميقة

عرض على TensorFlow.org تشغيل في Google Colab عرض المصدر على جيثب تحميل دفتر

يوضح هذا البرنامج التعليمي كيفية توليد الصور من الأرقام المكتوبة بخط اليد باستخدام ديب التلافيف المولدة الخصومة شبكة (DCGAN). يتم كتابة التعليمات البرمجية باستخدام API Keras متسلسل مع tf.GradientTape حلقة التدريب.

ما هي شبكات GAN؟

توليدي الخصومة شبكات (GANS) هي واحدة من أكثر الأفكار المثيرة للاهتمام في علم الحاسوب اليوم. يتم تدريب نموذجين في وقت واحد من خلال عملية عدائية. مولد ( "الفنان") يتعلم لإنشاء الصور التي تبدو حقيقية، في حين أن الممي ( "الناقد الفني") يتعلم ان اقول الصور الحقيقية بصرف النظر عن مزيفة.

رسم تخطيطي لمولد ومميز

خلال التدريب، ومولد يصبح تدريجيا أكثر قدرة على خلق الصور التي تبدو حقيقية، في حين يصبح الممي أفضل في إخبار بينهما. الروافد عملية التوازن عندما الممي لم تعد قادرة على تمييز الصور الحقيقية من المزيفة.

رسم تخطيطي ثان لمولد ومميز

يوضح هذا الكمبيوتر الدفتري هذه العملية على مجموعة بيانات 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)

قم بإنشاء النماذج

كلاهما يعرف المولد والممي باستخدام API Keras متسلسل .

المولد

يستخدم مولد tf.keras.layers.Conv2DTranspose (upsampling) طبقات لإنتاج صورة من البذور (الضجيج العشوائي). تبدأ مع Dense طبقة تأخذ هذه البذور كمدخل، ثم upsample عدة مرات حتى تصل إلى حجم الصورة المطلوبة من 28x28x1. لاحظ tf.keras.layers.LeakyReLU تفعيل لكل طبقة، باستثناء طبقة الإنتاج الذي يستخدم تان.

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>

بي إن جي

التمييز

المُميِّز هو مُصنِّف صور قائم على 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)

الخسارة المميزة

تحدد هذه الطريقة مدى قدرة أداة التمييز على التمييز بين الصور الحقيقية والمزيفة. يقارن تنبؤات أداة التمييز على الصور الحقيقية بمصفوفة من 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)

بي إن جي

استعادة أحدث نقطة تفتيش.

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)

بي إن جي

استخدام 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 . لمعرفة المزيد عن GANS رؤية يستأصل 2016 البرنامج التعليمي: شبكات الخصومة المولدة .