DCGAN (Deep Convolutional GAN)
Article précédent Pour le générateur et le classificateur GAN simples, au lieu d'utiliser un simple feed forward à deux couches, un neuronal convolutif Le GAN utilisant un réseau s'appelle DCGAN.
Cette fois, DCGAN utilise la normalisation par lots. Pour une explication détaillée, [l'article] de cette personne (https://qiita.com/t-tkd3a/items/14950dbf55f7a3095600) est très facile à comprendre.
Présenter brièvement uniquement les avantages de l'introduction de la normalisation des lots
Etc. Dans cette implémentation, la fonction keras.layers.BatchNormalization fait un bon travail de calcul et de mise à jour du mini-lot dans les coulisses. Implémentons réellement DCGAN! Le flux général est presque le même que celui de l'article précédent.
#Tout d'abord, importez
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from keras.datasets import mnist
from keras.layers import Activation, BatchNormalization, Dense, Dropout, Flatten, Reshape
from keras.layers.advanced_activations import LeakyReLU
from keras.layers.convolutional import Conv2D, Conv2DTranspose
from keras.models import Sequential
from keras.optimizers import Adam
#Définition de la dimension d'entrée du modèle
img_rows = 28
img_cols = 28
channels = 1
img_shape = (img_rows, img_cols, channels)
#La dimension du vecteur de bruit utilisé comme entrée du générateur
z_dim = 100
Puisque le générateur génère une image à partir du vecteur de bruit z, nous utiliserons la convolution de translocation. En d'autres termes, dans la figure ci-dessous, l'image la plus à gauche est générée à partir du vecteur z le plus à droite.
Les étapes spécifiques sont résumées ci-dessous.
Pour les paramètres de Conv2D Transpose, je me suis référé à cet article.
#Générateur
def build_generator(z_dim):
model = Sequential()
model.add(Dense(256*7*7, input_dim = z_dim))
model.add(Reshape((7, 7, 256)))
model.add(Conv2DTranspose(128, kernel_size=3, strides=2,padding='same'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.01))
model.add(Conv2DTranspose(1, kernel_size=3, strides=2, padding="same"))
model.add(Activation('tanh'))
return model
Le classificateur reprend la structure de réseau familière de CNN. Pour expliquer brièvement ce que vous faites, en entrant des données d'image et en effectuant une convolution, la probabilité que l'image soit authentique est finalement calculée. Veuillez vérifier le code ci-dessous pour plus de détails.
def build_discriminator(img_shape):
model = Sequential()
model.add(Conv2D(32, kernel_size=3, strides=2, input_shape=img_shape, padding='same'))
model.add(LeakyReLU(alpha=0.01))
model.add(Conv2D(64, kernel_size=3, strides=2, padding="same"))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.01))
model.add(Conv2D(128, kernel_size=3, strides=2, padding="same"))
model.add(BatchNormalization())
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.01))
model.add(Flatten())
model.add(Dense(1, activation="sigmoid"))
return model
#Compilation DCGAN
def build_gan(generator, discriminator):
model = Sequential()
model.add(generator)
model.add(discriminator)
return model
discriminator = build_discriminator(img_shape)
discriminator.compile(loss="binary_crossentropy", optimizer=Adam(), metrics=["accuracy"])
generator = build_generator(z_dim)
discriminator.trainable = False
gan = build_gan(generator, discriminator)
gan.compile(loss="binary_crossentropy", optimizer=Adam())
#Training
losses = []
accuracies = []
iteration_checkpoints = []
def train(iterations, batch_size, sample_interval):
(X_train, _),(_, _) = mnist.load_data()
X_train = X_train / 127.5 -1.0
X_train = np.expand_dims(X_train, 3)
real = np.ones((batch_size, 1))
fake = np.zeros((batch_size, 1))
for iteration in range(iterations):
idx = np.random.randint(0, X_train.shape[0], batch_size)
imgs = X_train[idx]
z = np.random.normal(0, 1, (batch_size, 100))
gen_imgs = generator.predict(z)
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)
z = np.random.normal(0, 1, (batch_size, 100))
gen_imgs = generator.predict(z)
g_loss = gan.train_on_batch(z, real)
if iteration == 0:
sample_images(generator)
if ((iteration + 1) % sample_interval == 0):
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)
def sample_images(generator, image_grid_rows=4, image_grid_columns=4):
z = np.random.normal(0, 1, (image_grid_rows * image_grid_columns, z_dim))
gen_imgs = generator.predict(z)
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):
axs[i, j].imshow(gen_imgs[cnt, :, :, 0], cmap='gray')
axs[i, j].axis('off')
cnt += 1
iterations = 20000
batch_size = 128
sample_interval = 1000
train(iterations, batch_size, sample_interval)
↓ Bruit initial ↓1000iterations ↓10000iterations ↓20000iterations
Que diriez-vous, j'ai pu générer une image à un niveau qui ne se distingue pas du vrai texte manuscrit tiré de la mnist de l'ensemble de données. De plus, dans le GAN simple de précédent, le bruit en unités de pixels était inclus dans l'image, mais cette fois en utilisant DCGAN, il se situe entre les pixels. Les relations peuvent être intégrées et une belle image sans bruit est générée.