ホーム » DCGAN

DCGAN」カテゴリーアーカイブ

TensorFlow 2.0 : 上級 Tutorials : 生成 :- 深層畳み込み敵対的生成ネットワーク

TensorFlow 2.0 : 上級 Tutorials : 生成 :- 深層畳み込み敵対的生成ネットワーク (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 11/21/2019

* 本ページは、TensorFlow org サイトの TF 2.0 – Advanced Tutorials – Generative の以下のページを翻訳した上で
適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

生成 :- 深層畳み込み敵対的生成ネットワーク

このチュートリアルは DCGAN (Deep Convolutional Generative Adversarial Network, 深層畳み込み敵対的生成ネットワーク) を使用して手書き数字の画像をどのように生成するかを実演します。コードは tf.GradientTape 訓練ループで Keras Sequential API を使用して書かれています。

 

GAN とは何でしょう?

敵対的生成ネットワーク (GAN, Generative Adversarial Networks) は現在コンピュータ・サイエンスで最も興味深いアイデアの一つです。2 つのモデルが敵対するプロセスにより同時に訓練されます。generator (「芸術家 = the artist」) がリアルに見える画像を作成することを学習し、その一方で discriminator (「芸術評論家 = the art critic」) がフェイクからリアル画像を識別することを学習します。

訓練の間、generator はリアルに見える画像を作成することに次第に上達し、その一方で discriminator はそれらを識別することに上達します。discriminator がもはやフェイクからリアル画像を識別できないとき、プロセスは均衡に達します。

このノートブックは MNIST データセット上でこのプロセスを実演します。次のアニメーションは (generator が) 50 エポックの間訓練されたとき generator により生成された画像のシリーズを示します。画像はランダム・ノイズとして始まり、そして時間とともに手書き数字にだんだん似ていきます。

GAN について更に学習するためには、MIT の Intro to Deep Learning コースを勧めます。

 

TensorFlow と他のライブラリをインポートする

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
tf.__version__
'2.0.0'
# To generate GIFs
!pip install -q imageio
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

 

データセットをロードして準備する

generator と discriminator を訓練するために MNIST データセットを使用します。generator は 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)

 

モデルを作成する

generator と discriminator の両者は Keras Sequential API を使用して定義されます。

 

Generator

generator は seed (ランダムノイズ) から画像を生成するために tf.keras.layers.Conv2DTranspose (upsampling) 層を使用します。この seed を入力として取る Dense 層から始めて、それから 28x28x1 の望まれるサイズに到達するまで幾度かアップサンプリングします。tanh を使用する出力層を除いて、各層のために 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 を使用します。

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

 

Discriminator

discriminator は 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 を使用します。モデルはリアル画像のためにはポジティブ値を、そしてフェイク画像のためにはネガティブ値を出力するように訓練されます。

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

 

損失と optimizer を定義する

両者のモデルのために損失関数と optimizer を定義します。

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

 

Discriminator 損失

このメソッドは discriminator がフェイク (画像) からリアル画像をどの程度上手く識別できるかを数値化します。それはリアル画像上の discriminator の予測を 1 の配列と、そしてフェイク (生成された) 画像上の discriminator の予測を 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

 

Generator 損失

generator 損失はそれがどの程度上手く discriminator を欺くことができたかを数値化します。直感的には、generator が上手く遂行していれば、discriminator はフェイク画像をリアル (or 1) として分類するでしょう。ここでは、生成された画像上の discriminator の決定を 1 の配列と比較します。

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

discriminator と generator の optimizer は異なります、何故ならば 2 つのネットワークを別々に訓練するからです。

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

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

訓練ループは generator が入力としてランダムシードを受け取ることから開始されます。そのシードは画像を生成するために使用されます。それから discriminator は (訓練セットからドローされた) リアル画像と (generator により生成された) フェイク画像を分類するために使用されます。損失はこれらのモデルの各々のために計算されて、勾配は generator と discriminator を更新するために使用されます。

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

 

モデルを訓練する

