当前位置: 首页 > 科技观察

开发者自述:我就是这样学习GAN的

时间:2023-03-16 13:58:05 科技观察

GenerativeAdversarialNetwork的,也就是大家熟悉的GAN。它首先由伊恩·古德费罗(IanGoodfellow)提出。近两年,它已经成为深度学习中最热门的东西。似乎一切都可以由GAN控制。做吧。最近刚开始接触GAN,看了一些资料,做了一些笔记。1.世代什么是世代?即模型学习一些数据,然后生成相似的数据。让机器看一些动物的图片,然后自己生成动物的图片,就是生成。过去有很多技术可以用来生成,比如自动编码器(self-encoder),结构如下:你训练一个编码器,将输入转换成代码,然后训练一个解码器,将编码成图像,然后计算图像和输入之间的MSE(均方误差)。模型训练好后,取出NNDecoder的后半部分,输入一个随机码生成图像。但是auto-encoder生成的图像效果,当然看起来很别扭,一看就知道是真的。所以后来提出了VAE这样的生成模型。我对此了解不多,这里就不多说了。上面提到的生成模型其实有一个非常严重的缺点。比如VAE,它生成的图像希望尽可能和输入相似,但是模型是怎么衡量这种相似度的呢?该模型将计算损失,主要使用MSE,即每个像素的均方误差。小损失真的意味着相似吗?比如这两张图片,第一张,我们认为是生成好的图片,第二张是生成不好的图片,但是对于上面的模型来说,这两张图片计算出来的loss是一样的,所以Willthink是和图片一样好。这是上述生成模型的缺点。用于衡量生成图像质量的标准不能很好地达到预期目的。于是就有了下面要讨论的GAN。2.著名的GAN之GAN是如何生成图片的?首先大家知道GAN有两个网络,一个是生成器,一个是判别器。受到两人零和博弈的启发,两个网络相互对抗,以达到最佳的生成效果。流程如下:主要流程与上图类似。首先有一代的生成器,可以生成一些较差的图片,然后有一代的判别器,可以对生成的图片和真实图片进行准确的分类。简而言之,这个判别器是一个二进制分类输出,0代表生成图像,1代表真实图像。然后,开始训练二代生成器,它可以生成稍微好一点的图片,并且可以让第一代判别器认为这些生成的图片是真实的图片。然后训练一个二代判别器,可以准确识别真实图片和二代生成器生成的图片。以此类推,还会有三代、四代。..n代的生成器和判别器,***判别器无法区分生成图片和真实图片,拟合这个网络。这就是GAN,运行起来就这么简单。这就是结局?显然不是,下面就来介绍一下GAN的原理。3.原理首先我们知道真实图片集的分布Pdata(x),x是一张真实的图片,可以想象成一个向量,这个向量集的分布就是Pdata。我们需要生成一些也在这个分布中的图片。如果直接在这个发行版里面,恐怕就不行了。我们现在有的生成器生成的分布可以假设为PG(x;θ),这是一个受θ控制的分布,θ是这个分布的参数(如果是高斯混合模型,那么θ就是每个高斯分布和方差的平均值)假设我们在真实分布中取一些数据,{x1,x2,...,xm},我们想计算一个似然PG(xi;θ)。对于这些数据,生成模型中的似然就是我们要最大化这个似然,相当于让生成器生成那些真实图片的概率**。这就变成了最优似然估计的问题,我们需要找到一个θ*来最大化这个似然。找到一个θ*来最大化这种可能性等同于优化对数似然。因为此时这m个数据取自真实分布,所以在PG分布中近似等于真实分布中所有x的对数似然的期望。对实数分布中所有x的期望等价于计算概率积分,所以可以转化为积分运算,因为减号后面的项与θ无关,所以加上后等价。然后提出commonitems,括号中的求逆,max变成min,可以转化为KL散度的形式。KL散度描述了两个概率分布之间的差异。所以最大化似然,让生成器以最大的概率生成真实的图片,也就是找到一个θ让PG更接近Pdata。那么如何找到最合理的θ呢?我们可以假设PG(x;θ)是一个神经网络。首先随机生成一个向量z,通过G(z)=x网络生成一张图片x。那我们怎么比较两个分布是否相似呢?只要我们取一组样本z,这组z符合一个分布,那么就可以通过网络生成另一个分布PG,然后与真实分布Pdata进行比较。大家都知道,神经网络只要有非线性激活函数,就可以拟合任何函数,分布也是一样的,所以可以用正态分布或者高斯分布来采样来训练神经网络,学习一个很复杂分布。如何找到更接近的分布,这就是GAN的贡献。先给出GAN的公式:这个公式的好处是,当G固定时,maxV(G,D)代表PG和Pdata的差值,然后我们需要找到一个最优的G,使得最优值最小,即两个分布之间的差异最小。从表面上看,这意味着D应该使这个公式尽可能大,即对于x是一个真实的分布,D(x)应该接近1,而对于x来自一个生成的分布,D(x)应该接近于0,那么G应该使公式尽可能小,并且让生成分布中的x,D(x)尽可能接近1。现在我们先固定G,求解最好的D:对于给定的x,得到最好的D,如上图所示,范围在(0,1)内,将最好的D带入其中,得到:JSdivergenceisKL散度的对称平滑版本,表示两个分布之间的差异。这个推导显示了上面提到的固定G。表示两个分布之间的差异,最小值为-2log2,最大值为0。现在我们需要找到一个G来最小化上面的观察。当PG(x)=Pdata(x)时,G最好。4.训练有了上面推导的基础,我们就可以开始训练GAN了。结合我们一开始说的,两个网络是交替训练的。我们可以一开始有一个G0和D0,先训练D0找到:然后固定D0开始训练G0,训练过程可以使用梯度下降,以此类推,训练D1,G1,D2,G2,...但是这里有个问题,你可能会在D0*的位置得到:然后updateG0到G1,是可以的,但是不保证会出现一个新的点D1*使得这个updateG没有达到原来的效果,如下图所示:避免出现上述情况的方法是在更新G的时候不要对G更新太多。知道了网络的训练顺序,我们还需要设置两个损失函数,一个是D的损失,另一个是G的损失。下面是整个GAN训练的具体步骤:以上步骤在机器学习和深度学习中也很常见,也很容易理解。5.存在的问题但是上面G的损失函数还有一个小问题。下图是两个函数的图像:log(1-D(x))是我们计算时G的损失函数,但是我们发现在D(x)接近0的时候,函数很平滑而且梯度很小。这会导致,在训练的初期,G想欺骗D,而且变化很慢,而且上面的函数和下面的函数趋势一样,都是递减的。但它的优点是当D(x)接近0时,梯度很大,有利于训练。D(x)越来越大后,梯度下降,也很符合实际。在早期,训练速度要快一些。快,以后慢。所以我们修改G的损失函数来提高训练速度。还有一个问题,在其他论文中提出过。通过实验发现经过多次训练,loss一直是平坦的,即JS散度一直是log2,PG和Pdata根本没有交集,但实际上两个分布是有交集的.这样做的原因是我们无法真正计算出期望值和积分,所以只能用sample的方法。如果训练过拟合,D仍然可以完全分离两部分点,如下图:对于这道题,我们是不是应该让D变弱,弱化它的分类能力,但是理论上来说,为了让它能够有效的区分真假图片,我们希望它强大,所以这里就产生了矛盾。另一个可能的原因是,虽然两个分布是高维的,但是两个分布很窄,交集可能相当小,这也会导致JS散度计算=log2,近似等于没有交集。一些解决方案包括加入噪声,使两个分布变宽,可以增加它们的交集,这样就可以计算JS散度,但是随着时间的变化,噪声需要逐渐变小。还有一个问题叫做ModeCollapse,如下图所示:这个图的意思是数据的分布是双峰的,但是学习到的生成分布只是单峰的。我们可以看到模型学习到的数据,但不知道它没有学习到的分布。造成这种情况的原因是KL散度中的两个分布是相反的。这个图清楚的表明,如果写第一个KL散度,为了防止无穷大,出现Pdata的地方一定要写。有了PG覆盖,就不会出现ModeCollapse。6.参考这些是GAN入门学习的一些笔记和理解。后来实在懒得敲公式了。我主要参考了李鸿毅老师的视频:http://t.cn/RKXQOV0本文转自雷锋网,本文作者马少南,原发表于作者知乎专栏。