Ошибка значения: градиенты не предусмотрены ни для одной переменной в TensorFlow при построении GAN

#python #python-3.x #tensorflow #generative-adversarial-network

#python #python-3.x #tensorflow #порождающая-состязательная-сеть

Вопрос:

Я пытаюсь создать GAN для университетского задания. Мой код очень похож на вводный пример в этом руководстве с веб-сайта TF.

Ниже приведены, по моему мнению, соответствующие части кода (при необходимости можно предоставить более подробную информацию, например. как строится модель дискриминатора). Строка, которая выдает мне ошибку:

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

Это может быть связано со слоями моего генератора, поскольку это почти единственное отличие от примера кода TF..

 def create_generator(max_len, vocab_size):
  model = tf.keras.Sequential()
  model.add(tf.keras.layers.Embedding(vocab_size, output_dim=64, input_length=max_len))  
  model.add(tf.keras.layers.LSTM(units=1024, activation='tanh'))
  model.add(tf.keras.layers.Dense(units=1024, activation='sigmoid'))
  model.add(tf.keras.layers.Dense(units=MAX_LEN, activation=None))

  return model

generator = create_generator(MAX_LEN, VOCABULARY_SIZE)

for epoch in range(EPOCHS):
  noise = (tf.random.uniform([BATCH_SIZE, LATENT_DIM], minval=0, maxval = VOCABULARY_SIZE))

  with tf.GradientTape() as disc_tape, tf.GradientTape() as gen_tape:

    # Generator loss    
    fake_revs = generator(noise)
    pred_class_fake_revs = discriminator(fake_revs)
    gen_loss, gen_acc = generator_loss_and_accuracy(pred_class_fake_revs)

    # Disc loss
    real_revs = reviews_tok_padded[np.random.randint(0, len(reviews_tok_padded),BATCH_SIZE)]
    pred_class_real_revs = discriminator(real_revs) 
    disc_loss, disc_acc = discriminator_loss_and_accuracy(pred_class_real_revs, pred_class_fake_revs)

    gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)    
    disc_grad = disc_tape.gradient(disc_loss, discriminator.trainable_variables)

    generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
    disc_optimizer.apply_gradients(zip(disc_grad, discriminator.trainable_variables))
 

Точная ошибка, которую я получаю,:

 ValueError: No gradients provided for any variable: ['embedding_22/embeddings:0', 'lstm_22/lstm_cell_30/kernel:0', 'lstm_22/lstm_cell_30/recurrent_kernel:0', 'lstm_22/lstm_cell_30/bias:0', 'dense_44/kernel:0', 'dense_44/bias:0', 'dense_45/kernel:0', 'dense_45/bias:0'].
 

Редактировать: после некоторого дальнейшего исследования становится ясно, что проблема заключается в том, что лента не вычисляет градиент, поэтому переменная gradients_of_generator равна none для всех generator.trainable_variables . Однако я не знаю, почему это происходит.

Комментарии:

1. Во время прямого прохождения вы используете другую градиентную ленту (disc_tape_real, disc_tape_fake), но вы пытаетесь вычислить градиенты дискриминатора с совершенно другой ленты (gen_tape или disc_tape)……… gen_tap не имеет отслеживания графика

2. Вы правы, это проблема. Однако это была ошибка при копировании кода и его упрощении для создания этого сообщения. Я только что исправил это и все еще получаю ту же проблему.

3. Я воспроизвел ваш код в colab, я не получаю ошибок, и градиенты вычисляются нормально. Можете ли вы поделиться своим кодом с ошибкой в colab? потому что я не вижу в этом никакой ошибки

4. Привет. Я только что нашел причину проблемы. Смотрите Ответ ниже. Спасибо, что уделили мне время.

Ответ №1:

Итак, я наконец-то нашел причину проблемы. Это связано со слоями в модели дискриминатора, которая даже не включена в приведенный выше фрагмент кода, поскольку я думал, что это не проблема (потому что, когда я тестировал дискриминатор как отдельную модель, он работал). Вот как это определяется:

 
    def crear_discriminador():
      model = tf.keras.Sequential()    
      model.add(tf.keras.layers.Embedding(input_dim=VOCABULARY_SIZE, output_dim=64, input_length=MAX_LEN))
      model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(units=64, activation='tanh')))
      model.add(tf.keras.layers.Dense(64, activation='relu'))
      model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
    
    return model
 

Проблема в том, что слой встраивания не является дифференцируемым, поэтому при объединении генератора и дискриминатора слой встраивания в дискриминаторе препятствовал вычислению градиента для слоев в генераторе.

Комментарии:

1. Проблема сейчас в том, что невозможность использовать слои на основе RNN (поскольку они нуждаются в встраивании) означает, что GAN работает намного хуже для генерации текста, что я и пытаюсь сделать. Так что любые предложения о том, как решить эту проблему, приветствуются

2. слой встраивания поддается обучению IMO, но я предполагаю, что вы делаете argmax, чтобы выбрать правильные индексы из генератора, прежде чем передавать его дискриминатору, который не предоставляет градиентов.