admin管理员组

文章数量:1435823

Having some experience in developing neural networks in Keras, I decided to write a non-standard GAN, which you can't really call as such. The point is that the discriminator is a ready-made neural network that perfectly predicts the quality of a face image, and I wanted my network to increase the resolution of 48 by 48 images by 4 times (made them 96 by 96). My regular GAN with a trainable discriminator simply interpolated the image to a larger space with a loss of quality, as if you simply enlarged the image on a computer. It is not so important for me that the image is a complete copy, so the idea with a ready-made discriminator seemed good to me.

Here is the code of train step function:

@tf.function
def train_step(images_x, images_y):

  with tf.GradientTape() as gen_tape:
    generated_images = generator(images_x, training=True).numpy()

    #Integrating ready-made network, which returns numpy array with shape (batch_size, 1) and contains scalars representing the number in range of 0-1
    fake_output = K.constant(face_detector.estimate(generated_images)) #K = tensorflow backend

    gen_loss = generator_loss(fake_output)

  gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)

  generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))

  return gen_loss

common train function:

def train(dataset_x, dataset_y, epochs):
  history = []
  MAX_PRINT_LABEL = 10
  th = BUFFER_SIZE // (BATCH_SIZE * MAX_PRINT_LABEL)

  for epoch in range(1, epochs + 1):
    print(f'{epoch}/{EPOCHS}: ', end='')

    start = time.time()
    n = 0

    gen_loss_epoch = 0
    l = len(dataset_x)
    for o in range(l):
      tf.config.run_functions_eagerly(True) #I'm suspecting the issue is related to this, but i can't do it without running eagerly (train_step doesn't work)
      gen_loss = train_step(dataset_x[o], dataset_y[o]) 
      tf.config.run_functions_eagerly(False)
      print(gen_loss, disc_loss)
      gen_loss_epoch += K.mean(gen_loss)
      if (n % th == 0): print('=', end='')
      n += 1
    generator.save("generator.h5")


    history += [gen_loss_epoch / n]
    

  return history

generator structure and other

cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)

hidden_dim = 2


def dropout_and_batch():
  return Dropout(0.3)(BatchNormalization())

img_height = 96
img_width = 96
img_channels = 3  
latent_dim = 2  
input_img = Input(shape=(48, 48, 3))
x = Conv2D(32, 3, padding='same', activation='relu')(input_img)
x = Conv2D(32, 3, padding='same', activation='relu')(x)
x = Conv2D(32, 3, padding='same', activation='relu')(x)

x = Flatten()(input_img)
z_mean = Dense(latent_dim)(x)
z_log_var = Dense(latent_dim)(x)
@keras.saving.register_keras_serializable()
def sampling(args):
    z_mean, z_log_var = args
    epsilon = tf.random.normal([batch_size, latent_dim], 0, 1, tf.float32)
    return z_mean + tf.exp(0.5 * z_log_var) * epsilon 
z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, 
 z_log_var])


decoder_input = Input(shape=(latent_dim,))
x = Dense(img_width*img_height*3, activation='relu')(decoder_input)
x = Reshape((img_width, img_height, 3))(x)
x = Conv2D(32, 3, padding='same', activation='relu')(x)
x = Conv2D(32, 3, padding='same', activation='relu')(x)
decoded = Conv2D(3, 3, padding='same', activation='sigmoid')(x)

encoder = Model(input_img, [z_mean, z_log_var, z])
decoder = Model(decoder_input, decoded)

generator = Model(input_img, decoder(encoder(input_img)[2]))

custom loss function:

def generator_loss(fake_output):
  loss = cross_entropy(tf.ones_like(fake_output), fake_output)
  return loss

loading dataset:

for path in glob("faces/*.jpg"):
  img = Image.open(path)
  y_train.append(np.asarray(img.resize((96, 96))))
  if y_train[-1].shape != (96, 96, 3):
    del y_train[-1]
    continue
  x_train.append(np.asarray(img.resize((48, 48))))
x_train = np.asarray(x_train)/255
y_train = np.asarray(y_train)/255

BUFFER_SIZE = x_train.shape[0]
BATCH_SIZE = 100

BUFFER_SIZE = BUFFER_SIZE // BATCH_SIZE * BATCH_SIZE
x_train = x_train[:BUFFER_SIZE]
y_train = y_train[:BUFFER_SIZE]
print(x_train.shape, y_train.shape)


train_dataset_x = list(tf.data.Dataset.from_tensor_slices(x_train).shuffle(BUFFER_SIZE).batch(BATCH_SIZE))
train_dataset_y = list(tf.data.Dataset.from_tensor_slices(y_train).shuffle(BUFFER_SIZE).batch(BATCH_SIZE))

I have had this error that I still can't solve on my own and with Gemini for a long time now: ValueError: No gradients provided for any variable (it points to a line generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables)))

本文标签: pythonProblems with setting gradients of GAN in kerasStack Overflow