最近在跟着教程用PyTorch搭一个简单的DCGAN,想在自拍数据集上生成点真人脸的假图。结果每次训练到差不多200个epoch左右,判别器loss就突然飙到20多,生成器loss直接掉到0附近,然后整个模型就废掉了,出来的全是噪点。我确认过数据归一化是[-1,1],学习率设的是0.0002,用的是Adam优化器。有人说是梯度爆炸或者模式崩塌,但我不知道怎么判断具体是哪种,也不知道该调什么参数。有没有大佬给个排查思路?或者有什么靠谱的GAN训练trick可以分享?先谢过。
用PyTorch写GAN训练到一半loss爆了,有人遇到过类似情况吗?
全部回复
共 163 条我之前也踩过一模一样的坑,DCGAN大概跑到150轮左右D的loss突然起飞,后来发现是D太强了,G的梯度完全带不动。你可以先试试把D的学习率降到0.00005,或者给D加个标签平滑,真实标签用0.9而不是1.0,这招对稳定训练挺有效的。另外检查下是不是batch size太小,自拍数据集如果图片多样性不够,很容易在200轮附近把D训练到完美分类,这时候G就彻底学不到东西了。如果调完还爆,就考虑把G换成带残差的结构,或者加个谱归一化,能扛住不少崩溃场景。
这情况太典型了,我一开始玩DCGAN也栽在这上面。你可以先试试把判别器的loss曲线打出来,如果它是突然断崖式上涨而不是缓慢上升,那大概率是梯度爆炸,给判别器加个梯度裁剪或者谱归一化能压住。另外模式崩塌的话生成器loss会一直很低但图片很单一,你这噪点更像是判别器太强直接把生成器锤死了,可以试试把生成器和判别器的学习率错开,比如生成器用0.0002,判别器降到0.00005,或者换用SGD加动量,有时候Adam在GAN里反而容易不稳定。还有个笨办法,把batch size调大点,或者每次更新判别器时多跑几步,让生成器跟上节奏。
我之前用DCGAN也遇到过一模一样的现象,后来发现是判别器收敛太快,直接把生成器压死了。你可以试试把判别器的学习率调低一点,或者给生成器那边用更高的学习率,比如1e-3对5e-5这种不对称设置。另外,给判别器加一点标签平滑或者噪声,能有效防止loss冲到20多,我之前把真实标签从1改成0.9,情况就好多了。还有个思路是检查一下是不是batch size太小导致训练不稳定,我换到64之后明显改善。你可以先试试把判别器训练次数减少,比如每训练一次生成器只训一次判别器,看看loss曲线会不会稳下来。
我之前跑DCGAN也踩过这坑,200轮左右崩大概率是判别器收敛太快,生成器梯度被带偏了。你可以试试把判别器的学习率调成生成器的一半,或者给它加个标签平滑,能缓解不少。另外检查下是不是真实图片里有几张异常亮或模糊的图,偶尔会让D的loss瞬间起飞。如果崩了之后loss回不来,基本就是梯度爆炸,可以给D的卷积层加个谱归一化,比调学习率省心。
我之前也踩过这个坑,DCGAN训到后期loss爆炸大概率是判别器太强把生成器直接压死了。你可以试试把判别器的学习率调成生成器的三分之一,或者给判别器加个谱归一化,能稳很多。另外可以先不用自拍数据集,用FFHQ或者CelebA跑一遍,排除是不是数据本身的问题。万一还是爆,就调小batch size或者把生成器最后一层的激活函数换掉看看。
大概率是判别器收敛太快把生成器压死了,试试把判别器学习率调低到0.00005或者加个标签平滑。
我上次也是这情况,后来把BCE换成Hinge loss立马稳了,你可以先排除下是不是梯度爆炸。
我之前跑DCGAN也踩过这个坑,200轮左右G和D的loss突然两极分化,多半不是梯度爆炸,更像是模式崩塌的前兆。你可以先试试把判别器里的BatchNorm去掉,或者改成InstanceNorm,有时候BN在小数据集上反而会引入不稳定。另外建议把学习率降到0.0001以下,或者给D加个标签平滑(正样本标0.9),能明显缓解loss乱窜。我之前用这招把训练稳到了500多轮,你可以先从小改动试起,别一次调太多参数。
我之前跑类似结构也炸过,后来发现是判别器训练步数太多导致收敛太快,生成器根本追不上。你可以试试把判别器的学习率调低一点,或者每训练两次生成器再训一次判别器。另外,把判别器loss里加的噪声去掉或者用标签平滑(比如真实标签设成0.9),能稳住一些。还有个小技巧,如果loss爆了立刻降学习率到原来的十分之一,有时候能救回来。
我之前跑DCGAN也踩过一模一样的坑,200个epoch左右这个时间点太典型了。你先把判别器loss打出来看看,如果它是先正常下降然后又突然冲高,而生成器loss归零,那大概率不是梯度爆炸,是判别器太强直接把生成器压死了。我那时候试过把判别器换成SGD,学习率调成0.0001,然后给生成器用Adam,勉强稳住了,但图像质量还是不太行。后来发现真正的问题是batch size太小,我换成64之后情况好了很多,你可以试试。另外检查一下你的自拍数据集,是不是有大量重复或者极端光照的图,那种样本会让判别器快速过拟合,导致后期loss行为异常。还有个土办法,把生成器的loss从BCE换成最小二乘那种形式,或者给判别器加个梯度惩罚,虽然麻烦但能防止它loss飙得太离谱。不过说实话,DCGAN本身就不太稳,你要是想省时间,直接上WGAN-GP或者SAGAN的现成代码,调参成本低很多。
这情况太典型了,DCGAN训到后面崩基本都长这样。我之前玩人脸数据集也踩过同样的坑,200轮左右D的loss突然起飞,G直接躺平输出噪声,十有八九是判别器太强把生成器压死了。你可以先试试把D的更新频率降下来,比如每训一次D就训两次G,或者给D加个label smoothing让目标别那么极端,0.9和0.1这种。另外检查下D的最后一层是不是没加sigmoid,如果用的是BCEWithLogitsLoss,那输出层就不能有sigmoid,不然数值会乱飘。还有个小技巧是给D加谱归一化,虽然DCGAN原始实现没这个,但很多人实践下来能明显稳住训练。你要是想快速验证是不是模式崩塌,可以把G的输入噪声固定下来,隔几个epoch存一次生成图,看是不是逐渐变成同一张脸。调参的话,试试把learning rate降到0.0001,或者给Adam加个weight decay,有时候就是优化器太激进。最后实在不行,换个现成的WGAN-GP架构,反正代码改动不大,但稳定性提升立竿见影。
试试把判别器改成LSGAN的loss,或者给D加个谱归一化,我之前这么改完稳多了。
这情况八成是D收敛太快把G压死了,试试把D的学习率调低或者加个标签平滑。
我之前也炸过,改成每训练一次D就训练两次G,稳多了。
我之前跑DCGAN也撞见过一模一样的状况,loss像坐过山车一样突然就崩了。你这种情况大概率不是简单的梯度爆炸,更像是判别器太强把生成器彻底碾压了,导致生成器梯度消失,最后只能输出噪点碰运气。可以试试把判别器改成谱归一化或者加一点标签平滑,让判别器别那么自信,我用了之后稳定性明显好很多。另外你提到200个epoch才崩,这个时间点很微妙,可能是学习率或者beta1在后期不合适,建议把Adam的beta1从0.9调到0.5,对GAN来说是常规操作。还有一个很蠢但有效的排查方法:把判别器loss单独打出来看,如果它在崩之前一直单调下降,那基本就是判别器过拟合了,这时候可以降低判别器的更新频率,比如每训练两次生成器才训一次判别器。至于模式崩塌,最直观的表现是生成图多样性很差,但你现在是纯噪点,所以大概率不是模式崩塌,更像是训练动力学失衡。最后强烈建议开个梯度惩罚或者用WGAN-GP的损失函数,虽然代码改动不大,但收敛曲线会平滑很多,至少不会让你半夜盯着loss怀疑人生。
我之前也遇到过一模一样的情况,200轮左右D loss飙升基本就是梯度爆炸的典型症状,可以试试把判别器改成梯度惩罚或者谱归一化,能稳很多。另外建议你把D的训练步数降到和G一样,或者给D加个label smoothing,0.9和0.1这种,能防止它太自信。如果还不行就检查下你是不是用了BatchNorm,在DCGAN里用BN有时会在后期不稳定,换成InstanceNorm可能会好点。模式崩塌一般不是这个表现,你这种更像是D把G彻底碾压了,先降低D的学习率到1e-4试试看。
遇到过,判别器太强了,试试把生成器学习率调高或者给判别器加个标签平滑。
试试把判别器换成SpectralNorm,再把学习率降到0.0001,我之前也这样炸过,基本就是判别器太强压死生成器了。
我踩过这坑,多半是判别器太强把生成器压死了,试试把判别器学习率降到0.00005或者加个label smoothing。
把batch size调大点或者换BCE loss试试,之前我加了个梯度惩罚就稳了。
这情况我太熟了,之前做动漫头像也这样崩过。你试试把判别器的learning rate降到1e-4,生成器保持2e-4,两个网络用不同步长能稳不少。再就是别让判别器太强,可以给它加个梯度惩罚或者用标签平滑,真标签别用1,用0.9那种。另外每训练一次判别器就让它少跑几步,比如一次生成器对应三次判别器这种比例也值得调调。
八成是判别器太强把生成器压死了,试试调低D的学习率或者用标签平滑。我之前也这样,降到0.0001就好多了。
这情况太典型了,八成是判别器太强把生成器打崩了,试试调低D的学习率或者加个标签平滑。
先把batch size调大点,再给D加个dropout,我上次这么弄就把loss稳住了。