我正在尝试训练 GAN。不知何故,生成器的梯度返回 None,即使它返回鉴别器的梯度。这导致ValueError: No gradients provided for any variable: ['carrier_freq:0'].
优化器将梯度应用于权重(在这种情况下,只有一个权重,应该是一个梯度)。我似乎找不到原因,因为计算应该几乎相同。
这是生成器的梯度返回 [None] 的训练步骤的代码。
generator = make_generator()
discriminator = make_discriminator()
g_loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
g_optimizer = keras.optimizers.Adam(learning_rate=0.04)
d_loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
d_optimizer = keras.optimizers.Adam(learning_rate=0.03)
def train_step(train_set):
# modulate or don't modulate sample
for batch in train_set:
# get a random DEMAND noise sample to mix with speech
noise_indices = tf.random.uniform([batch_size], minval=0, maxval=len(demand_dataset), dtype=tf.int32)
# labels of 0 representing legit samples
legit_labels = tf.zeros(batch_size, dtype=tf.uint8)
# labels of 1 representing adversarial samples
adversarial_labels = tf.ones(batch_size, dtype=tf.uint8)
# concat legit and adversarial labels
concat_labels = tf.concat((legit_labels, adversarial_labels), axis=0)
# calculate gradients
with tf.GradientTape(persistent=True) as tape:
legit_predictions = discriminator(legit_path(batch, noise_indices))
adversarial_predictions = discriminator(adversarial_path(batch, noise_indices))
# concat legit and adversarial predictions to match double batch of concat_labels
d_predictions = tf.concat((legit_predictions, adversarial_predictions), axis=0)
d_loss = d_loss_fn(concat_labels, d_predictions)
g_loss = g_loss_fn(legit_labels, adversarial_predictions)
print('Discriminator loss: ' + str(d_loss))
print('Generator loss: ' + str(g_loss))
d_grads = tape.gradient(d_loss, discriminator.trainable_weights)
g_grads = tape.gradient(g_loss, generator.trainable_weights)
print(g_grads)
d_optimizer.apply_gradients(zip(d_grads, discriminator.trainable_weights))
g_optimizer.apply_gradients(zip(g_grads, generator.trainable_weights))
discriminator_loss(d_loss)
generator_loss(g_loss)
return d_loss, g_loss
这里有一些关于那里发生了什么
的信息: 鉴别器的目标是区分合法样本和对抗样本。鉴别器接收双倍的批次。一旦批处理以合法数据的方式进行预处理,并再次以产生对抗性数据的方式进行预处理,即数据通过生成器并在那里进行修改。
生成器现在只有一个权重,由包装在 lambda 层中的加法和乘法运算组成。
损失计算为标签和数据之间的 BinaryCrossentropy。鉴别器接收代表每个样本是否被修改的真实标签。生成器损失的计算类似,但它只考虑修改过的样本和代表合法样本的标签。所以它基本上衡量了有多少对抗样本被鉴别器分类为合法样本。
现在解决问题:
两种损失计算似乎都有效,因为它们返回了一个值。梯度的计算也适用于鉴别器。但是生成器的梯度返回[None]
。它应该与鉴别器梯度的计算非常相似,因为不同之处在于损失计算仅使用用于鉴别器损失的数据的子集。另一件事是,生成器只有一个权重,由 lambda 层组成,进行乘法和加法,而鉴别器是一个密集网络,具有多个权重。
有谁知道问题的根源可能是什么?