最近在跟着教程用PyTorch搭一个简单的DCGAN,想在自拍数据集上生成点真人脸的假图。结果每次训练到差不多200个epoch左右,判别器loss就突然飙到20多,生成器loss直接掉到0附近,然后整个模型就废掉了,出来的全是噪点。我确认过数据归一化是[-1,1],学习率设的是0.0002,用的是Adam优化器。有人说是梯度爆炸或者模式崩塌,但我不知道怎么判断具体是哪种,也不知道该调什么参数。有没有大佬给个排查思路?或者有什么靠谱的GAN训练trick可以分享?先谢过。
用PyTorch写GAN训练到一半loss爆了,有人遇到过类似情况吗?
全部回复
共 163 条这个思路不错,收藏了。
这情况太典型了,我之前用DCGAN也栽在过同一个坑里。你可以先试试把判别器里的BatchNorm换成InstanceNorm,或者给生成器加个dropout,很多情况下能稳住训练。另外,loss爆掉之前D的loss是不是一直压得很低?如果是的话大概率是判别器太强把生成器梯度打没了,可以考虑调低D的学习率或者用标签平滑。你那个自拍数据集如果人脸位置比较单一,也容易让模型偷懒走捷径,建议先跑个纯随机背景的验证集看看。
我之前也撞见过一模一样的现象,200轮附近D loss突然起飞,G loss归零基本就是判别器太强把生成器彻底压死了。建议先试试把判别器换成SGD,或者给D加个label smoothing,有时候0.9/0.1这种软标签能救回来。另外可以查一下是不是D的梯度在最后几层爆了,clip一下norm到1左右,比调学习率见效快。
这现象太典型了,我当初调DCGAN时也卡在这。你那个“判别器loss飙到20”其实不是梯度爆炸,更像是判别器“赢麻了”——它把真图和假图分得太彻底,梯度回传时把生成器直接压死,模式崩塌的前兆。先别急着动学习率,你试试把判别器的更新次数降下来,比如每训练一次生成器再训练一次判别器,甚至让判别器每两次迭代才更新一次。另一个很隐蔽的坑是batch size,如果设得太大(比如128以上),判别器很容易过拟合,我后来改成64就好了。还有,你说的“噪点”很可能是生成器梯度消失,可以检查一下最后一层有没有用Tanh,以及BCELoss是不是直接用了logits而非经过Sigmoid,这俩错一个都容易在后期崩。另外,强烈建议把Adam的betas调成(0.5, 0.999),这是DCGAN原论文的默认值,默认的(0.9, 0.999)对GAN来说太“冲”了。最后说个玄学但有效的招:给判别器加一点标签平滑,真图标签从1改成0.9,能极大缓解这种后期暴死。你先试这三样,大概率能撑过300个epoch。
这loss曲线一看就是典型的训练崩了,建议先调低判别器学习率或者给它加个标签平滑试试。
我上次也这样,把batch size调大点或者换用SpectralNorm就好多了,你可以先试试哪个有效。
我之前跑DCGAN也踩过这个坑,loss爆掉基本就是判别器太强把生成器碾压了,可以试试把判别器的学习率调低点,或者给它加个梯度惩罚。另外你那个200轮才炸很像是训练后期判别器过拟合了,建议检查一下真实图片和生成图片的分布差异,有时候是数据里混了太多相似的自拍导致判别器容易钻牛角尖。还有个笨办法,把batch size调大或者换用SGD优化器,虽然慢但稳定性会好很多。
我之前跑DCGAN也遇到过一模一样的情况,200轮左右直接崩。你这个描述听着更像是判别器太强了,把生成器压死了,梯度爆炸一般loss会乱跳而不是单边倒。可以试试把判别器换更浅一点的网络,或者给它加个dropout,让生成器喘口气。另外那个loss飙到20多,大概率是判别器过拟合了,可以调低它的学习率或者减少它的更新次数,比如每更新两次生成器再更新一次判别器。
我之前练DCGAN也碰到过一模一样的,loss暴涨基本就是判别器太强把生成器压死了,典型的不稳定训练。你可以试试把判别器的学习率调低一点,比如改成0.00005,或者给生成器加个标签平滑,别让判别器那么自信。如果还是崩,建议直接把训练停掉,加载最近的checkpoint把学习率调小再续跑,比从头调省时间。另外可以看看判别器最后一层有没有加Sigmoid,有时候数值范围不对也会这样。
之前做实验也遇到过一模一样的现象,200轮左右突然崩盘基本就是判别器太强把生成器压死了,典型的不稳定训练。你可以试试把判别器的学习率调低到生成器的三分之一,或者给它加个梯度惩罚,这个对稳定性帮助很大。另外把batch size调大一点,比如64到128,也能缓解loss跳变。如果还不行就检查下生成器最后一层是不是忘加tanh了,有时候这个小细节会让输出分布跑偏。
这情况太经典了,我之前调DCGAN也卡在这。建议你先盯一下生成器和判别器loss的曲线,如果D的loss是先缓降再突然暴增,大概率是梯度爆炸,可以在判别器里加个谱归一化或者梯度惩罚试试。另外把学习率降到0.0001,或者给Adam加个weight decay,有时候真能救回来。模式崩塌的话,生成器loss会一直很低但图片多样性极差,你可以看看不同batch的生成结果是不是长得一模一样。
这情况太典型了,我当初用DCGAN跑人脸也翻过车,八成是判别器收敛太快把生成器压死了。你可以先盯一下D的loss曲线,如果它一路飙高不带回落的,基本就是梯度爆炸,试试把判别器改成LSGAN那种最小二乘损失,或者给D加个谱归一化。另外200个epoch才崩的话,也可能是生成器学习率太小跟不上D,把两边学习率错开试试,比如D设1e-4,G设2e-4。还有个笨办法,每次迭代里多训练几次G,少训几次D,强行让G喘口气。反正先别急着换模型结构,把loss曲线打出来看下趋势,比瞎猜靠谱。
把D的loss砍一半再训,或者给G加个标签平滑,这情况八成是D学太快了。
一看就是模式崩塌,先把学习率降到0.0001以下,再加个标签平滑试试。
我之前也栽这上面,后来把生成器加个BN层,loss稳多了。
判别器loss飙到20多大概率是梯度爆炸,试试把判别器里的BN层换掉或者加个谱归一化。
我之前也踩过这坑,调小学习率到1e-4同时给生成器加个标签平滑会稳很多。
我之前跑DCGAN也遇到过一模一样的症状,200轮左右D loss突然冲高,基本就是判别器太强把生成器彻底碾压了,典型的不稳定训练。可以先试试把D的学习率降到0.00005,或者给D加个标签平滑,比如把真实标签从1换成0.9,能缓解不少。另外检查下是不是D更新次数比G多,最好保持1:1,别让D太早收敛。模式崩塌的话一般生成图会重复某几个样式,你这种全噪点更像是梯度爆炸,可以给G和D都加个梯度裁剪,或者换用SpectralNorm试试。
我之前跑DCGAN也遇到过一模一样的,200轮左右D的loss飙到20基本就是梯度爆炸了,不是模式崩塌。你可以试试把判别器改成LSGAN那种最小二乘损失,或者给D加个谱归一化,能稳很多。另外Adam的beta1默认0.9在GAN里太激进,改成0.5对收敛帮助很大,我这么调完基本没再爆过。还有个小技巧是每次更新G之前,把D的梯度做一下clip,虽然土但很管用。你那个自拍数据集要是脸比较单一的话,也得注意是不是生成器太容易骗过D导致D开始摆烂。
我之前跑DCGAN也遇到过一模一样的现象,大概也是200轮左右,D loss突然起飞,G loss归零,生成图直接糊成一团。你这种情况我赌五毛是模式崩塌,不是单纯梯度爆炸,因为梯度爆炸通常D和G会一起疯涨,而不是一个飙一个躺平。可以先试试把判别器里的BatchNorm换成InstanceNorm,或者给D加个谱归一化,这招对稳定训练特别管用。另外你那个学习率虽然是标准值,但自拍数据集背景复杂,可以试着调成0.0001甚至0.00005,同时把beta1从0.5改成0.5以下。还有个小技巧,把D的loss改成软标签,就是真图不是1而是0.9,假图不是0而是0.1,能缓解后期loss震荡。你要是想快速验证是不是崩塌,把G的输入噪声维度从100加到256,或者给G加一点dropout,看看是不是能撑过300轮。我上次这么改完,虽然没完全根治,但至少能多撑几十轮,最后加了个梯度惩罚才彻底稳住。
试试把判别器换成谱归一化,然后调低学习率到1e-4,我之前就是这么救回来的。
我之前也踩过差不多的坑,判别器loss冲到20多基本就是梯度爆炸了,可以试试把判别器的权重裁剪或者加个谱归一化,能稳很多。另外模式崩塌的话,生成器loss不会掉到0那么夸张,你这种情况更像判别器太强直接把生成器碾压了。建议先减小判别器学习率,或者给它加个label smoothing,让判别器别那么自信。还有个小技巧是把batch size调大点,能缓解训练后期的不稳定。
遇到过,200个epoch才爆说明前面还正常,大概率是判别器累积误差导致梯度异常。你可以把判别器的loss打印出来看看是不是最后几轮突然跳变,如果是的话,试试把Adam的betas改成(0.5, 0.999),这是DCGAN原论文的设置。另外检查下生成器有没有用BatchNorm,特别是最后一层别加,不然容易震荡。我之前是把生成器的学习率单独调低到0.0001,然后判别器加了个梯度惩罚,就没再爆过了。
这种后期爆loss挺典型的,不一定是梯度爆炸,也可能是判别器收敛太快,把生成器逼到死角了。你可以试着每训练几次判别器就训练一次生成器,比如1:1改成1:3,让生成器有更多机会追赶。还有就是看看你的自拍数据集是不是太单一,如果人脸角度和光线都差不多,模式崩塌概率会很高,
这情况太典型了,基本就是模式崩塌的前兆,不过也不排除是判别器收敛太快把生成器压死了。你可以试试把判别器的学习率调低点,或者给生成器用更高的学习率,让两边节奏错开;另外把batch size调大或者加些标签平滑(比如把真实标签设成0.9),对稳定训练挺管用的。我之前也被这个折磨过,后来加了谱归一化加上每训练一次判别器就训练三次生成器,才稍微稳下来。你那个自拍数据集要是人脸角度太单一,也容易崩,建议先清洗下数据分布看看。