generator と discriminator を同時に訓練するために上で定義された train() メソッドを呼び出します。注意してください、GAN の訓練はトリッキーであり得ます。generator と discriminator は互いに圧倒 (= overpower) しないこと (e.g., それらは同様なレートで訓練します) は重要です。

訓練の最初では、生成された画像はランダムノイズのように見えます。訓練が進むにつれて、生成される数字は段々とリアルに見えます。およそ 50 エポック後、それらは MNIST 数字に似ます。Colab のデフォルト設定で約 1 分 / エポックかかるかもしれません。

train(train_dataset, EPOCHS)

 
最新のチェックポイントをリストアします。

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

 

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)

 
訓練の間にセーブされた画像を使用して animated gif を作成するために imageio を使用します。

anim_file = 'dcgan.gif'

with imageio.get_writer(anim_file, mode='I') as writer:
  filenames = glob.glob('image*.png')
  filenames = sorted(filenames)
  last = -1
  for i,filename in enumerate(filenames):
    frame = 2*(i**0.5)
    if round(frame) > round(last):
      last = frame
    else:
      continue
    image = imageio.imread(filename)
    writer.append_data(image)
  image = imageio.imread(filename)
  writer.append_data(image)

import IPython
if IPython.version_info > (6,2,0,''):
  display.Image(filename=anim_file)

Colab で作業しているのであれば、下のコードでアニメーションをダウンロードできます :

try:
  from google.colab import files
except ImportError:
   pass
else:
  files.download(anim_file)

 

Next steps

このチュートリアルは GAN を書いて訓練するために必要な完全なコードを示しました。次のステップとして、異なるデータセットで実験することを望むかもしれません、例えば、Kaggle で利用可能な Large-scale Celeb Faces Attributes (CelebA) データセットです。GAN についてより多く学習するためには NIPS 2016 Tutorial: Generative Adversarial Networks を勧めます。

 

以上






TensorFlow 2.0 Beta : 上級 Tutorials : 画像生成 :- 深層畳み込み敵対的生成ネットワーク

TensorFlow 2.0 Beta : 上級 Tutorials : 画像生成 :- 深層畳み込み敵対的生成ネットワーク (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 07/08/2019

* 本ページは、TensorFlow の本家サイトの TF 2.0 Beta – Advanced Tutorials – Image generation の以下のページを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

画像生成 :- 深層畳み込み敵対的生成ネットワーク

このチュートリアルは DCGAN (Deep Convolutional Generative Adversarial Network, 深層畳み込み敵対的生成ネットワーク) を使用して手書き数字の画像をどのように生成するかを実演します。コードは tf.GradientTape 訓練ループで Keras Sequential API を使用して書かれています。

 

GAN とは何でしょう?

敵対的生成ネットワーク (GAN, Generative Adversarial Networks) は現在コンピュータ・サイエンスで最も興味深いアイデアの一つです。2 つのモデルが敵対するプロセスにより同時に訓練されます。generator (「芸術家 = the artist」) がリアルに見える画像を作成することを学習し、その一方で discriminator (「芸術評論家 = the art critic」) がフェイクからリアル画像を識別することを学習します。

訓練の間、generator はリアルに見える画像を作成することに次第に上達し、その一方で discriminator はそれらを識別することに上達します。discriminator がもはやリアル画像をフェイクから識別できないとき、プロセスは均衡に達します。

このノートブックは MNIST データセット上でこのプロセスを実演します。次のアニメーションは (generator が) 50 エポックの間訓練されたとき generator により生成された画像のシリーズを示します。画像はランダム・ノイズとして始まり、そして時間とともに手書き数字にだんだん似ていきます。

 

TensorFlow と他のライブラリをインポートする

from __future__ import absolute_import, division, print_function, unicode_literals
!pip install -q tensorflow-gpu==2.0.0-beta1
import tensorflow as tf
tf.__version__
'2.0.0-beta1'
# To generate GIFs
!pip install -q imageio
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

 

データセットをロードして準備する

generator と discriminator を訓練するために MNIST データセットを使用していきます。generator は 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)

 

モデルを作成する

generator と discriminator の両者は Keras Sequential API を使用して定義されます。

 

Generator

