[PYTHON] DCGAN

DCGAN (Deep Convolutional GAN)

Qu'est-ce que DCGAN?

Article précédent Pour le générateur et le classificateur GAN simples, au lieu d'utiliser un simple feed forward à deux couches, un neuronal convolutif Le GAN utilisant un réseau s'appelle DCGAN.

Normalisation des lots

Cette fois, DCGAN utilise la normalisation par lots. Pour une explication détaillée, [l'article] de cette personne (https://qiita.com/t-tkd3a/items/14950dbf55f7a3095600) est très facile à comprendre.

Présenter brièvement uniquement les avantages de l'introduction de la normalisation des lots

  1. Il est possible de progresser rapidement dans l'apprentissage
  2. Moins dépendant des valeurs initiales
  3. Le surapprentissage peut être supprimé

Etc. Dans cette implémentation, la fonction keras.layers.BatchNormalization fait un bon travail de calcul et de mise à jour du mini-lot dans les coulisses. Implémentons réellement DCGAN! Le flux général est presque le même que celui de l'article précédent.

Il est temps de mettre en œuvre! !! !!

1. Diverses importations

#Tout d'abord, importez

%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np

from keras.datasets import mnist
from keras.layers import Activation, BatchNormalization, Dense, Dropout, Flatten, Reshape
from keras.layers.advanced_activations import LeakyReLU
from keras.layers.convolutional import Conv2D, Conv2DTranspose
from keras.models import Sequential
from keras.optimizers import Adam

2. Définition de la dimension d'entrée du modèle

#Définition de la dimension d'entrée du modèle

img_rows = 28
img_cols = 28
channels = 1

img_shape = (img_rows, img_cols, channels)

#La dimension du vecteur de bruit utilisé comme entrée du générateur
z_dim = 100

3. Implémentation du générateur

Puisque le générateur génère une image à partir du vecteur de bruit z, nous utiliserons la convolution de translocation. En d'autres termes, dans la figure ci-dessous, l'image la plus à gauche est générée à partir du vecteur z le plus à droite.

スクリーンショット 2020-06-13 15.16.22.png

Les étapes spécifiques sont résumées ci-dessous.

  1. Convertissez en un tenseur 7x7x256 en créant un vecteur de bruit et en le passant à travers la couche entièrement connectée
  2. Convertissez 7x7x256 en 14x14x128 par couche de convolution de translocation
  3. Effectuez la normalisation des lots et appliquez Leaky ReLU
  4. Convertissez 14x14x128 en 14x14x64 avec la couche de convolution de translocation. La hauteur et la largeur ne changent pas à cette étape
  5. Effectuez la normalisation des lots et appliquez Leaky ReLU
  6. Convertissez 14x14x64 en taille d'image de sortie 28x28x1 avec couche de convolution de translocation
  7. Appliquer la fonction tanh

Pour les paramètres de Conv2D Transpose, je me suis référé à cet article.

#Générateur

def build_generator(z_dim):
  model = Sequential()

  model.add(Dense(256*7*7, input_dim = z_dim))
  model.add(Reshape((7, 7, 256)))

  model.add(Conv2DTranspose(128, kernel_size=3, strides=2,padding='same'))
  model.add(BatchNormalization())
  model.add(LeakyReLU(alpha=0.01))

  model.add(Conv2DTranspose(1, kernel_size=3, strides=2, padding="same"))
  model.add(Activation('tanh'))

  return model

4. Mise en œuvre du classificateur

Le classificateur reprend la structure de réseau familière de CNN. Pour expliquer brièvement ce que vous faites, en entrant des données d'image et en effectuant une convolution, la probabilité que l'image soit authentique est finalement calculée. Veuillez vérifier le code ci-dessous pour plus de détails.

Identifiant

def build_discriminator(img_shape):

  model = Sequential()

  model.add(Conv2D(32, kernel_size=3, strides=2, input_shape=img_shape, padding='same'))
  model.add(LeakyReLU(alpha=0.01))

  model.add(Conv2D(64, kernel_size=3, strides=2, padding="same"))
  model.add(BatchNormalization())
  model.add(LeakyReLU(alpha=0.01))

  model.add(Conv2D(128, kernel_size=3, strides=2, padding="same"))
  model.add(BatchNormalization())
  model.add(BatchNormalization())
  model.add(LeakyReLU(alpha=0.01))

  model.add(Flatten())
  model.add(Dense(1, activation="sigmoid"))

  return model

5. Compilation de DCGAN

#Compilation DCGAN
def build_gan(generator, discriminator):

  model = Sequential()

  model.add(generator)
  model.add(discriminator)

  return model

discriminator = build_discriminator(img_shape)
discriminator.compile(loss="binary_crossentropy", optimizer=Adam(), metrics=["accuracy"])

generator = build_generator(z_dim)
discriminator.trainable = False

gan = build_gan(generator, discriminator)
gan.compile(loss="binary_crossentropy", optimizer=Adam())

6. Paramètres d'apprentissage

#Training

losses = []
accuracies = []
iteration_checkpoints = []

def train(iterations, batch_size, sample_interval):
  (X_train, _),(_, _) = mnist.load_data()

  X_train = X_train / 127.5 -1.0
  X_train = np.expand_dims(X_train, 3)

  real = np.ones((batch_size, 1))
  fake = np.zeros((batch_size, 1))

  for iteration in range(iterations):

    idx = np.random.randint(0, X_train.shape[0], batch_size)
    imgs = X_train[idx]

    z = np.random.normal(0, 1, (batch_size, 100))
    gen_imgs = generator.predict(z)

    d_loss_real = discriminator.train_on_batch(imgs, real)
    d_loss_fake = discriminator.train_on_batch(gen_imgs, fake)
    d_loss,  accuracy = 0.5 * np.add(d_loss_real, d_loss_fake)

    z = np.random.normal(0, 1, (batch_size, 100))
    gen_imgs = generator.predict(z)

    g_loss = gan.train_on_batch(z, real)
    if iteration == 0:
      sample_images(generator)

    if ((iteration + 1) % sample_interval == 0):

      losses.append((d_loss, g_loss))
      accuracies.append(100 * accuracy)
      iteration_checkpoints.append(iteration+1)

      print("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" %
                  (iteration + 1, d_loss, 100.0 * accuracy, g_loss))
      sample_images(generator)

7. Affichage de l'image

def sample_images(generator, image_grid_rows=4, image_grid_columns=4):

  z = np.random.normal(0, 1, (image_grid_rows * image_grid_columns, z_dim))
  gen_imgs = generator.predict(z)
  gen_imgs = 0.5 * gen_imgs + 0.5

  fig, axs = plt.subplots(image_grid_rows,
                           image_grid_columns,
                           figsize=(4,4),
                           sharey=True,
                           sharex=True
                           )
  cnt = 0
  for i in range(image_grid_rows):
    for j in range(image_grid_columns):
      axs[i, j].imshow(gen_imgs[cnt, :, :, 0], cmap='gray')
      axs[i, j].axis('off')
      cnt += 1

8. Apprenons!

iterations = 20000
batch_size = 128
sample_interval = 1000
train(iterations, batch_size, sample_interval)

résultat

↓ Bruit initial スクリーンショット 2020-06-13 19.26.47.png ↓1000iterations スクリーンショット 2020-06-13 19.26.57.png ↓10000iterations スクリーンショット 2020-06-13 19.27.29.png ↓20000iterations スクリーンショット 2020-06-13 19.27.43.png

Que diriez-vous, j'ai pu générer une image à un niveau qui ne se distingue pas du vrai texte manuscrit tiré de la mnist de l'ensemble de données. De plus, dans le GAN simple de précédent, le bruit en unités de pixels était inclus dans l'image, mais cette fois en utilisant DCGAN, il se situe entre les pixels. Les relations peuvent être intégrées et une belle image sans bruit est générée.

Recommended Posts

DCGAN
Ecrire DCGAN avec Keras
GAN: DCGAN Part2-Training Modèle DCGAN
DCGAN avec TF Learn