GANs (Generative Adversarial Networks)

Les Generative Adversarial Networks (GANs) sont un type de modèle génératif introduit par Ian Goodfellow et ses collaborateurs en 2014. Ce modèle révolutionnaire a permis des avancées spectaculaires dans la génération de données réalistes, notamment dans les domaines de l’image, du texte, et du son. Les GANs reposent sur un processus compétitif où deux réseaux de neurones s’affrontent pour produire des résultats de plus en plus réalistes. Ce mécanisme unique permet de générer des échantillons de données qui imitent les distributions observées dans un jeu de données d’entraînement.

1. Principe de Fonctionnement des GANs

Les GANs sont composés de deux réseaux de neurones distincts :

Les deux réseaux sont entraînés simultanément dans un processus de jeu à somme nulle, où :

Cet entraînement compétitif fait en sorte que, progressivement, les deux réseaux deviennent de plus en plus performants.

2. Objectif de l’Entraînement

L’objectif ultime de l’entraînement d’un GAN est de parvenir à un équilibre où le générateur crée des échantillons de qualité presque indiscernables des données réelles, et où le discriminateur ne peut plus distinguer efficacement entre échantillons réels et générés.

Mathematiquement, cela correspond à la minimisation de la fonction de perte des deux réseaux, ce qui revient à résoudre un problème de jeu à deux joueurs où :

3. Applications des GANs

Les GANs sont largement utilisés pour générer des données réalistes dans de nombreuses applications créatives et industrielles. Parmi les applications populaires, on trouve :

4. Défis et Limites des GANs

Bien que puissants, les GANs présentent plusieurs défis et limitations qui doivent être pris en compte lors de leur utilisation :

5. Améliorations et Variantes des GANs

Afin de surmonter certains de ces défis, plusieurs améliorations et variantes des GANs ont été proposées :

6. Conclusion

Les GANs ont révolutionné le domaine des modèles génératifs et ont trouvé des applications dans des domaines aussi divers que la création artistique, la recherche médicale, l’amélioration de la qualité des données, et bien plus encore. Toutefois, leur entraînement reste complexe et instable, et il existe encore de nombreux défis à surmonter pour garantir des résultats de haute qualité dans des contextes pratiques. Malgré cela, les avancées dans ce domaine laissent entrevoir un avenir prometteur, avec des applications toujours plus sophistiquées et variées des GANs dans le monde réel.