generator は seed (ランダムノイズ) から画像を生成するために tf.keras.layers.Conv2DTranspose (upsampling) 層を使用します。この seed を入力として取る Dense 層から始めて、それから 28x28x1 の望まれるサイズに達するまで幾度か upsample します。tanh を使用する出力層を除いて、各層のためには 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 を使用します。

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

 

Discriminator

discriminator は 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 を使用します。モデルはリアル画像のためにはポジティブ値を、そしてフェイク画像のためにはネガティブ値を出力するように訓練されます。

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

 

損失と optimizer を定義する

両者のモデルのために損失関数と optimizer を定義します。

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

 

Discriminator 損失

このメソッドは discriminator がフェイク (画像) からリアル画像をどの程度上手く識別できるかを数値化します。それはリアル画像上の discriminator の予測を 1 の配列と、そしてフェイク (生成された) 画像上の discriminator の予測を 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

 

Generator 損失

generator 損失はそれがどの程度上手く discriminator を欺くことができたかを数値化します。直感的には、generator が上手く遂行していれば、discriminator はフェイク画像をリアル (or 1) として分類するでしょう。ここでは、生成された画像上の discriminator の決定を 1 の配列と比較します。

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

discriminator と generator の optimizer は異なります、何故ならば 2 つのネットワークを別々に訓練するからです。

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

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

訓練ループは generator が入力としてランダムシードを受け取ることから開始されます。そのシードは画像を生成するために使用されます。それから discriminator は (訓練セットからドローされた) リアル画像と (generator により生成された) フェイク画像を分類するために使用されます。損失はこれらのモデルの各々のために計算されて、勾配は generator と discriminator を更新するために使用されます。

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

 

モデルを訓練する

generator と discriminator を同時に訓練するためには上で定義された train() メソッドを呼び出します。注意してください、GAN の訓練はトリッキーかもしれません。generator と discriminator は互いに圧倒 (= overpower) しないこと (e.g., それらは同様なレートで訓練します) は重要です。

訓練の最初では、生成された画像はランダムノイズのように見えます。訓練が進むにつれて、生成される数字は段々とリアルに見えます。およそ 50 エポック後、それらは MNIST 数字に似ます。Colab のデフォルト設定で約 1 分 / エポックかかるかもしれません。

%%time
train(train_dataset, EPOCHS)

CPU times: user 2min 33s, sys: 31.3 s, total: 3min 5s
Wall time: 3min 48s

最新のチェックポイントをリストアします。

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

 

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)

訓練の間にセーブされた画像を使用して animated gif を作成するために imageio を使用します。

anim_file = 'dcgan.gif'

with imageio.get_writer(anim_file, mode='I') as writer:
  filenames = glob.glob('image*.png')
  filenames = sorted(filenames)
  last = -1
  for i,filename in enumerate(filenames):
    frame = 2*(i**0.5)
    if round(frame) > round(last):
      last = frame
    else:
      continue
    image = imageio.imread(filename)
    writer.append_data(image)
  image = imageio.imread(filename)
  writer.append_data(image)

import IPython
if IPython.version_info > (6,2,0,''):
  display.Image(filename=anim_file)

Colab で作業しているのであれば、下のコードでアニメーションをダウンロードできます :

try:
  from google.colab import files
except ImportError:
  pass
else:
  files.download(anim_file)

 

Next steps

このチュートリアルは GAN を書いて訓練するために必要な完全なコードを示しました。次のステップとして、異なるデータセットで実験することを望むかもしれません、例えば、Kaggle で利用可能な Large-scale Celeb Faces Attributes (CelebA) データセットです。GAN についてより多く学習するためには NIPS 2016 Tutorial: Generative Adversarial Networks を勧めます。

 

以上






TensorFlow 2.0 Alpha : 上級 Tutorials : GAN と VAE :- 深層畳み込み敵対的生成ネットワーク

