使用tf.GradientTape训练GAN时生成器梯度返回[None]如何解决
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
关联逻辑说明
判别器目标是区分合法样本与对抗样本,输入包含两倍batch大小数据:一路是预处理后的合法数据,另一路是生成器修改得到的对抗样本。生成器仅含单个权重,由封装乘加操作的lambda层构成,判别器为全连接网络。
损失均采用BinaryCrossentropy计算:判别器损失基于样本是否被修改的真实标签计算,生成器损失统计对抗样本被判别为合法样本的概率。
问题根因排查方向
- 生成对抗样本的
adversarial_path函数未在tf.GradientTape上下文范围内调用生成器,或者根本没有调用生成器,导致梯度带没有记录生成器权重的计算链路,无法反向传播梯度。 - 生成器的lambda层权重未被正确注册为可训练参数,可打印
generator.trainable_weights确认carrier_freq是否在返回列表中,排除权重未被识别为可训练参数的问题。 - 生成器内部或
adversarial_path流程中使用了不可微操作,例如将张量转为numpy数组、使用非TensorFlow内置算子、添加tf.stop_gradient截断梯度、强制类型转换为无梯度的整数类型、对生成的对抗样本做量化/编码这类不可微预处理,都会打断梯度传播链路。 - 生成器的乘加操作没有关联到可训练的
carrier_freq变量,例如lambda层内直接用了常量做计算,没有引用生成器的可训练权重。
内容的提问来源于stack exchange,提问作者jost
相关产品推荐
相关产品推荐

