单nn.Module封装的CycleGAN用单个优化器部分更新权重问题
CycleGAN训练参数更新控制问题解答
问题1:能否仅为整个CycleGAN模块使用一个优化器实现上述需求?
可以实现。核心逻辑是在反向传播的不同阶段,切换判别器Discriminator的参数梯度开关,控制梯度是否可计算,仅用同一个优化器就能完成不同模块的差异化更新。
问题2:能否在优化器执行.step()操作时冻结Discriminator的参数?
可以实现,有两种常用实现方案:
- 方案一:反向传播阶段控制梯度流
在计算生成器(即你的EncoderDecoder模块)相关损失前,将判别器所有参数的requires_grad属性设为False,此时生成器损失反向传播时不会给判别器参数计算梯度,自然不会在step时更新判别器权重。 - 方案二:step前手动清零判别器梯度
如果不想修改requires_grad属性,也可以在调用optimizer.step()前手动把判别器所有参数的梯度清空,此时反向传播时生成器损失给判别器带来的梯度被清除,step时判别器参数也不会被错误更新。
修改后的训练循环参考代码
c_gan.zero_grad() optimizer_gan.zero_grad() # 第一步:计算判别器损失,开启判别器梯度更新权限 for param in c_gan.disc.parameters(): param.requires_grad = True disc_color, disc_bw, decoded1, decoded2, decoded_disc = c_gan(images, images_bw) loss_true = bce_loss(disc_color, label_true) loss_false = bce_loss(disc_bw, label_false) disc_loss = loss_true + loss_false # 保留计算图,后续计算生成器损失时复用 disc_loss.backward(retain_graph=True) # 第二步:计算生成器损失,冻结判别器梯度更新权限 for param in c_gan.disc.parameters(): param.requires_grad = False decoded_loss = l2_loss(decoded2, images_bw) decoded_disc_loss = bce_loss(decoded_disc, label_true) both_decoded_losses = decoded_loss + decoded_disc_loss both_decoded_losses.backward() # 统一更新所有参数 optimizer_gan.step()
注意:第一次调用第一次
backward时需要加retain_graph=True参数,否则第一次反向传播后计算图会被释放,第二次反向传播计算生成器损失时会报错。
内容的提问来源于stack exchange,提问作者NakedCat
相关产品推荐
相关产品推荐