TensorFlow 2.0 Alpha : 上級 Tutorials : GAN と VAE :- 深層畳み込み敵対的生成ネットワーク (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/10/2019

* 本ページは、TensorFlow の本家サイトの TF 2.0 Alpha – Advanced Tutorials – GANs and VAEs の以下のページを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

GAN と VAE :- 深層畳み込み敵対的生成ネットワーク

このチュートリアルは DCGAN (Deep Convolutional Generative Adversarial Network, 深層畳み込み敵対的生成ネットワーク) を使用して手書き数字の画像をどのように生成するかを実演します。コードは tf.GradientTape 訓練ループで Keras Sequential API を使用して書かれています。

 

GAN とは何でしょう?

敵対的生成ネットワーク (GAN, Generative Adversarial Networks) は現在コンピュータ・サイエンスで最も興味深いアイデアの一つです。2 つのモデルが敵対するプロセスにより同時に訓練されます。generator (「芸術家 = the artist」) がリアルに見える画像を作成することを学習し、その一方で discriminator (「芸術評論家 = the art critic」) がフェイクからリアル画像を識別することを学習します。

訓練の間、generator はリアルに見える画像を作成することに次第に上達し、その一方でdiscriminator はそれらを識別することに上達します。discriminator がもはやリアル画像をフェイクから識別できないとき、プロセスは均衡に達します。

このノートブックは MNIST データセット上でこのプロセスを実演します。次のアニメーションは 50 エポックの間訓練された generator により生成された画像のシリーズを示します。画像はランダム・ノイズとして始まり、そして時間とともに手書き数字にだんだん似ていきます。

 

TensorFlow と他のライブラリをインポートする

from __future__ import absolute_import, division, print_function, unicode_literals
!pip install -q tensorflow-gpu==2.0.0-alpha0
Collecting tensorflow-gpu==2.0.0-alpha0
[?25l  Downloading https://files.pythonhosted.org/packages/1a/66/32cffad095253219d53f6b6c2a436637bbe45ac4e7be0244557210dc3918/tensorflow_gpu-2.0.0a0-cp36-cp36m-manylinux1_x86_64.whl (332.1MB)
Successfully installed tensorflow-gpu-2.0.0a0
import tensorflow as tf
tf.__version__
'2.0.0-alpha0'
# To generate GIFs
!pip install -q imageio
Requirement already satisfied: imageio in /usr/local/lib/python3.6/dist-packages (2.4.1)
Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (from imageio) (1.14.6)
Requirement already satisfied: pillow in /usr/local/lib/python3.6/dist-packages (from imageio) (4.1.1)
Requirement already satisfied: olefile in /usr/local/lib/python3.6/dist-packages (from pillow->imageio) (0.46)
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

 

データセットをロードして準備する

generator と discriminator を訓練するために MNIST データセットを使用していきます。generator は 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)

 

モデルを作成する

generator と discriminator の両者は Keras Sequential API を使用して定義されます。

 

Generator

generator は seed (ランダムノイズ) から画像を生成するために tf.keras.layers.Conv2DTranspose (upsampling) 層を使用します。この seed を入力として取る Dense 層から始めて、それから 28x28x1 の望まれるサイズに達するまで幾度か upsample します。tanh を使用する出力層を除いて、各層のためには 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 を使用します。

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

 

Discriminator

discriminator は 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 を使用します。モデルはリアル画像のためにはポジティブ値を、そしてフェイク画像のためにはネガティブ値を出力するように訓練されます。

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

 

損失と optimizer を定義する

両者のモデルのために損失関数と optimizer を定義します。

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

 

Discriminator 損失

このメソッドは discriminator がフェイク画像からリアル画像をどの程度上手く識別できるかを数値化します。それはリアル画像上の discriminator の予測を 1 の配列と、そしてフェイク (生成された) 画像上の discriminator の予測を 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

 

Generator 損失

generator 損失はそれがどの程度上手く discriminator を欺くことができたかを数値化します。直感的には、generator が上手く遂行していれば、discriminator はフェイク画像をリアル (or 1) として分類するでしょう。ここでは、生成された画像上の discriminator の決定を 1 の配列と比較します。

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

discriminator and the generator の optimizer は異なります、何故ならば 2 つのネットワークを別々に訓練するからです。

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

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

訓練ループは generator が入力としてランダムシードを受け取ることから開始されます。そのシードは画像を生成するために使用されます。それから discriminator は (訓練セットからドローされた) リアル画像と (generator により生成された) フェイク画像を分類するために使用されます。損失はこれらのモデルの各々のために計算されて、勾配は generator と discriminator を更新するために使用されます。

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

 

モデルを訓練する

generator と discriminator を同時に訓練するためには上で定義された train() メソッドを呼び出します。注意してください、GAN の訓練はトリッキーです。generator と discriminator は互いに圧倒 (= overpower) しないこと (e.g., それらは同様なレートで訓練します) は重要です。

訓練の最初では、生成された画像はランダムノイズのように見えます。訓練が進むにつれて、生成される数字は段々とリアルに見えます。およそ 50 エポック後、それらは MNIST 数字に似ます。Colab のデフォルト設定で約 1 分 / エポックかかるかもしれません。

%%time
train(train_dataset, EPOCHS)

CPU times: user 3min 10s, sys: 48.1 s, total: 3min 58s
Wall time: 10min 52s

最新のチェックポイントをリストアします。

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

 

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)

