最近试着玩了多种GAN,今天我们主要总结下常用的GAN包括DCGAN,WGAN,WGAN-GP,LSGAN-BEGAN,SRGAN的详细原理介绍以及他们对GAN的主要改进,并推荐了一些Github代码复现链接。
本文旨在对GAN的变种做一些梳理工作,详细请看下文。
1.GAN的原理:
GAN的主要灵感来源于博弈论中零和博弈的思想,应用到深度学习神经网络上来说,就是通过生成网络G(Generator)和判别网络D(Discriminator)不断博弈,进而使G学习到数据的分布,如果用到图片生成上,则训练完成后,G可以从一段随机数中生成逼真的图像。G, D的主要功能是:
● G是一个生成式的网络,它接收一个随机的噪声z(随机数),通过这个噪声生成图像
● D是一个判别网络,判别一张图片是不是“真实的”。它的输入参数是x,x代表一张图片,输出D(x)代表x为真实图片的概率,如果为1,就代表100%是真实的图片,而输出为0,就代表不可能是真实的图片
训练过程中,生成网络G的目标就是尽量生成真实的图片去欺骗判别网络D。而D的目标就是尽量辨别出G生成的假图像和真实的图像。这样,G和D构成了一个动态的“博弈过程”,最终的平衡点即纳什均衡点.
2. GAN的特点:
● 相比较传统的模型,他存在两个不同的网络,而不是单一的网络,并且训练方式采用的是对抗训练方式
● GAN中G的梯度更新信息来自判别器D,而不是来自数据样本
3. GAN 的优点:
(以下部分摘自ian goodfellow 在Quora的问答)
● GAN是一种生成式模型,相比较其他生成模型(玻尔兹曼机和GSNs)只用到了反向传播,而不需要复杂的马尔科夫链
● 相比其他所有模型, GAN可以产生更加清晰,真实的样本
● GAN采用的是一种无监督的学习方式训练,可以被广泛用在无监督学习和半监督学习领域
● 相比于变分自编码器, GANs没有引入任何决定性偏置( deterministic bias),变分方法引入决定性偏置,因为他们优化对数似然的下界,而不是似然度本身,这看起来导致了VAEs生成的实例比GANs更模糊
● 相比VAE, GANs没有变分下界,如果鉴别器训练良好,那么生成器可以完美的学习到训练样本的分布.换句话说,GANs是渐进一致的,但是VAE是有偏差的
● GAN应用到一些场景上,比如图片风格迁移,超分辨率,图像补全,去噪,避免了损失函数设计的困难,不管三七二十一,只要有一个的基准,直接上判别器,剩下的就交给对抗训练了。
4. GAN的缺点:
● 训练GAN需要达到纳什均衡,有时候可以用梯度下降法做到,有时候做不到.我们还没有找到很好的达到纳什均衡的方法,所以训练GAN相比VAE或者PixelRNN是不稳定的,但我认为在实践中它还是比训练玻尔兹曼机稳定的多
● GAN不适合处理离散形式的数据,比如文本
● GAN存在训练不稳定、梯度消失、模式崩溃的问题(目前已解决)
模式崩溃(model collapse)原因
一般出现在GAN训练不稳定的时候,具体表现为生成出来的结果非常差,但是即使加长训练时间后也无法得到很好的改善。
具体原因可以解释如下:GAN采用的是对抗训练的方式,G的梯度更新来自D,所以G生成的好不好,得看D怎么说。具体就是G生成一个样本,交给D去评判,D会输出生成的假样本是真样本的概率(0-1),相当于告诉G生成的样本有多大的真实性,G就会根据这个反馈不断改善自己,提高D输出的概率值。但是如果某一次G生成的样本可能并不是很真实,但是D给出了正确的评价,或者是G生成的结果中一些特征得到了D的认可,这时候G就会认为我输出的正确的,那么接下来我就这样输出肯定D还会给出比较高的评价,实际上G生成的并不怎么样,但是他们两个就这样自我欺骗下去了,导致最终生成结果缺失一些信息,特征不全。
关于梯度消失的问题可以参考郑华滨的令人拍案叫绝的wassertein GAN,里面给出了详细的解释,不过多重复。
原始GAN中判别器要最小化如下损失函数,尽可能把真实样本分为正例,生成样本分为负例:
(公式1 )
其中是真实样本分布,是由生成器产生的样本分布。对于生成器,Goodfellow一开始提出来一个损失函数,后来又提出了一个改进的损失函数,分别是
(公式2)
(公式3)
为什么GAN不适合处理文本数据
1. 文本数据相比较图片数据来说是离散的,因为对于文本来说,通常需要将一个词映射为一个高维的向量,最终预测的输出是一个one-hot向量,假设softmax的输出是(0.2, 0.3, 0.1,0.2,0.15,0.05)那么变为onehot是(0,1,0,0,0,0),如果softmax输出是(0.2, 0.25, 0.2, 0.1,0.15,0.1 ),one-hot仍然是(0, 1, 0, 0, 0, 0),所以对于生成器来说,G输出了不同的结果但是D给出了同样的判别结果,并不能将梯度更新信息很好的传递到G中去,所以D最终输出的判别没有意义。
2. 另外就是GAN的损失函数是JS散度,JS散度不适合衡量不想交分布之间的距离。
(WGAN虽然使用wassertein距离代替了JS散度,但是在生成文本上能力还是有限,GAN在生成文本上的应用有seq-GAN,和强化学习结合的产物)
训练GAN的一些技巧
1. 输入规范化到(-1,1)之间,最后一层的激活函数使用tanh(BEGAN除外)
2. 使用wassertein GAN的损失函数,
3. 如果有标签数据的话,尽量使用标签,也有人提出使用反转标签效果很好,另外使用标签平滑,单边标签平滑或者双边标签平滑
4. 使用mini-batch norm, 如果不用batch norm 可以使用instance norm 或者weight norm
5. 避免使用RELU和pooling层,减少稀疏梯度的可能性,可以使用leakrelu激活函数
6. 优化器尽量选择ADAM,学习率不要设置太大,初始1e-4可以参考,另外可以随着训练进行不断缩小学习率,
7. 给D的网络层增加高斯噪声,相当于是一种正则
【Paper】 :
http://arxiv.org/abs/1511.06434
【github】 :
https://github.com/Newmu/dcgan_code theano
https://github.com/carpedm20/DCGAN-tensorflow tensorflow
https://github.com/jacobgil/keras-dcgan keras
https://github.com/soumith/dcgan.torch torch
DCGAN是继GAN之后比较好的改进,其主要的改进主要是在网络结构上,到目前为止,DCGAN的网络结构还是被广泛的使用,DCGAN极大的提升了GAN训练的稳定性以及生成结果质量。
论文的主要贡献是:
◆ 为GAN的训练提供了一个很好的网络拓扑结构。
◆ 表明生成的特征具有向量的计算特性。
DCGAN的生成器网络结构如上图所示,相较原始的GAN,DCGAN几乎完全使用了卷积层代替全链接层,判别器几乎是和生成器对称的,从上图中我们可以看到,整个网络没有pooling层和上采样层的存在,实际上是使用了带步长(fractional-strided)的卷积代替了上采样,以增加训练的稳定性。
DCGAN能改进GAN训练稳定的原因主要有:
◆ 使用步长卷积代替上采样层,卷积在提取图像特征上具有很好的作用,并且使用卷积代替全连接层。
◆ 生成器G和判别器D中几乎每一层都使用batchnorm层,将特征层的输出归一化到一起,加速了训练,提升了训练的稳定性。(生成器的最后一层和判别器的第一层不加batchnorm)
◆ 在判别器中使用leakrelu激活函数,而不是RELU,防止梯度稀疏,生成器中仍然采用relu,但是输出层采用tanh
◆ 使用adam优化器训练,并且学习率最好是0.0002,(我也试过其他学习率,不得不说0.0002是表现最好的了)
主要改进总结:
1.将pooling层用convolutions替代。(对于判别模型,允许网络学习自己的空间下采样;対于生成模型,允许它学习自己的空间上采样)
2.在generator和discriminator上都使用batchnorm:
解决初始化差的问题
帮助梯度传播到每一层
防止generator把所有的样本都收敛到同一个点
3.在CNN中移除全连接层
4.在generator的除了输出层外的所有层使用ReLU,输出层采用tanh
5.在discriminator的所有层上使用LeakyReLU.
问题:
DCGAN虽然有很好的架构,但是对GAN训练稳定性来说是治标不治本,没有从根本上解决问题,而且训练的时候仍需要小心的平衡G,D的训练进程,往往是训练一个多次,训练另一个一次。
【paper】:
https://arxiv.org/abs/1701.07875
【GitHub】:
https://github.com/hwalsuklee/tensorflow-generative-model-collections
https://github.com/Zardinality/WGAN-tensorflow
与DCGAN不同,WGAN主要从损失函数的角度对GAN做了改进,损失函数改进之后的WGAN即使在全链接层上也能得到很好的表现结果,WGAN对GAN的改进主要有:
◆ 判别器最后一层去掉sigmoid
◆ 生成器和判别器的loss不取log
◆ 对更新后的权重强制截断到一定范围内,比如[-0.01,0.01],以满足论文中提到的lipschitz连续性条件。
◆ 论文中也推荐使用SGD, RMSprop等优化器,不要基于使用动量的优化算法,比如adam,但是就我目前来说,训练GAN时,我还是adam用的多一些。
从上面看来,WGAN好像在代码上很好实现,基本上在原始GAN的代码上不用更改什么,但是它的作用是巨大的
◆ WGAN理论上给出了GAN训练不稳定的原因,即交叉熵(JS散度)不适合衡量具有不相交部分的分布之间的距离,转而使用wassertein距离去衡量生成数据分布和真实数据分布之间的距离,理论上解决了训练不稳定的问题。
◆ 解决了模式崩溃的(collapse mode)问题,生成结果多样性更丰富。
◆ 对GAN的训练提供了一个指标,此指标数值越小,表示GAN训练的越差,反之越好。可以说之前训练GAN完全就和买彩票一样,训练好了算你中奖,没中奖也不要气馁,多买几注吧。
有关GAN和WGAN的解释,可以参考链接:https://zhuanlan.zhihu.com/p/25071913
总的来说,GAN中交叉熵(JS散度)不适合衡量生成数据分布和真实数据分布的距离,如果通过优化JS散度训练GAN会导致找不到正确的优化目标,所以,WGAN提出使用wassertein距离作为优化方式训练GAN,但是数学上和真正代码实现上还是有区别的,使用Wasserteion距离需要满足很强的连续性条件—lipschitz连续性,为了满足这个条件,作者使用了将权重限制到一个范围的方式强制满足lipschitz连续性,但是这也造成了隐患,接下来会详细说。另外说实话,虽然理论证明很漂亮,但是实际上训练起来,以及生成结果并没有期待的那么好。
注:Lipschitz限制是在样本空间中,要求判别器函数D(x)梯度值不大于一个有限的常数K,通过权重值限制的方式保证了权重参数的有界性,间接限制了其梯度信息。
【paper】:
https://arxiv.org/abs/1704.00028
【GitHub】:
https://link.zhihu.com/?target=https%3A//github.com/igul222/improved_wgan_training
https://github.com/caogang/wgan-gp
WGAN-GP是WGAN之后的改进版,主要还是改进了连续性限制的条件,因为,作者也发现将权重剪切到一定范围之后,比如剪切到[-0.01,+0.01]后,发生了这样的情况,如下图左边表示。
发现大多数的权重都在-0.01 和0.01上,这就意味了网络的大部分权重只有两个可能数,对于深度神经网络来说不能充分发挥深度神经网络的拟合能力,简直是极大的浪费。并且,也发现强制剪切权重容易导致梯度消失或者梯度爆炸,梯度消失很好理解,就是权重得不到更新信息,梯度爆炸就是更新过猛了,权重每次更新都变化很大,很容易导致训练不稳定。梯度消失与梯度爆炸原因均在于剪切范围的选择,选择过小的话会导致梯度消失,如果设得稍微大了一点,每经过一层网络,梯度变大一点点,多层之后就会发生梯度爆炸 。为了解决这个问题,并且找一个合适的方式满足lipschitz连续性条件,作者提出了使用梯度惩罚(gradient penalty)的方式以满足此连续性条件,其结果如上图右边所示。
梯度惩罚就是既然Lipschitz限制是要求判别器的梯度不超过K,那么可以通过建立一个损失函数来满足这个要求,即先求出判别器的梯度d(D(x)),然后建立与K之间的二范数就可以实现一个简单的损失函数设计。但是注意到D的梯度的数值空间是整个样本空间,对于图片(既包含了真实数据集也包含了生成出的图片集)这样的数据集来说,维度及其高,显然是及其不适合的计算的。作者提出没必要对整个数据集(真的和生成的)做采样,只要从每一批次的样本中采样就可以了,比如可以产生一个随机数,在生成数据和真实数据上做一个插值
于是就算解决了在整个样本空间上采样的麻烦。
所以WGAN-GP的贡献是:
◆ 提出了一种新的lipschitz连续性限制手法—梯度惩罚,解决了训练梯度消失梯度爆炸的问题。
◆ 比标准WGAN拥有更快的收敛速度,并能生成更高质量的样本
◆ 提供稳定的GAN训练方式,几乎不需要怎么调参,成功训练多种针对图片生成和语言模型的GAN架构
但是论文提出,由于是对每个batch中的每一个样本都做了梯度惩罚(随机数的维度是(batchsize,1)),因此判别器中不能使用batch norm,但是可以使用其他的normalization方法,比如Layer Normalization、Weight Normalization和Instance Normalization,论文中使用了Layer Normalization,weight normalization效果也是可以的。为了比较,还是给出了下面这张图,可以发现WGAN-GP完爆其他GAN:
最小二乘GAN
全称是Least Squares Generative Adversarial Networks
【paper】
https://arxiv.org/abs/1611.04076
【github】
https://github.com/hwalsuklee/tensorflow-generative-model-collections
https://github.com/guojunq/lsgan
LSGAN原理:
其实原理部分可以一句话概括,即使用了最小二乘损失函数代替了GAN的损失函数。
但是就这样的改变,缓解了GAN训练不稳定和生成图像质量差多样性不足的问题。
事实上,作者认为使用JS散度并不能拉近真实分布和生成分布之间的距离,使用最小二乘可以将图像的分布尽可能的接近决策边界,其损失函数定义如下:
其中作者设置a=c=1,b=0
论文里还是给了一些数学推导与证明,感兴趣的可以去看看
生成结果展示:
BEGAN全称是Boundary Equilibrium GANs
【paper】:
https://arxiv.org/abs/1703.10717
【GitHub】:
https://github.com/carpedm20/BEGAN-tensorflow
https://github.com/Heumi/BEGAN-tensorflow
https://github.com/carpedm20/BEGAN-pytorch
BEGAN的主要贡献:
◆ 提出了一种新的简单强大GAN,使用标准的训练方式,不加训练trick也能很快且稳定的收敛
◆ 对于GAN中G,D的能力的平衡提出了一种均衡的概念(GAN的理论基础就是goodfellow理论上证明了GAN均衡点的存在,但是一直没有一个准确的衡量指标说明GAN的均衡程度)
◆ 提出了一种收敛程度的估计,这个机制只在WGAN中出现过。作者在论文中也提到,他们的灵感来自于WGAN,在此之前只有wgan做到了
◆ 提供了一个超参数,这个超参数可以在图像的多样性和生成质量之间做均衡(熟悉GAN的小伙伴就知道这又多难得)
先说说BEGAN的主要原理,BEGAN和其他GAN不一样,这里的D使用的是auto-encoder结构,就是下面这种,D的输入是图片,输出是经过编码解码后的图片,
为了估计分布的误差,作者使用了auto-encoder作为D,D的输入是图像V,维度为RNx,输出的也是维度为RNx的图片,本文中n=1,自编码器的模型如下
,
之前的GAN以及其变种都是希望生成器生成的数据分布尽可能的接近真实数据的分布,当生成数据分布等同于真实数据分布时,我们就确定生成器G经过训练可以生成和真实数据分布相同的样本,即获得了生成足以以假乱真数据的能力,所以从这一点出发,研究者们设计了各种损失函数去令G的生成数据分布尽可能接近真实数据分布。BEGAN代替了这种估计概率分布方法,它不直接去估计生成分布Pg与真实分布Px的差距,进而设计合理的损失函数拉近他们之间的距离,而是估计分布的误差之间的距离,作者认为只要分布的的误差分布相近的话,也可以认为这些分布是相近的。即如果我们认为两个人非常相似,又发现这两人中的第二个人和第三个人很相似,那么我们就完全可以说第一个人和第三个人长的很像。
在BEGAN中,第一个人相当于训练的数据x,第二个人相当于D对x编码解码后的图像D(x),第三个人相当于D以G的生成为输入的结果D(g(z)),所以,如果||D(x)-x|| - || D(x)- D(g(z)) || 不断趋近于0,那么随着训练,D(x)会不断接近x,那么D(g(z)) 接近于D(x),岂不是就意味着 g(z) 的数据分布和x分布几乎一样了,那么就说明G学到了生成数据的能力。于是乎,假设图片足够大,像素很多。但是问题来了,如果||D(x)-x|| - || D(x)- D(g(z)) ||刚好等于0,这时候,D(x)和x可能还差的很远呢,那不就什么也学不到了D(x)-x是一个图片,假设图片上的每一个像素都满足独立同分布条件,根据中心极限定理,像素的误差近似满足正太分布,假设期望是m1,方差是μ1,同理D(x)- D(g(z)),还有m2, μ2这时候如果我们再用wassertein距离衡量m1与m2的距离,
trace是求迹操作。
再满足下面这个条件下,
即他们成正比,这时候连lipschitz连续性条件也不需要了,
令D不断的最大化m2,最小化m1,而G则不断最小化m2,当m2 接近m1的时候我们就认为GAN完成了训练。
分析到这里我们得出结论,我们可以去估计误差的分布而不是直接估计分布去拟合GAN,但是损失函数究竟是怎么样的呢?
有一个问题,当m1和m2很接近是,条件1是趋于无穷的,不可能再忽略,于是,boundary(限制)就来了,
设置一个位于[0~1]之间的数λ,强制将m1和m2划分开界限,具体的损失函数如下:
BEGAN的训练结果:不同的γ可以在图片的质量和生成多样性之间做选择。
SRGAN (Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network, arxiv, 21 Nov, 2016)将生成式对抗网络(GAN)用于SR问题。其出发点是传统的方法一般处理的是较小的放大倍数,当图像的放大倍数在4以上时,很容易使得到的结果显得过于平滑,而缺少一些细节上的真实感。因此SRGAN使用GAN来生成图像中的细节。
传统的方法使用的代价函数一般是最小均方差(MSE),即
该代价函数使重建结果有较高的信噪比,但是缺少了高频信息,出现过度平滑的纹理。SRGAN认为,应当使重建的高分辨率图像与真实的高分辨率图像无论是低层次的像素值上,还是高层次的抽象特征上,和整体概念和风格上,都应当接近。整体概念和风格如何来评估呢?可以使用一个判别器,判断一副高分辨率图像是由算法生成的还是真实的。如果一个判别器无法区分出来,那么由算法生成的图像就达到了以假乱真的效果。
因此,该文章将代价函数改进为
第一部分是基于内容的代价函数,第二部分是基于对抗学习的代价函数。基于内容的代价函数除了上述像素空间的最小均方差以外,又包含了一个基于特征空间的最小均方差,该特征是利用VGG网络提取的图像高层次特征: 对抗学习的代价函数是基于判别器输出的概率: 其中 是一个图像属于真实的高分辨率图像的概率。 是重建的高分辨率图像。SRGAN使用的生成式网络和判别式网络分别如下: 该方法的实验结果如下 从定量评价结果上来看,PSNR和SSIM这两个指标评价的是重建结果和金标准在像素值空间的差异。SRGAN得到的评价值不是最高。但是对于MOS(mean opinion score)的评价显示,SRGAN生成的高分辨率图像看起来更真实。这里直介绍了一些对GAN在训练和生成上改进的工作,具体还有很多很多很多很多没有介绍到,这里只是挑选了一些典型的,用的比较多的来介绍一下。感兴趣的可以去看看https://github.com/hindupuravinash/the-gan-zoo
GAN动物园,上百个GAN等着被翻牌。
Google研究原文请见:https://arxiv.org/abs/1711.10337
在此项研究中,Google此项研究中使用了minimax损失函数和用non-saturating损失函数的GAN,分别简称为MM GAN和NS GAN,对比了WGAN、WGAN GP、LS GAN、DRAGAN、BEGAN,除了DRAGAN上文都做了介绍,另外还对比的有VAE(变分自编码器)。
虽然得出的结论是没有明显的证据说明其他GAN比原始GAN好,但是,有本事你用原始GAN生成一个2K的高清图给我看看,此时BEGAN和PG-GAN相视一笑,默默不说话。大部分情况来说,还是wgan-gp用的更多一些。生成高清图像BEGAN最简单合适。
1.https://zhuanlan.zhihu.com/p/27159510?utm_source=wechat_session&utm_medium=social
2. https://www.zhihu.com/question/56171002/answer/148593584
3. http://www.inference.vc/instance-noise-a-trick-for-stabilising-gan-training/
4. https://github.com/soumith/ganhacks
5. https://github.com/hindupuravinash/the-gan-zoo
6. https://zhuanlan.zhihu.com/p/25071913
7. https://zhuanlan.zhihu.com/p/25071913
8.https://zhuanlan.zhihu.com/p/25532538?utm_medium=social&utm_source=weibo