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 :
-
Le générateur : Ce réseau a pour objectif de produire des échantillons (par exemple, des images, du texte ou du son) qui ressemblent aux données réelles du jeu d’entraînement. Il prend un vecteur de bruit (généralement une variable aléatoire) en entrée et génère des données synthétiques en sortie.
-
Le discriminateur : Ce réseau évalue la qualité des échantillons générés par le générateur. Il reçoit à la fois des données réelles provenant du jeu de données d’entraînement et des données générées par le générateur, et sa tâche consiste à déterminer si les échantillons sont réels ou synthétiques. L’objectif du discriminateur est de maximiser sa capacité à différencier les données réelles des données générées.
Les deux réseaux sont entraînés simultanément dans un processus de jeu à somme nulle, où :
-
Le générateur cherche à tromper le discriminateur en produisant des échantillons de plus en plus réalistes.
-
Le discriminateur cherche à s’améliorer pour mieux distinguer les vrais échantillons des faux.
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ù :
-
Le générateur veut minimiser la probabilité que le discriminateur détecte qu’un échantillon est faux.
-
Le discriminateur veut maximiser cette probabilité.
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 :
-
Génération d’images : Les GANs ont été utilisés pour générer des images réalistes, telles que des portraits, des paysages, ou des créations artistiques originales. Par exemple, des systèmes comme DeepArt ou Artbreeder utilisent des GANs pour créer de nouvelles œuvres d’art.
-
Amélioration de la qualité d’image : Les GANs peuvent être utilisés pour améliorer la résolution d’images de basse qualité, une technique appelée super-résolution.
-
Création de vidéos et de simulations : Les GANs sont capables de générer des vidéos réalistes ou de simuler des environnements complexes pour des applications de jeux vidéo ou de films.
-
Génération de musique : Des GANs peuvent être entraînés pour générer de la musique à partir de données d’exemples musicaux, ouvrant ainsi de nouvelles possibilités dans la composition automatique.
-
Génération de texte : Bien que plus complexes, les GANs ont été explorés pour générer des séquences de texte, bien qu’il existe des modèles plus spécialisés comme les LSTM et les Transformers pour cette tâche.
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 :
-
Mode Collapse : Un des principaux problèmes rencontrés lors de l’entraînement des GANs est le mode collapse, où le générateur produit une gamme limitée d’échantillons au lieu de générer une grande diversité d’échantillons. Ce phénomène se produit lorsque le générateur trouve une « solution » qui trompe facilement le discriminateur, mais qui ne reflète pas correctement la diversité du jeu de données réel.
-
Stabilité de l’entraînement : L’entraînement des GANs peut être instable et difficile. Il est fréquent que le modèle ne converge pas de manière optimale, en partie à cause de l’interaction complexe entre le générateur et le discriminateur.
-
Équilibre délicat : Trouver un bon équilibre entre les performances du générateur et du discriminateur est un défi. Si l’un des réseaux devient trop puissant par rapport à l’autre, l’entraînement peut échouer.
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 :
-
Wasserstein GANs (WGANs) : Cette version utilise une métrique de distance plus stable entre les distributions de données, appelée distance de Wasserstein, pour améliorer la stabilité de l’entraînement.
-
Conditional GANs (cGANs) : Dans cette version, l’entrée du générateur et du discriminateur inclut des conditions supplémentaires (par exemple, des labels), permettant de conditionner la génération sur des caractéristiques spécifiques (par exemple, générer une image d’un chat de couleur spécifique).
-
Progressive GANs : Cette approche consiste à entraîner les GANs à une résolution basse et à augmenter progressivement la résolution pendant l’entraînement, permettant une génération d’images plus réalistes.
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)
Explication du code :
-
Le Générateur (G) :
Ce réseau prend un vecteur aléatoire de dimensionz_dim
(par exemple, 100) comme entrée. Il passe par plusieurs couches de Dense et LeakyReLU avant de produire une sortie transformée partanh
pour générer une image. Cette image est ensuite redimensionnée pour correspondre aux dimensions des images réelles, ici28x28x1
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.
-