[PYTHON] Exemple d'implémentation d'un réseau de génération hostile (GAN) par Keras

Ce que j'ai fait dans cet article

** - Génération d'image Minst par GAN

introduction

Réseau de génération hostile, ou GAN. J'entends souvent dire que c'est vraiment populaire, mais quand vous essayez de l'implémenter vous-même, c'est tout un seuil.

C'est une technologie qui semble importante pour moi, alors je l'ai laissée tranquille rien qu'en la regardant de l'extérieur. Étonnamment, il y a pas mal de gens comme ça.

** Cette fois, je présenterai un exemple d'implémentation d'un tel GAN en utilisant des données mnist. ** ** Données et code ["Apprentissage non supervisé avec python"](url https://www.amazon.co.jp/Python%E3%81%A7%E3%81%AF%E3%81%98%E3%82 % 81% E3% 82% 8B% E6% 95% 99% E5% B8% AB% E3% 81% AA% E3% 81% 97% E5% AD% A6% E7% BF% 92-% E2% 80% 95% E6% A9% 9F% E6% A2% B0% E5% AD% A6% E7% BF% 92% E3% 81% AE% E5% 8F% AF% E8% 83% BD% E6% 80% A7% E3% 82% 92% E5% BA% 83% E3% 81% 92% E3% 82% 8B% E3% 83% A9% E3% 83% 99% E3% 83% AB% E3% 81% AA% E3% 81% 97% E3% 83% 87% E3% 83% BC% E3% 82% BF% E3% 81% AE% E5% 88% A9% E7% 94% A8-Ankur-Patel / dp / 4873119103) J'ai le droit de le faire.

Le livre auquel je faisais référence a été écrit en utilisant l'orientation objet, donc c'était un peu de haut niveau, mais c'était une excellente expérience d'apprentissage.

De même, j'espère que cela sera utile pour les débutants.

Voici les résultats que j'ai obtenus en premier. Parce que cela a un impact sur l'apparence.

** Authentique ** image.png

** Produire ** mnist_14000.png

** J'ai l'impression que les images générées sont incroyablement similaires ... ** Vous pourrez peut-être faire mieux si vous les laissez apprendre plus longtemps.

Qu'est-ce qu'un réseau de génération hostile (GAN)?

Voici un bref aperçu. Veuillez consulter cet article pour plus de détails. GAN: Qu'est-ce qu'un réseau de génération hostile? -Génération d'images par "apprendre sans professeur" https://www.imagazine.co.jp/gan%EF%BC%9A%E6%95%B5%E5%AF%BE%E7%9A%84%E7%94%9F%E6%88%90%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B%E3%80%80%EF%BD%9E%E3%80%8C%E6%95%99%E5%B8%AB/

** Avec GAN, vous pouvez entraîner un ensemble de données pour créer des données identiques et similaires. ** ** Dans l'exemple de l'article de référence, GAN est utilisé pour générer une image d'une chambre qui n'existe pas réellement. C'est difficile à dire, l'apprentissage automatique est effrayant.

Puisque cet article utilise mnist, nous allons générer des caractères manuscrits. Comment générez-vous ce caractère manuscrit?

** Au GAN, il existe deux modèles, l'un qui génère des données et l'autre qui identifie les données. Dans le modèle qui génère des données, nous créerons des données qui ressemblent à des caractères manuscrits. Ensuite, les données créées sont utilisées comme modèle d'identification pour déterminer si elles sont fausses ou authentiques. Ensuite, en fonction du résultat, nous entraînerons le modèle généré, puis créerons une image plus proche de la réalité. ** **

En termes simples, c'est juste ce modèle. La seule question reste, comment former les données et comment former les données? Je pense.

Données d'apprentissage

Dans ce modèle, l'apprentissage des données est effectué comme suit.

** - Générer une image (1 * 28 * 28) à partir du bruit (100 * 1 * 1) avec le modèle de génération

Nous allons effectivement mettre en œuvre ce modèle.

Importer la bibliothèque

C'est juste un livre de référence, mais je l'ai un peu amélioré pour qu'il puisse être utilisé avec google colab.

python



'''Main'''
import numpy as np
import pandas as pd
import os, time, re
import pickle, gzip, datetime

'''Data Viz'''
import matplotlib.pyplot as plt
import seaborn as sns
color = sns.color_palette()
import matplotlib as mpl
from mpl_toolkits.axes_grid1 import Grid

%matplotlib inline

'''Data Prep and Model Evaluation'''
from sklearn import preprocessing as pp
from sklearn.model_selection import train_test_split 
from sklearn.model_selection import StratifiedKFold 
from sklearn.metrics import log_loss, accuracy_score
from sklearn.metrics import precision_recall_curve, average_precision_score
from sklearn.metrics import roc_curve, auc, roc_auc_score, mean_squared_error
from keras.utils import to_categorical

'''Algos'''
import lightgbm as lgb

'''TensorFlow and Keras'''
import tensorflow as tf
import keras
from keras import backend as K
from keras.models import Sequential, Model
from keras.layers import Activation, Dense, Dropout, Flatten, Conv2D, MaxPool2D
from keras.layers import LeakyReLU, Reshape, UpSampling2D, Conv2DTranspose
from keras.layers import BatchNormalization, Input, Lambda
from keras.layers import Embedding, Flatten, dot
from keras import regularizers
from keras.losses import mse, binary_crossentropy
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
from keras.optimizers import Adam, RMSprop

from keras.datasets import mnist

sns.set("talk")

Lecture des données

Il lit des données. Utilisez des données minimes. Il est destiné à être utilisé en collaboration. Puisque nous n'utilisons que x_train, nous ne normalisons que reshpae et les valeurs de 0 à 1 à x_train.

python



#Données divisées en données d'entraînement et données de test
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape((60000, 28, 28, 1))
#Définissez la valeur du pixel sur 0~Normaliser entre 1
x_train= x_train / 255.0

Conception de classe DCGAN

Code DCGAN super important. Il est défini dans une classe qui résume le modèle de génération et le modèle d'identification. Pour décrire brièvement la fonction de chaque fonction generator --Réseau neural qui convertit 100 * 1 * 1 vecteurs en 28 * 28 * 1 images ―― En apprenant ceci, une image comme celle-ci sera générée.

discriminator

discriminator_model --Compiler et modéliser un réseau de neurones pour l'identification

adversarial?model

python


#Classe DCGAN
class DCGAN(object):
  #Initialisation
    def __init__(self, img_rows=28, img_cols=28, channel=1):

        self.img_rows = img_rows
        self.img_cols = img_cols
        self.channel = channel
        self.D = None   # discriminator
        self.G = None   # generator
        self.AM = None  # adversarial model
        self.DM = None  # discriminator model
    
    #Réseau de génération
    #100*1*La matrice de 1 est la même que l'image de l'ensemble de données 1*28*28
    def generator(self, depth=256, dim=7, dropout=0.3, momentum=0.8, \
                  window=5, input_dim=100, output_depth=1):
        if self.G:
            return self.G
        self.G = Sequential()

        #100*1*1 → 256*7*7
        self.G.add(Dense(dim*dim*depth, input_dim=input_dim))
        self.G.add(BatchNormalization(momentum=momentum))
        self.G.add(Activation('relu'))
        self.G.add(Reshape((dim, dim, depth)))
        self.G.add(Dropout(dropout))
        
        #256*7*7 → 128*14*14
        self.G.add(UpSampling2D())
        self.G.add(Conv2DTranspose(int(depth/2), window, padding='same'))
        self.G.add(BatchNormalization(momentum=momentum))
        self.G.add(Activation('relu'))

        #128*14*14 → 64*28*28
        self.G.add(UpSampling2D())
        self.G.add(Conv2DTranspose(int(depth/4), window, padding='same'))
        self.G.add(BatchNormalization(momentum=momentum))
        self.G.add(Activation('relu'))

        #64*28*28→32*28*28
        self.G.add(Conv2DTranspose(int(depth/8), window, padding='same'))
        self.G.add(BatchNormalization(momentum=momentum))
        self.G.add(Activation('relu'))

        #1*28*28
        self.G.add(Conv2DTranspose(output_depth, window, padding='same'))
        #Définissez chaque pixel sur une valeur comprise entre 0 et 1
        self.G.add(Activation('sigmoid')) 
        self.G.summary()
        return self.G


    #Réseau d'identification
    #28*28*Distinguer si l'image de 1 est authentique
    def discriminator(self, depth=64, dropout=0.3, alpha=0.3):
        if self.D:
            return self.D

        self.D = Sequential()
        input_shape = (self.img_rows, self.img_cols, self.channel)

      #28*28*1 → 14*14*64
        self.D.add(Conv2D(depth*1, 5, strides=2, input_shape=input_shape,padding='same'))
        self.D.add(LeakyReLU(alpha=alpha))
        self.D.add(Dropout(dropout))

      #14*14*64 → 7*7*128
        self.D.add(Conv2D(depth*2, 5, strides=2, padding='same'))
        self.D.add(LeakyReLU(alpha=alpha))
        self.D.add(Dropout(dropout))

      #7*7*128 → 4*4*256
        self.D.add(Conv2D(depth*4, 5, strides=2, padding='same'))
        self.D.add(LeakyReLU(alpha=alpha))
        self.D.add(Dropout(dropout))

        #4*4*512 → 4*4*512 ####Cependant, vérifiez si cela correspond###
        self.D.add(Conv2D(depth*8, 5, strides=1, padding='same'))
        self.D.add(LeakyReLU(alpha=alpha))
        self.D.add(Dropout(dropout))

        #Aplatir et classer par sigmoïde
        self.D.add(Flatten())
        self.D.add(Dense(1))
        self.D.add(Activation('sigmoid'))

        self.D.summary()
        return self.D

    #Modèle de discrimination
    def discriminator_model(self):
        if self.DM:
            return self.DM
        optimizer = RMSprop(lr=0.0002, decay=6e-8)
        self.DM = Sequential()
        self.DM.add(self.discriminator())
        self.DM.compile(loss='binary_crossentropy', \
                        optimizer=optimizer, metrics=['accuracy'])
        return self.DM

    #Modèle de génération
    def adversarial_model(self):
        if self.AM:
            return self.AM
        optimizer = RMSprop(lr=0.0001, decay=3e-8)
        self.AM = Sequential()
        self.AM.add(self.generator())
        self.AM.add(self.discriminator())
        self.AM.compile(loss='binary_crossentropy', \
                        optimizer=optimizer, metrics=['accuracy'])
        return self.AM

Conception de classe DCGAN pour mnist

Ensuite, nous utiliserons ces fonctions pour entraîner réellement les données minimes à générer une image. Entraînez l'image avec la fonction de train et enregistrez l'image avec plot_images.

La fonction de train est exécutée dans le flux suivant.

** - Générer des données d'entraînement à partir du bruit

python


#Classe qui applique DCGAN aux données MNIST
class MNIST_DCGAN(object):
    #Initialisation
    def __init__(self, x_train):
        self.img_rows = 28
        self.img_cols = 28
        self.channel = 1

        self.x_train = x_train

        #Identification de DCGAN, définition du modèle de génération hostile
        self.DCGAN = DCGAN()
        self.discriminator =  self.DCGAN.discriminator_model()
        self.adversarial = self.DCGAN.adversarial_model()
        self.generator = self.DCGAN.generator()

    #Fonction de formation
    #train_on_batch apprend pour chaque batch. La sortie est la perte et l'acc
    def train(self, train_steps=2000, batch_size=256, save_interval=0):
        noise_input = None

        if save_interval>0:
            noise_input = np.random.uniform(-1.0, 1.0, size=[16, 100])

        for i in range(train_steps):
            #Données d'entraînement par lots_Extraire aléatoirement uniquement la taille
            images_train = self.x_train[np.random.randint(0,self.x_train.shape[0], size=batch_size), :, :, :] 
            
            # 100*1*Créez un bruit de 1 par taille de lot et faites-en une fausse image
            noise = np.random.uniform(-1.0, 1.0, size=[batch_size, 100])
            
            #Former l'image générée
            images_fake = self.generator.predict(noise)
            x = np.concatenate((images_train, images_fake))
            #Définissez les données d'entraînement sur 1 et les données générées sur 0
            y = np.ones([2*batch_size, 1])
            y[batch_size:, :] = 0
            
            #Former le modèle discriminant
            d_loss = self.discriminator.train_on_batch(x, y)

            y = np.ones([batch_size, 1])
            noise = np.random.uniform(-1.0, 1.0, size=[batch_size, 100])

            #produire&Former le modèle discriminant
            #La formation du modèle de génération se fait uniquement ici
            a_loss = self.adversarial.train_on_batch(noise, y)

            #Perte et précision des données d'entraînement et du modèle généré
            #La perte D est la perte et l'accessibilité de l'image générée et de l'image réelle
            #Une perte est une perte et acc lorsque l'image générée par l'adversaire est 1.
            log_mesg = "%d: [D loss: %f, acc: %f]" % (i, d_loss[0], d_loss[1])
            log_mesg = "%s  [A loss: %f, acc: %f]" % (log_mesg, a_loss[0], a_loss[1])
            print(log_mesg)

            #save_Enregistrer les données à intervalles
            if save_interval>0:
                if (i+1)%save_interval==0:
                    self.plot_images(save2file=True, \
                        samples=noise_input.shape[0],\
                        noise=noise_input, step=(i+1))

    #Tracer les résultats de l'entraînement
    def plot_images(self, save2file=False, fake=True, samples=16, \
                    noise=None, step=0):
        current_path = os.getcwd()
        file = os.path.sep.join(["","data", 'images', 'chapter12', 'synthetic_mnist', ''])
        filename = 'mnist.png'
        if fake:
            if noise is None:
                noise = np.random.uniform(-1.0, 1.0, size=[samples, 100])
            else:
                filename = "mnist_%d.png " % step
            images = self.generator.predict(noise)
        else:
            i = np.random.randint(0, self.x_train.shape[0], samples)
            images = self.x_train[i, :, :, :]

        plt.figure(figsize=(10,10))
        for i in range(images.shape[0]):
            plt.subplot(4, 4, i+1)
            image = images[i, :, :, :]
            image = np.reshape(image, [self.img_rows, self.img_cols])
            plt.imshow(image, cmap='gray')
            plt.axis('off')
        plt.tight_layout()
        if save2file:
            plt.savefig(current_path+file+filename)
            plt.close('all')
        else:
            plt.show()

À la fin

GAN est incroyable. Je me sens même mal à l'aise lorsque quelque chose comme des caractères manuscrits est généré.

Il semble qu'il puisse être utilisé pour la détection d'anomalies, etc. sur le site réel.

Cependant, dans le résumé des ouvrages de référence, il y avait une déclaration ** "Soyez prêt à faire beaucoup d'efforts lors de l'utilisation du GAN" **. Il n'y avait aucune raison détaillée à cela ...

Comme tu as du mal, GAN.

Jusqu'à la fin Merci d'avoir lu.

Recommended Posts

Exemple d'implémentation d'un réseau de génération hostile (GAN) par Keras
Détection d'anomalies par encodeur automatique à l'aide de keras [Exemple d'implémentation pour les débutants]
Exemple d'implémentation du serveur LINE BOT pour un fonctionnement réel
[Linux] Principes de base de la configuration des autorisations par chmod pour les débutants
Enregistrez la sortie du GAN conditionnel pour chaque classe ~ Avec l'implémentation cGAN par PyTorch ~
[Pour les débutants] Les bases de Python expliquées par Java Gold Part 2
Sauvegardez la sortie de GAN une par une ~ Avec l'implémentation de GAN par PyTorch ~
■ Kaggle Practice pour les débutants - Introduction de Python - par Google Colaboratory
[Pour les débutants] Les bases de Python expliquées par Java Gold Part 1
Vue d'ensemble de Docker (pour les débutants)
Implémentation de Scale-Space pour SIFT
Résumé de l'implémentation de base par PyTorch
Implémentation d'un réseau de neurones à deux couches 2
[À voir pour les débutants] Bases de Linux
Exemple de réécriture de code par ast.NodeTransformer
Dérivation de la distribution t multivariée et implémentation de la génération de nombres aléatoires par python
[Exemple d'amélioration de Python] Quel est le site d'apprentissage recommandé pour les débutants en Python?
Implémenter un modèle avec état et comportement (3) - Exemple d'implémentation par décorateur