Fonctions :

  • Generative Adversarial Networks (exemple)

    Un Generative Adversarial Network (GAN) est une classe de modèles d'apprentissage automatique composée de deux réseaux neuronaux qui s'opposent mutuellement dans un cadre de jeu. Le premier réseau, appelé générateur, crée des échantillons de données qui sont similaires à un jeu de données d'origine. Le second réseau, appelé discriminateur, tente de distinguer entre les vrais échantillons (issus des données réelles) et les faux (créés par le générateur). L'objectif est que le générateur apprenne à créer des échantillons réalistes et que le discriminateur devienne suffisamment performant pour différencier les vrais des faux.

    Importation :

    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense, LeakyReLU
    from tensorflow.keras.optimizers import Adam
    import numpy as np
    import matplotlib.pyplot as plt

    Attributs :

    Paramètre Type Valeur par défaut Description
    input_dim int 100 Dimension de l'entrée aléatoire pour le générateur.
    output_dim int 28 * 28 Dimension de la sortie (par exemple, une image 28x28 dans le cas de MNIST).
    optimizer str 'adam' L'optimiseur utilisé pour entraîner les réseaux (Adam dans cet exemple).
    loss str 'binary_crossentropy' La fonction de perte utilisée pour entraîner les réseaux (cross-entropie binaire dans cet exemple).

    Exemple de code :

    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense, LeakyReLU
    from tensorflow.keras.optimizers import Adam
    import numpy as np
    import matplotlib.pyplot as plt
    
    # Définir la dimension d'entrée et la dimension de sortie
    z_dim = 100  # Dimension d'entrée aléatoire pour le générateur
    img_shape = (28, 28, 1)  # Dimensions d'une image 28x28 en niveau de gris (MNIST)
    
    # 1. Générateur (G)
    def build_generator(z_dim):
        model = Sequential()
        model.add(Dense(128, input_dim=z_dim))
        model.add(LeakyReLU(0.2))  # Activation
        model.add(Dense(256))
        model.add(LeakyReLU(0.2))  # Activation
        model.add(Dense(512))
        model.add(LeakyReLU(0.2))  # Activation
        model.add(Dense(1024))
        model.add(LeakyReLU(0.2))  # Activation
        model.add(Dense(np.prod(img_shape), activation='tanh'))  # Sortie finale
        model.add(Reshape(img_shape))  # Reshaping la sortie en image 28x28x1
        return model
    
    # 2. Discriminateur (D)
    def build_discriminator(img_shape):
        model = Sequential()
        model.add(Dense(1024, input_shape=img_shape))
        model.add(LeakyReLU(0.2))  # Activation
        model.add(Dense(512))
        model.add(LeakyReLU(0.2))  # Activation
        model.add(Dense(256))
        model.add(LeakyReLU(0.2))  # Activation
        model.add(Dense(1, activation='sigmoid'))  # Sortie binaire
        return model
    
    # 3. GAN (G + D)
    def build_gan(generator, discriminator):
        model = Sequential()
        model.add(generator)
        model.add(discriminator)
        return model
    
    # Compiling le discriminateur
    discriminator = build_discriminator(img_shape)
    discriminator.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5), metrics=['accuracy'])
    
    # Compiling le générateur
    generator = build_generator(z_dim)
    
    # Le GAN combine le générateur et le discriminateur
    discriminator.trainable = False
    gan = build_gan(generator, discriminator)
    gan.compile(loss='binary_crossentropy', optimizer=Adam(0.0002, 0.5))
    
    # 4. Entraînement du GAN
    def train_gan(epochs, batch_size=128, sample_interval=50):
        # Charger les données (MNIST)
        X_train = (np.random.rand(60000, 28, 28, 1) * 2) - 1  # Données simulées ici, à remplacer par MNIST
    
        # Labels pour les images réelles et générées
        real_labels = np.ones((batch_size, 1))
        fake_labels = np.zeros((batch_size, 1))
    
        for epoch in range(epochs):
            # Sélectionner un lot d'images réelles
            idx = np.random.randint(0, X_train.shape[0], batch_size)
            real_imgs = X_train[idx]
    
            # Générer un lot d'images fausses
            noise = np.random.normal(0, 1, (batch_size, z_dim))
            fake_imgs = generator.predict(noise)
    
            # Entraîner le discriminateur
            d_loss_real = discriminator.train_on_batch(real_imgs, real_labels)
            d_loss_fake = discriminator.train_on_batch(fake_imgs, fake_labels)
            d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)
    
            # Entraîner le générateur via le GAN
            g_loss = gan.train_on_batch(noise, real_labels)
    
            # Affichage des progrès
            if epoch % sample_interval == 0:
                print(f"{epoch}/{epochs} [D loss: {d_loss[0]} | D accuracy: {100 * d_loss[1]}] [G loss: {g_loss}]")
                save_sample_images(epoch)
    
    def save_sample_images(epoch, batch_size=128):
        noise = np.random.normal(0, 1, (25, z_dim))
        gen_imgs = generator.predict(noise)
    
        # Sauvegarder les images générées
        fig, axs = plt.subplots(5, 5)
        cnt = 0
        for i in range(5):
            for j in range(5):
                axs[i, j].imshow(gen_imgs[cnt, :, :, 0], cmap='gray')
                axs[i, j].axis('off')
                cnt += 1
        plt.savefig(f"gan_generated_image_epoch_{epoch}.png")
        plt.close()
    
    # Entraîner le GAN
    train_gan(epochs=10000, batch_size=64, sample_interval=1000)
    Résultat du code

    Explication du code :

    • Le Générateur (G) :
      Ce réseau prend un vecteur aléatoire de dimension z_dim (par exemple, 100) comme entrée. Il passe par plusieurs couches de Dense et LeakyReLU avant de produire une sortie transformée par tanh pour générer une image. Cette image est ensuite redimensionnée pour correspondre aux dimensions des images réelles, ici 28x28x1 pour des images en niveaux de gris.

    • Le Discriminateur (D) :
      Ce réseau prend une image en entrée (réelle ou générée) et passe par des couches Dense et LeakyReLU, avant de produire une sortie binaire via la fonction d'activation sigmoid, qui prédit si l'image est réelle (proche de 1) ou générée (proche de 0).

    • Le GAN :
      Le GAN est composé du générateur et du discriminateur. Le générateur est formé pour tromper le discriminateur, tandis que le discriminateur est formé pour distinguer les vrais et faux échantillons.

    • Entraînement :
      L'entraînement se fait par itération. Le modèle Discriminateur est d'abord formé en utilisant des échantillons réels et générés, puis le modèle GAN est formé pour entraîner le générateur à créer des images plus réalistes en inversant les rôles du discriminateur.

    • Visualisation :
      À chaque intervalle spécifié, les images générées par le générateur sont sauvegardées pour montrer l'amélioration du modèle au fil du temps.