如何解决使用 tf.GradientTape 的自定义 GAN 训练循环返回 [None] 作为生成器的梯度,而它适用于鉴别器
我正在尝试训练 GAN。不知何故,生成器的梯度返回 None ,即使它返回鉴别器的梯度。当优化器将梯度应用于权重时,这会导致 ValueError: No gradients provided for any variable: ['carrier_freq:0'].
(在这种情况下只是一个权重,应该是一个单一的梯度)。我似乎找不到原因,因为计算应该几乎相同。
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 层组成,而判别器是一个密集网络并且有多个权重。
有人知道问题的根源是什么吗?
解决方法
我找到了问题和解决方案。无法从问题中提供的代码中解决问题,但我仍然想写下针对具有相同问题和背景情况的不太可能发生的事件的解决方案。
问题:生成器权重是 tf.keras.layers.Lambda()
层的一部分。
此类权重或变量将不会被跟踪以进行梯度计算。更多信息请访问:https://programming.vip/docs/day-6-tensorflow2-model-subclassing-api.html .
解决方案:编写自定义层,继承上面链接的基础层类。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。