訓練の間にセーブされた画像を使用して animated gif を作成するために imageio を使用します。

anim_file = 'dcgan.gif'

with imageio.get_writer(anim_file, mode='I') as writer:
  filenames = glob.glob('image*.png')
  filenames = sorted(filenames)
  last = -1
  for i,filename in enumerate(filenames):
    frame = 2*(i**0.5)
    if round(frame) > round(last):
      last = frame
    else:
      continue
    image = imageio.imread(filename)
    writer.append_data(image)
  image = imageio.imread(filename)
  writer.append_data(image)

import IPython
if IPython.version_info > (6,2,0,''):
  display.Image(filename=anim_file)

Colab で作業しているのであれば、下のコードでアニメーションをダウンロードできます :

try:
  from google.colab import files
except ImportError:
  pass
else:
  files.download(lite_model_path)

 

Next steps

このチュートリアルは GAN を書いて訓練するために必要な完全なコードを示しました。次のステップとして、異なるデータセットで実験することを望むかもしれません、例えば、Kaggle で利用可能な Large-scale Celeb Faces Attributes (CelebA) データセットです。GAN についてより多く学習するためには NIPS 2016 Tutorial: Generative Adversarial Networks を勧めます。

 

以上






TensorFlow : Tutorials : 生成モデル : DCGAN : tf.keras と eager のサンプル

TensorFlow : Tutorials : 生成モデル : DCGAN: tf.keras と eager のサンプル (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 08/29/2018

* TensorFlow 1.10 で更に改訂されています。
* TensorFlow 1.9 でドキュメント構成が変更され、数篇が新規に追加されましたので再翻訳しました。
* 本ページは、TensorFlow の本家サイトの Tutorials – Generative Models の以下のページを翻訳した上で
適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

DCGAN : tf.keras と eager のサンプル

このノートブックは tf.keras と eager execution を使用して手書き数字の画像をどのように生成するかを示します。それを行なうために、DCGAN (Deep Convolutional Generative Adversarial Networks, 深層畳み込み敵対的生成ネットワーク) を使用します。

このモデルは 2018年7月 時点で、Colab 上単一の Tesla K80 上で訓練するためにエポック毎におよそ ~30 秒かかります (グラフ関数を作成するために tf.contrib.eager.defun を使用)。

下は、generator と discriminator モデルを 150 エポック訓練した後に生成された出力です。

# to generate gifs
!pip install imageio

 

TensorFlow をインポートして eager execution を有効にする

from __future__ import absolute_import, division, print_function

# Import TensorFlow >= 1.10 and enable eager execution
import tensorflow as tf
tf.enable_eager_execution()

import os
import time
import numpy as np
import glob
import matplotlib.pyplot as plt
import PIL
import imageio
from IPython import display

 

データセットをロードする

generator と discriminator を訓練するために MNIST データセットを使用していきます。それから generator は手書き数字を生成します。

(train_images, train_labels), (_, _) = tf.keras.datasets.mnist.load_data()
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
# We are normalizing the images to the range of [-1, 1]
train_images = (train_images - 127.5) / 127.5
BUFFER_SIZE = 60000
BATCH_SIZE = 256

 

バッチを作成してデータセットをシャッフルするために tf.data を使用する

train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)

 

