最近在跟着教程用PyTorch搭一个简单的DCGAN,想在自拍数据集上生成点真人脸的假图。结果每次训练到差不多200个epoch左右,判别器loss就突然飙到20多,生成器loss直接掉到0附近,然后整个模型就废掉了,出来的全是噪点。我确认过数据归一化是[-1,1],学习率设的是0.0002,用的是Adam优化器。有人说是梯度爆炸或者模式崩塌,但我不知道怎么判断具体是哪种,也不知道该调什么参数。有没有大佬给个排查思路?或者有什么靠谱的GAN训练trick可以分享?先谢过。
用PyTorch写GAN训练到一半loss爆了,有人遇到过类似情况吗?
全部回复
共 171 条我遇到过一模一样的,DCGAN训到后期discriminator loss飙到20多基本就是梯度爆炸了,你把D的输入加个gradient penalty试试,或者干脆把learning rate降到0.0001以下。另外自拍数据集如果不够干净或者人脸不够居中,比CelebA难训很多,建议先裁剪对齐到64x64再跑。模式崩塌的话通常loss曲线是震荡的,不会像你说的这样突然断崖式跳变,所以先排除爆炸。
我之前也卡在这,后来发现是D的最后一层没用sigmoid而是裸的logits,然后BCEWithLogitsLoss里又叠加了别的操作,改回来就好多了。你可以把D和G的loss分开打印,再看看D对真实图和假图的输出均值,如果真实图输出突然掉到负数很大,就是爆炸没跑了。trick的话,试试给D加个label smoothing,或者每训练一次D就训练两次G,能稳不少。
D loss飙到20多、G loss掉到0,这基本就是D太强把G压死了,模式崩塌的典型症状。你可以先看看D的梯度norm是不是爆炸了,顺便把D的更新频率降一降,比如每训两次G才训一次D。另外DCGAN里加个谱归一化或者把D的lr调低一点(比如1e-4)挺管用的,我上次这么改完就稳多了。
我当初也卡在这个阶段,200个epoch左右D loss飙升基本就是D太强了,G梯度消失导致的崩盘。你可以先看看D的准确率是不是快接近1了,如果是就说明D过拟合了。建议把D的更新频率降一降,比如每更新两次G才更新一次D,或者给D加个label smoothing,把真实标签从1改成0.9。另外自拍数据集样本量小也容易崩,试试加一点数据增强或者用TTUR把D的学习率调低一半。
D loss飙到20多、G loss掉到0,这基本就是D太强把G按死了,模式崩塌的典型症状,跟梯度爆炸不太一样。你可以先把D的更新频率降一降,比如G更新两次D才更新一次试试。另外200个epoch对DCGAN来说已经不短了,后面D稍微强一点就容易崩,加个label smoothing或者给D的输入加点噪声会稳不少。学习率0.0002其实还行,但两个优化器都这个值可能偏大,试试把D的lr降到0.0001看看。
试试把判别器更新频率降一降,或者给D的输入加点儿噪声,200个epoch才崩已经挺能扛了。
你描述的这个现象我太熟了,大概率是判别器太强把生成器压死了,而不是单纯的梯度爆炸。你可以看下D loss飙到20多的时候,D对真实样本和假样本的输出是不是几乎饱和了,比如真样本都接近1、假样本都接近0,如果是这样那生成器基本拿不到有效梯度,loss掉到0就是它摆烂了。排查上建议先把D的更新频率降下来,比如每更新两次G才更新一次D,或者把D的学习率调到G的一半试试。另外DCGAN里如果用BatchNorm要注意,生成器和判别器里都别在最后一层用,判别器输入也别用,不然容易加剧不稳定。还有个常见坑是Adam的beta1默认0.9对GAN偏大,换成0.5会稳很多,这个在原始DCGAN论文里就提过。如果还是崩,可以加个label smoothing,把真实标签从1改成0.9,或者给D的输入加一点高斯噪声,能明显缓解D过强的问题。至于模式崩塌,典型表现是G生成的图高度相似、多样性很差,跟loss爆掉是两回事,你这个更像训练失衡,先把D压一压再看。
D loss飙到20多、G loss掉到0,这个信号其实挺典型的,大概率是D太强了,把G按在地上摩擦,G梯度直接消失。你可以先别急着调学习率,去打印一下D对真实样本和假样本的平均输出值,如果真实样本那边接近1、假样本那边也很快被压到0附近,那基本就是D过强导致的训练失衡。200个epoch才崩说明前期还能撑住,后面D慢慢把决策边界收得太紧,G就彻底没梯度了。判断是不是模式崩塌可以看G生成的多样性,如果所有输出都趋同或者直接变噪点,那更像是G已经死了。可以试试把D的学习率降到G的一半,或者给D加个dropout、label smoothing,再不行就换成WGAN-GP,训练稳定性会好很多。另外batch size如果太小也容易让D过拟合,适当加大一点或者用TTUR(双时间尺度更新规则)会稳一些。
你D掉到0、G loss飙高,更像是判别器太强把生成器压死了,不一定是梯度爆炸。我之前也遇到过,后来把D的更新频率降到G的一半,或者给D加个谱归一化就稳多了。另外建议你每50个epoch存一次模型和生成的图,方便回看崩之前发生了什么。实在不行先拿CelebA这种干净数据跑通再换自拍,小数据集真的很容易崩。
我之前也遇到过类似的情况,大概率是判别器太强了把生成器压死了,你盯着D loss突然飙、G loss掉到0,这基本就是模式崩塌的典型表现。可以试试把D的更新频率降下来,比如每训两次G才训一次D,或者把D的学习率调低一点。另外DCGAN里BN层和leaky relu别乱改,标签平滑到0.9也有点用。
我之前也遇到过类似问题,后来换了方案。
刚入门,这个对我帮助很大。