生成器模型在训练期间不产生图片

Generator model doesn't produce pictures during training

我正在使用 MNIST 训练 GAN,我想在训练期间可视化带有噪声输入的生成器输出。

代码如下:

from numpy import expand_dims
import numpy as np
import time
import tensorflow as tf
from numpy import zeros
from numpy import ones
from numpy import vstack
from numpy.random import randn
from numpy.random import randint
from tensorflow.keras.datasets.mnist import load_data
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import layers, Sequential
import matplotlib.pyplot as plt
from IPython import display
import imageio # for creating gifs
import PIL

(trainX, _), (_, _) = load_data()
# add channels dimension
X = expand_dims(trainX, axis=-1)
# convert from unsigned ints to floats
X = X.astype('float32')
# scale from [0,255] to [0,1]
dataset = X / 255.0

def define_generator(latent_dim):
    model = Sequential()
    # foundation for 7x7 image
    n_nodes = 128 * 7 * 7
    model.add(layers.Dense(n_nodes, input_dim=latent_dim))
    model.add(layers.LeakyReLU())
    model.add(layers.Reshape((7, 7, 128)))
    # upsample to 14x14
    model.add(layers.Conv2DTranspose(128, (4,4), strides=(2,2), padding='same'))
    model.add(layers.LeakyReLU())
    # upsample to 28x28
    model.add(layers.Conv2DTranspose(128, (4,4), strides=(2,2), padding='same'))
    model.add(layers.LeakyReLU())
    model.add(layers.Conv2D(1, (7,7), activation='sigmoid', padding='same'))
    return model

def define_discriminator(in_shape=(28,28,1)):
    model = Sequential()
    model.add(layers.Conv2D(128, (5,5), strides=(2, 2), padding='same', input_shape=in_shape))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.3))
    model.add(layers.Conv2D(128, (5,5), strides=(2, 2), padding='same'))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.3))
    model.add(layers.Flatten())
    model.add(layers.Dense(1, activation='sigmoid'))
    # compile model
    opt = Adam(lr=0.0002)
    model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
    return model

# size of the noise vector
latent_dim = 100
num_examples_to_generate = 16

g_model = define_generator(latent_dim)

d_model = define_discriminator()

# define the combined generator and discriminator model, for updating the generator
def define_gan(g_model, d_model):
    # make weights in the discriminator not trainable
    d_model.trainable = False
    # connect them
    model = Sequential()
    # add generator
    model.add(g_model)
    # add the discriminator
    model.add(d_model)
    # compile model
    opt = Adam(lr=0.0002)
    model.compile(loss='binary_crossentropy', optimizer=opt)
    return model

gan_model = define_gan(g_model, d_model)

# select real samples
def generate_real_samples(dataset, n_samples):
    # choose random instances
    ix = randint(0, dataset.shape[0], n_samples)
    # retrieve selected images
    X = dataset[ix]
    # generate 'real' class labels (1)
    y = ones((n_samples, 1))
    return X, y

# generate points in latent space as input for the generator
def generate_latent_points(latent_dim, n_samples):
    # generate noise vector for training
    x_input = randn(latent_dim * n_samples)
    # reshape into a batch of inputs for the network
    x_input = x_input.reshape(n_samples, latent_dim)
    return x_input

# use the generator to generate n fake examples, with class labels
def generate_fake_samples(g_model, latent_dim, n_samples):
    # generate points in latent space
    x_input = generate_latent_points(latent_dim, n_samples)
    # predict outputs
    X = g_model.predict(x_input)
    # create 'fake' class labels (0)
    y = zeros((n_samples, 1))
    return X, y

def generate_and_save_images(epoch):
  # for generating the fake images after each epoch

  # generate points in the latent space
  noise = randn(latent_dim * num_examples_to_generate)
  # reshape into a batch of inputs for the network
  noise = noise.reshape(num_examples_to_generate, latent_dim)
 
  predictions = g_model(noise, training=False)

  fig = plt.figure(figsize=(4, 4))

  for i in range(predictions.shape[0]):
      plt.subplot(4, 4, i+1)
      plt.imshow(predictions[i, :, :, 0], cmap='gray')
      plt.axis('off')

  plt.savefig('image_at_epoch_{:04d}.png'.format(epoch))
  plt.show()

def train(g_model, d_model, gan_model, dataset, latent_dim, n_epochs=60, n_batch=256):
  bat_per_epo = int(dataset.shape[0] / n_batch)
  half_batch = int(n_batch / 2)

  for epoch in range(n_epochs):

    start = time.time()

    for batch in range(bat_per_epo):
      
      X_real, y_real = generate_real_samples(dataset, half_batch)

      X_fake, y_fake = generate_fake_samples(g_model, latent_dim, half_batch)

      X = vstack((X_real, X_fake))

      y = vstack((y_real, y_fake))

      d_loss, _ = d_model.train_on_batch(X,y)

      X_gan = generate_latent_points(latent_dim, n_batch)

      y_gan = ones((n_batch, 1))

      g_loss = gan_model.train_on_batch(X_gan, y_gan)

    display.clear_output(wait=True)
    generate_and_save_images(epoch + 1)

    print('Time for epoch {} is {} sec'.format(epoch + 1, time.time()-start))

  display.clear_output(wait=True)
  generate_and_save_images(n_epochs)

train(g_model, d_model, gan_model, dataset, latent_dim)

我得到的输出是:

Output for train(...) command

没有错误,或者只是我看不到带有噪声输入的生成器的输出。

应该显示输出的函数是 generate_and_save_images

当您在 plt.imshow() 中使用 cmap="gray" 时,您必须取消缩放输出或设置 vmin 和 vmax。 据我所知,您通过除以 255 进行缩放,因此您必须将数据乘以 255,或者,alternativle set vmin=0, vmax=1 选项 1:

plt.imshow(predictions[i, :, :, 0]*255, cmap='gray')

选项 2:

plt.imshow(predictions[i, :, :, 0], cmap='gray', vmin=0, vmax=1)