[PYTHON] GAN et VAE

table des matières

  1. Qu'est-ce qu'un encodeur automatique?
  2. Variante Auto Encoder (VAE)
  3. GAN

Qu'est-ce qu'un encodeur automatique?

Le chiffre de ce que je faisais est facile à comprendre. En bref, le codeur compresse les informations en réduisant la dimension des données d'image, et le décodeur reconstruit l'image en utilisant les informations compressées. Calculez et optimisez la distance MAE entre les pixels de l'image d'entrée et l'image de sortie. Apprendre sans enseignant. image.png

Maintenant, comment générer une image à l'aide de cet encodeur automatique? Tout d'abord, entraînez l'encodeur automatique à l'aide d'images. Optimiser pour que les paramètres des deux réseaux, le codeur et le décodeur, soient appropriés. Ensuite, vous pouvez avoir une idée approximative de la façon dont l'image d'entrée est exprimée dans l'espace latent. Lorsque vous l'utilisez comme modèle de génération, la partie codeur n'est pas utilisée, seuls l'espace latent et le décodeur sont utilisés.

Codeur automatique de variante

Alors que les encodeurs automatiques ordinaires essaient d'apprendre l'espace latent sous forme de tableau, les encodeurs de variables tentent de trouver les paramètres appropriés qui définissent la distribution de l'espace latent. Ensuite, l'image est reconstruite en échantillonnant la valeur de cette distribution latente pour obtenir une valeur spécifique et en la saisissant dans le décodeur.

スクリーンショット 2020-06-12 2.29.18.png La gauche est un encodeur automatique normal et la droite est un encodeur variable.

Pour plus de détails, cet article est très facile à comprendre.

GAN

Veuillez vous référer à d'autres articles pour les mouvements détaillés du GAN. Ici, les propriétés caractéristiques du GAN sont décrites. Dans l'architecture GAN, le générateur et le discriminateur sont formés par la fonction de perte du discriminateur. Le propre entraînement du discriminateur tente de minimiser la perte du discriminateur pour toutes les données d'apprentissage. Le générateur, quant à lui, essaie de maximiser la perte du classificateur pour les faux échantillons qu'il produit. En d'autres termes, la formation des réseaux de neurones ordinaires est un problème d'optimisation, tandis que la formation du GAN est un jeu dans lequel les générateurs et les classificateurs sont en concurrence plutôt que l'optimisation. Il se stabilise lorsque l'équilibre Nash est atteint.

L'algorithme d'entraînement GAN peut être résumé comme suit.