generator と discriminator モデルを書く

  • Generator
    • それは、discriminator を欺くために十分に良い、説得力のある画像を生成する 責任を負います。
    • それは Conv2DTranspose (Upsampling) 層で構成されます。完全結合層で開始して、望まれる画像サイズ (mnist 画像サイズ)、(28, 28, 1) に到達するために画像を 2 回アップサンプリングします。
    • tanh 活性を仕様する最後の層を除いて leaky relu 活性を使用します。
  • Discriminator
    • discriminator は real 画像から fake 画像を分類する 責任を負います。
    • 換言すれば、discriminator は (generator から) 生成された画像と real MNIST 画像を与えられます。discriminator のジョブはこれらの画像を (生成された) fake と real (MNIST 画像) に分類することです。
    • 基本的には generator は discriminator を生成された画像が本物であると騙すために十分に良くあるべきです
class Generator(tf.keras.Model):
  def __init__(self):
    super(Generator, self).__init__()
    self.fc1 = tf.keras.layers.Dense(7*7*64, use_bias=False)
    self.batchnorm1 = tf.keras.layers.BatchNormalization()
    
    self.conv1 = tf.keras.layers.Conv2DTranspose(64, (5, 5), strides=(1, 1), padding='same', use_bias=False)
    self.batchnorm2 = tf.keras.layers.BatchNormalization()
    
    self.conv2 = tf.keras.layers.Conv2DTranspose(32, (5, 5), strides=(2, 2), padding='same', use_bias=False)
    self.batchnorm3 = tf.keras.layers.BatchNormalization()
    
    self.conv3 = tf.keras.layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False)

  def call(self, x, training=True):
    x = self.fc1(x)
    x = self.batchnorm1(x, training=training)
    x = tf.nn.relu(x)

    x = tf.reshape(x, shape=(-1, 7, 7, 64))

    x = self.conv1(x)
    x = self.batchnorm2(x, training=training)
    x = tf.nn.relu(x)

    x = self.conv2(x)
    x = self.batchnorm3(x, training=training)
    x = tf.nn.relu(x)

    x = tf.nn.tanh(self.conv3(x))  
    return x
class Discriminator(tf.keras.Model):
  def __init__(self):
    super(Discriminator, self).__init__()
    self.conv1 = tf.keras.layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same')
    self.conv2 = tf.keras.layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same')
    self.dropout = tf.keras.layers.Dropout(0.3)
    self.flatten = tf.keras.layers.Flatten()
    self.fc1 = tf.keras.layers.Dense(1)

  def call(self, x, training=True):
    x = tf.nn.leaky_relu(self.conv1(x))
    x = self.dropout(x, training=training)
    x = tf.nn.leaky_relu(self.conv2(x))
    x = self.dropout(x, training=training)
    x = self.flatten(x)
    x = self.fc1(x)
    return x
generator = Generator()
discriminator = Discriminator()
# Defun gives 10 secs/epoch performance boost
generator.call = tf.contrib.eager.defun(generator.call)
discriminator.call = tf.contrib.eager.defun(discriminator.call)

 

損失関数と optimizer を定義する

  • Discriminator 損失
    • discriminator 損失関数は 2 つの入力を取ります ; real 画像、生成された画像です。
    • real_loss は real 画像と 1 の配列の sigmoid 交差エントロピー損失です (何故ならばこれらは real 画像だからです)。
    • generated_loss は生成された画像とゼロ配列の sigmod 交差エントロピー損失です (何故ならばこれらは fake 画像だからです)。
    • そして total_loss は real_loss と generated_loss の合計です。
  • Generator 損失
    • それは生成された画像と 1 の配列の sigmoid 交差エントロピー損失です。
  • discriminator と generator optimizer は異なります、何故ならばそれらを別々に訓練するからです。
