Pas encore de compte ?
Un réseau antagoniste génératif (GAN) est un cadre de réseau neuronal profond capable d'apprendre à partir d'un ensemble de données d'entraînement et de générer de nouvelles données avec les mêmes caractéristiques que les données d'entraînement.
Les réseaux antagonistes génératifs sont constitués de deux réseaux de neurones, le générateur et le discriminateur, qui se font concurrence.
Le générateur est formé pour produire de fausses données.
Le discriminateur est formé pour distinguer les fausses données du générateur des exemples réels.
Un réseau antagoniste génératif très simple
Testé sous Anaconda et Python 3.7
import numpy as np import torch import torch.nn as nn import torch.optim as optim from torch.autograd import Variable matplotlib_is_available = True try: from matplotlib import pyplot as plt except ImportError: print("Will skip plotting; matplotlib is not available.") matplotlib_is_available = False # Data params data_mean = 4 data_stddev = 1.25 # ### Uncomment only one of these to define what data is actually sent to the Discriminator #(name, preprocess, d_input_func) = ("Raw data", lambda data: data, lambda x: x) #(name, preprocess, d_input_func) = ("Data and variances", lambda data: decorate_with_diffs(data, 2.0), lambda x: x * 2) #(name, preprocess, d_input_func) = ("Data and diffs", lambda data: decorate_with_diffs(data, 1.0), lambda x: x * 2) (name, preprocess, d_input_func) = ("Only 4 moments", lambda data: get_moments(data), lambda x: 4) print("Using data [%s]" % (name)) # ##### DATA: Target data and generator input data def get_distribution_sampler(mu, sigma): return lambda n: torch.Tensor(np.random.normal(mu, sigma, (1, n))) # Gaussian def get_generator_input_sampler(): return lambda m, n: torch.rand(m, n) # Uniform-dist data into generator, _NOT_ Gaussian # ##### MODELS: Generator model and discriminator model class Generator(nn.Module): def __init__(self, input_size, hidden_size, output_size, f): super(Generator, self).__init__() self.map1 = nn.Linear(input_size, hidden_size) self.map2 = nn.Linear(hidden_size, hidden_size) self.map3 = nn.Linear(hidden_size, output_size) self.f = f def forward(self, x): x = self.map1(x) x = self.f(x) x = self.map2(x) x = self.f(x) x = self.map3(x) return x class Discriminator(nn.Module): def __init__(self, input_size, hidden_size, output_size, f): super(Discriminator, self).__init__() self.map1 = nn.Linear(input_size, hidden_size) self.map2 = nn.Linear(hidden_size, hidden_size) self.map3 = nn.Linear(hidden_size, output_size) self.f = f def forward(self, x): x = self.f(self.map1(x)) x = self.f(self.map2(x)) return self.f(self.map3(x)) def extract(v): return v.data.storage().tolist() def stats(d): return [np.mean(d), np.std(d)] def get_moments(d): # Return the first 4 moments of the data provided mean = torch.mean(d) diffs = d - mean var = torch.mean(torch.pow(diffs, 2.0)) std = torch.pow(var, 0.5) zscores = diffs / std skews = torch.mean(torch.pow(zscores, 3.0)) kurtoses = torch.mean(torch.pow(zscores, 4.0)) - 3.0 # excess kurtosis, should be 0 for Gaussian final = torch.cat((mean.reshape(1,), std.reshape(1,), skews.reshape(1,), kurtoses.reshape(1,))) return final def decorate_with_diffs(data, exponent, remove_raw_data=False): mean = torch.mean(data.data, 1, keepdim=True) mean_broadcast = torch.mul(torch.ones(data.size()), mean.tolist()[0][0]) diffs = torch.pow(data - Variable(mean_broadcast), exponent) if remove_raw_data: return torch.cat([diffs], 1) else: return torch.cat([data, diffs], 1) def train(): # Model parameters g_input_size = 1 # Random noise dimension coming into generator, per output vector g_hidden_size = 5 # Generator complexity g_output_size = 1 # Size of generated output vector d_input_size = 500 # Minibatch size - cardinality of distributions d_hidden_size = 10 # Discriminator complexity d_output_size = 1 # Single dimension for 'real' vs. 'fake' classification minibatch_size = d_input_size d_learning_rate = 1e-3 g_learning_rate = 1e-3 sgd_momentum = 0.9 num_epochs = 5000 print_interval = 100 d_steps = 20 g_steps = 20 dfe, dre, ge = 0, 0, 0 d_real_data, d_fake_data, g_fake_data = None, None, None discriminator_activation_function = torch.sigmoid generator_activation_function = torch.tanh d_sampler = get_distribution_sampler(data_mean, data_stddev) gi_sampler = get_generator_input_sampler() G = Generator(input_size=g_input_size, hidden_size=g_hidden_size, output_size=g_output_size, f=generator_activation_function) D = Discriminator(input_size=d_input_func(d_input_size), hidden_size=d_hidden_size, output_size=d_output_size, f=discriminator_activation_function) criterion = nn.BCELoss() # Binary cross entropy: http://pytorch.org/docs/nn.html#bceloss d_optimizer = optim.SGD(D.parameters(), lr=d_learning_rate, momentum=sgd_momentum) g_optimizer = optim.SGD(G.parameters(), lr=g_learning_rate, momentum=sgd_momentum) for epoch in range(num_epochs): for d_index in range(d_steps): # 1. Train D on real+fake D.zero_grad() # 1A: Train D on real d_real_data = Variable(d_sampler(d_input_size)) d_real_decision = D(preprocess(d_real_data)) d_real_error = criterion(d_real_decision, Variable(torch.ones([1]))) # ones = true d_real_error.backward() # compute/store gradients, but don't change params # 1B: Train D on fake d_gen_input = Variable(gi_sampler(minibatch_size, g_input_size)) d_fake_data = G(d_gen_input).detach() # detach to avoid training G on these labels d_fake_decision = D(preprocess(d_fake_data.t())) d_fake_error = criterion(d_fake_decision, Variable(torch.zeros([1]))) # zeros = fake d_fake_error.backward() d_optimizer.step() # Only optimizes D's parameters; changes based on stored gradients from backward() dre, dfe = extract(d_real_error)[0], extract(d_fake_error)[0] for g_index in range(g_steps): # 2. Train G on D's response (but DO NOT train D on these labels) G.zero_grad() gen_input = Variable(gi_sampler(minibatch_size, g_input_size)) g_fake_data = G(gen_input) dg_fake_decision = D(preprocess(g_fake_data.t())) g_error = criterion(dg_fake_decision, Variable(torch.ones([1]))) # Train G to pretend it's genuine g_error.backward() g_optimizer.step() # Only optimizes G's parameters ge = extract(g_error)[0] if epoch % print_interval == 0: print("Epoch %s: D (%s real_err, %s fake_err) G (%s err); Real Dist (%s), Fake Dist (%s) " % (epoch, dre, dfe, ge, stats(extract(d_real_data)), stats(extract(d_fake_data)))) if matplotlib_is_available: print("Plotting the generated distribution...") values = extract(g_fake_data) print(" Values: %s" % (str(values))) plt.hist(values, bins=50) plt.xlabel('Value') plt.ylabel('Count') plt.title('Histogram of Generated Distribution') plt.grid(True) plt.show() train()
pytorch-generative-adversarial-networks
Copyright (c) Apache.
GAN architecture
generative-adversarial-networks
Copyright (c) 2017 Jon Bruner
Implémentations Keras des réseaux antagonistes génératifs bidirectionnels
Testé sous Anaconda et Python 3.7
from __future__ import print_function, division from keras.datasets import mnist from keras.layers import Input, Dense, Reshape, Flatten, Dropout from keras.layers import BatchNormalization, Activation, ZeroPadding2D from keras.layers.advanced_activations import LeakyReLU from keras.layers.convolutional import UpSampling2D, Conv2D from keras.models import Sequential, Model from keras.optimizers import Adam import matplotlib.pyplot as plt import sys import numpy as np class GAN(): def __init__(self): self.img_rows = 28 self.img_cols = 28 self.channels = 1 self.img_shape = (self.img_rows, self.img_cols, self.channels) self.latent_dim = 100 optimizer = Adam(0.0002, 0.5) # Build and compile the discriminator self.discriminator = self.build_discriminator() self.discriminator.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy']) # Build the generator self.generator = self.build_generator() # The generator takes noise as input and generates imgs z = Input(shape=(self.latent_dim,)) img = self.generator(z) # For the combined model we will only train the generator self.discriminator.trainable = False # The discriminator takes generated images as input and determines validity validity = self.discriminator(img) # The combined model (stacked generator and discriminator) # Trains the generator to fool the discriminator self.combined = Model(z, validity) self.combined.compile(loss='binary_crossentropy', optimizer=optimizer) def build_generator(self): model = Sequential() model.add(Dense(256, input_dim=self.latent_dim)) model.add(LeakyReLU(alpha=0.2)) model.add(BatchNormalization(momentum=0.8)) model.add(Dense(512)) model.add(LeakyReLU(alpha=0.2)) model.add(BatchNormalization(momentum=0.8)) model.add(Dense(1024)) model.add(LeakyReLU(alpha=0.2)) model.add(BatchNormalization(momentum=0.8)) model.add(Dense(np.prod(self.img_shape), activation='tanh')) model.add(Reshape(self.img_shape)) model.summary() noise = Input(shape=(self.latent_dim,)) img = model(noise) return Model(noise, img) def build_discriminator(self): model = Sequential() model.add(Flatten(input_shape=self.img_shape)) model.add(Dense(512)) model.add(LeakyReLU(alpha=0.2)) model.add(Dense(256)) model.add(LeakyReLU(alpha=0.2)) model.add(Dense(1, activation='sigmoid')) model.summary() img = Input(shape=self.img_shape) validity = model(img) return Model(img, validity) def train(self, epochs, batch_size=128, sample_interval=50): # Load the dataset (X_train, _), (_, _) = mnist.load_data() # Rescale -1 to 1 X_train = X_train / 127.5 - 1. X_train = np.expand_dims(X_train, axis=3) # Adversarial ground truths valid = np.ones((batch_size, 1)) fake = np.zeros((batch_size, 1)) for epoch in range(epochs): # --------------------- # Train Discriminator # --------------------- # Select a random batch of images idx = np.random.randint(0, X_train.shape[0], batch_size) imgs = X_train[idx] noise = np.random.normal(0, 1, (batch_size, self.latent_dim)) # Generate a batch of new images gen_imgs = self.generator.predict(noise) # Train the discriminator d_loss_real = self.discriminator.train_on_batch(imgs, valid) d_loss_fake = self.discriminator.train_on_batch(gen_imgs, fake) d_loss = 0.5 * np.add(d_loss_real, d_loss_fake) # --------------------- # Train Generator # --------------------- noise = np.random.normal(0, 1, (batch_size, self.latent_dim)) # Train the generator (to have the discriminator label samples as valid) g_loss = self.combined.train_on_batch(noise, valid) # Plot the progress print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss)) # If at save interval => save generated image samples if epoch % sample_interval == 0: self.sample_images(epoch) def sample_images(self, epoch): r, c = 5, 5 noise = np.random.normal(0, 1, (r * c, self.latent_dim)) gen_imgs = self.generator.predict(noise) # Rescale images 0 - 1 gen_imgs = 0.5 * gen_imgs + 0.5 fig, axs = plt.subplots(r, c) cnt = 0 for i in range(r): for j in range(c): axs[i,j].imshow(gen_imgs[cnt, :,:,0], cmap='gray') axs[i,j].axis('off') cnt += 1 fig.savefig("images/%d.png" % epoch) plt.close() if __name__ == '__main__': gan = GAN() gan.train(epochs=30000, batch_size=32, sample_interval=200)
Keras-GAN
Copyright (c) 2017 Erik Linder-Norén
Bienvenu, je m’appelle Eric Soupet et je suis l'administrateur du site elodees.com. elodees.com est un état de l'art de l'Intelligence Artificielle et se veut collaboratif, vous pouvez dès à présent proposer du contenu tels que des articles, des événements, des tutoriels, ... alors n'hésitez pas !
Crédit des images de la plate-forme : Pixabay - Pixabay License | Pexels - Pexels License