Chaque étape itérative de la formation:
1.Formation des discriminateurs
 a.Sélectionnez au hasard des échantillons à partir de données réelles pour créer un mini-lot X
 b.Faire un mini-lot z d'un vecteur de nombre aléatoire et faire un mini-lot G composé de faux échantillons(Z)=X`faire
 c. D(x)Et D(x`)Calculer la perte discriminante et mettre à jour les paramètres du classificateur en propageant l'erreur totale

2.Formation générateur
 a.Faire un mini-lot z d'un vecteur de nombre aléatoire et faire un mini-lot G composé de faux échantillons(z)=X`faire
 b.D(x`)L'erreur de discrimination est maximisée en calculant la perte de discrimination et en la rétropropagant pour mettre à jour les paramètres du générateur.

Notez que les paramètres du générateur ne sont pas mis à jour lors de la formation du classificateur à l'étape 1! Notez que les paramètres du classificateur ne sont pas mis à jour lors de la formation du générateur à l'étape 2!

En utilisant les connaissances de base du GAN jusqu'à présent, implémentez GAN de la manière la plus simple possible. (Une mise en œuvre plus pratique sera donnée dans un article suivant)

Implémentation simplifiée du GAN

Cette fois, nous allons implémenter le code pour générer une image à partir de données MNIST avec l'API séquentielle de Keras.

1. déclaration d'importation

%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np

from keras.datasets import mnist
from keras.layers import Dense, Flatten, Reshape
from keras.layers.advanced_activations import LeakyReLU
from keras.models import Sequential
from keras.optimizers import Adam

2. Réglage de la dimension d'entrée

#Paramètre de dimension d'entrée
img_rows = 28
img_cols = 28
channels = 1
img_shape = (img_rows, img_cols, channels)

#Dimension du bruit d'entrée au générateur
z_dim = 100

3. Génération de générateurs

#Générateur
def build_generator(img_shape, z_dim):
    model = Sequential()
    model.add(Dense(128, input_dim=z_dim))
    model.add(LeakyReLU(alpha=0.01))
    model.add(Dense(28*28*1, activation='tanh'))
    model.add(Reshape(img_shape))
    return model

4. Générer un classificateur

#Identifiant
def build_discriminator(image_shape):
    model = Sequential()
    model.add(Flatten(input_shape=img_shape))
    model.add(Dense(128))
    model.add(LeakyReLU(alpha=0.01))
    model.add(Dense(1, activation='sigmoid'))
    return model

5. Compiler

#compiler!

def build_gan(generator, discriminator):
    model = Sequential()
    model.add(generator)
    model.add(discriminator)
    return model

#Construire et compiler un classificateur
discriminator = build_discriminator(img_shape)
discriminator.compile(loss='binary_crossentropy',
                      optimizer=Adam(),
                      metrics=["accuracy"])

#Construire un générateur
generator = build_generator(img_shape, z_dim)
#Les paramètres d'identification sont fixés pendant la construction du générateur
discriminator.trainable = False
#Construire et compiler le modèle GAN
gan = build_gan(generator, discriminator)
gan.compile(loss="binary_crossentropy",optimizer=Adam())

6. Paramètres du train

#Entraînement!
losses = []
accuracies = []
iteration_checkpoints = []

def train(iterations, batch_size, sample_interval):
  (X_train, Y_train), (X_test, Y_test) = mnist.load_data() #X_train.shape=(60000, 28, 28)
  X_train = X_train /127.5 - 1.0
  X_train  = np.expand_dims(X_train, axis=3)

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

  for iteration in range(iterations):

    #Créez un lot choisi au hasard à partir d'une image réelle
    idx = np.random.randint(0, X_train.shape[0],batch_size)
    imgs = X_train[idx]
    #Créez un lot de fausses images
    z = np.random.normal(0, 1, (batch_size, 100))
    gen_imgs = generator.predict(z)

    #Formation des discriminateurs
    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)

    #Créez un lot de fausses images
    z = np.random.normal(0, 1, (batch_size, 100))
    ge_images = generator.predict(z)
    #Formation générateur
    g_loss = gan.train_on_batch(z, real)

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

      #Itération Enregistrer la valeur de perte et la valeur correspondante
      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. Sortie d'image

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

    #Échantillonnage aléatoire du bruit
    z = np.random.normal(0, 1, (image_grid_rows * image_grid_columns, z_dim))
    gen_imgs = generator.predict(z)

    #Échelle de valeur des pixels
    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):
            # Output a grid of images
            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

1000 [D loss: 0.129656, acc.: 96.09%] [G loss: 3.387729]
2000 [D loss: 0.079047, acc.: 97.66%] [G loss: 3.964481]
3000 [D loss: 0.071152, acc.: 97.27%] [G loss: 5.072118]
4000 [D loss: 0.217956, acc.: 91.02%] [G loss: 3.993687]
5000 [D loss: 0.380112, acc.: 86.72%] [G loss: 3.941338]
6000 [D loss: 0.292950, acc.: 89.45%] [G loss: 4.491636]
7000 [D loss: 0.345073, acc.: 85.55%] [G loss: 4.056399]
8000 [D loss: 0.396545, acc.: 86.33%] [G loss: 3.101150]
9000 [D loss: 0.744731, acc.: 70.70%] [G loss: 2.761991]
10000 [D loss: 0.444913, acc.: 80.86%] [G loss: 3.474383]
11000 [D loss: 0.362310, acc.: 82.81%] [G loss: 3.101751]
12000 [D loss: 0.383188, acc.: 84.38%] [G loss: 3.111648]
13000 [D loss: 0.283140, acc.: 89.06%] [G loss: 3.082010]
14000 [D loss: 0.411019, acc.: 81.64%] [G loss: 2.747284]
15000 [D loss: 0.386751, acc.: 82.03%] [G loss: 2.795580]
16000 [D loss: 0.475734, acc.: 80.86%] [G loss: 2.436490]
17000 [D loss: 0.285364, acc.: 89.45%] [G loss: 2.764011]
18000 [D loss: 0.202013, acc.: 91.80%] [G loss: 4.058733]
19000 [D loss: 0.285773, acc.: 86.72%] [G loss: 3.038511]
20000 [D loss: 0.354960, acc.: 81.64%] [G loss: 2.719907]

↓1000iteration スクリーンショット 2020-06-12 20.27.24.png ↓2000iteration スクリーンショット 2020-06-12 20.27.39.png ↓10000iteration スクリーンショット 2020-06-12 20.28.31.png ↓20000iteration スクリーンショット 2020-06-12 20.29.26.png

Au début de l'apprentissage, c'était juste une image de type bruit, mais à la fin, il semble que même un simple générateur à deux couches puisse générer des caractères manuscrits relativement réalistes. Cependant, des points blancs apparaissent sur l'arrière-plan de l'image manuscrite générée par un simple GAN, et on remarque immédiatement qu'elle n'est pas manuscrite. Afin d'améliorer cette faiblesse, j'aimerais implémenter DCGAN en utilisant la convolution la prochaine fois!

Recommended Posts

GAN et VAE
GAN et VAE
Comprendre et mettre en œuvre Style GAN
À propos de _ et __