def discriminator_loss(real_output, generated_output):
    # [1,1,...,1] with real output since it is true and we want
    # our generated examples to look like it
    real_loss = tf.losses.sigmoid_cross_entropy(multi_class_labels=tf.ones_like(real_output), logits=real_output)

    # [0,0,...,0] with generated images since they are fake
    generated_loss = tf.losses.sigmoid_cross_entropy(multi_class_labels=tf.zeros_like(generated_output), logits=generated_output)

    total_loss = real_loss + generated_loss

    return total_loss
def generator_loss(generated_output):
    return tf.losses.sigmoid_cross_entropy(tf.ones_like(generated_output), generated_output)
discriminator_optimizer = tf.train.AdamOptimizer(1e-4)
generator_optimizer = tf.train.AdamOptimizer(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)

 

訓練

  • データセットに渡り反復することから始めます。
  • generator は入力としてノイズが与えられます、これは generator モデルを通して渡されたとき手書き数字のような画像を出力します。
  • discriminator は real MNIST 画像 と (generator から) 生成された画像が与えられます。
  • 次に、generator と discriminator 損失を計算します。
  • それから、generator と discriminator 変数 (入力) の両者に関する損失の勾配を計算してそれらを optimizer に適用します。

 

画像を生成する

  • 訓練の後、何某かの画像を生成する時です!
  • generator への入力としてノイズ配列を作成することから始めます。
  • それから generator はノイズを手書き数字に変換します。
  • 最後のステップは予測をプロットします。Voila !
EPOCHS = 150
noise_dim = 100
num_examples_to_generate = 16

# keeping the random vector constant for generation (prediction) so
# it will be easier to see the improvement of the gan.
random_vector_for_generation = tf.random_normal([num_examples_to_generate,
                                                 noise_dim])
def generate_and_save_images(model, epoch, test_input):
  # make sure the training parameter is set to False because we
  # don't want to train the batchnorm layer when doing inference.
  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()
def train(dataset, epochs, noise_dim):  
  for epoch in range(epochs):
    start = time.time()
    
    for images in dataset:
      # generating noise from a uniform distribution
      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)
        generated_output = discriminator(generated_images, training=True)
        
        gen_loss = generator_loss(generated_output)
        disc_loss = discriminator_loss(real_output, generated_output)
        
      gradients_of_generator = gen_tape.gradient(gen_loss, generator.variables)
      gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.variables)
      
      generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.variables))
      discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.variables))

      
    if epoch % 1 == 0:
      display.clear_output(wait=True)
      generate_and_save_images(generator,
                               epoch + 1,
                               random_vector_for_generation)
    
    # saving (checkpoint) the model every 15 epochs
    if (epoch + 1) % 15 == 0:
      checkpoint.save(file_prefix = checkpoint_prefix)
    
    print ('Time taken for epoch {} is {} sec'.format(epoch + 1,
                                                      time.time()-start))
  # generating after the final epoch
  display.clear_output(wait=True)
  generate_and_save_images(generator,
                           epochs,
                           random_vector_for_generation)
train(train_dataset, EPOCHS, noise_dim)

 

最新のチェックポイントをリストアする

# restoring the latest checkpoint in checkpoint_dir
checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))

 

エポック数を使用して画像を表示する

def display_image(epoch_no):
  return PIL.Image.open('image_at_epoch_{:04d}.png'.format(epoch_no))
display_image(EPOCHS)

 

総ての保存された画像の GIF を生成する

with imageio.get_writer('dcgan.gif', mode='I') as writer:
  filenames = glob.glob('image*.png')
  filenames = sorted(filenames)
  last = -1
  for i,filename in enumerate(filenames):
    frame = 2*(i**0.5)
    if round(frame) > round(last):
      last = frame
    else:
      continue
    image = imageio.imread(filename)
    writer.append_data(image)
  image = imageio.imread(filename)
  writer.append_data(image)
    
# this is a hack to display the gif inside the notebook
os.system('cp dcgan.gif dcgan.gif.png')
display.Image(filename="dcgan.gif.png")

Colab からアニメーションをダウンロードするためには下のコードをアンコメントします :

#from google.colab import files
#files.download('dcgan.gif')
 

以上



AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com