Tensorflow 对抗生成网络GAN 不服就GAN

61 篇文章 6 订阅
39 篇文章 2 订阅

这一节的回顾也意味着深度学习基础课程学习进入了尾声了,GAN作为性能远超我们上一节提到的VAE的一个存在还是有很多出彩的地方的:

首先引用理查德费曼的一句话-'What I cannot create, I do not understand"

作为模型训练的目标就是毕竟模拟出这样一个分布P(x)。

那么P(x)这个分布究竟是怎么样的呢?看下一张图:

那么问题来怎么学习这样的分布呢,接下来我们以一个画家的成长作为举例:

一开始画家小时候画的蒙娜丽莎和达芬奇的蒙娜丽莎相去甚远,他的哥哥觉得这个8行

学习了5年后,画家画的蒙娜丽莎好一些了,但是哥哥也长大了对画作的鉴赏能力也提升了,所以依然8行

学习了10年后,画家也成长为了一个大学生了,他的哥哥张一山哈哈一看就是个很有品位的人,这个时候画家的蒙娜丽莎已经和达芬奇的很相似了,但是他的哥哥张一山发现了一个很明显的问题,弟弟的蒙娜丽莎这个体重肯定不对。

时间又过了很久,这个时候画家的蒙娜丽莎已经让达芬奇本人都难辨真假了,只有0.5的概率判断正确也就是几乎和原画一模一样了只能是个随机事件有0.5的概率。那么此时就达到了纳什均衡,画家也算是真是出山了。

好继续回到我们的GAN,其实GAN核心本质就是一个鉴画师和画家的一个博弈过程,通过画家的不断努力和鉴画师的不断学习鉴赏两者都希望能够自己最后胜利,画家希望自己的画能以假乱真,而鉴画师则希望自己能够每一次鉴别都是正确的从而竞争的关系由此产生。

好的问题来了怎么去训练呢,这里面就有两个目标函数,一个是painter 一个是 discriminator:

这是个多目标优化问题,画家的Gnerator在Loss函数中希望最小化,而鉴赏师与之相反,接下来看看具体公式是怎么样的。

我们假定两个阶段,一阶段是先不让鉴赏师进行学习,只让画家充分的去学习来满足函数目标,二阶段就是让画家的训练停滞不前然后去使得鉴画师Discriminator达到最优化。大致可以通过图片描绘成如下过程

那么通过上图A-》D的过程,已经让画家的水平和临摹的画作几乎一模一样也就是分布几乎完全一致了,那么接下来就要对鉴画师Discriminator进行训练了。

我们这里Dg的优化目标就是对画家作品和真迹鉴赏时的一个准确率,那么木白哦函数就是希望他能够尽可能的大,与之相反之前的那个画家就是希望鉴赏师能够尽可能小这个值。那么求和的过程是离散的,这里用积分表示的就是一个期望的计算过程,可以看到概率乘以函数,也就是分布概率乘以这个优化目标函数取对数,为什么取对数我估计是为了方便求导梯度下降。通过推导可以知道,纳什均衡实现的条件就是A=B就是Pr分布和Pg分布完全一样的时候取到max=0.5,OK回顾完这些,我们不得不提的一个就是我们对比的VAE在loss中使用的KL散度和GAN中使用的JS散度,为啥使用JS散度那肯定有他的奥妙。

KL散度这里不再赘述,我们看下JS散度,它本质上是对调了P和Q分布然后进行加和,弥补了不关于原点对称的问题,这样一来就可以对调p,q而不影响结果计算。那么像KL散度一样进行推导之后我们可以得到我们JS散度得计算式如下图所示:

好的这里我们就是介绍了GAN的一个思路,然后这个使用JS散度的就是著名的也是早在2015就提出的DCGAN模型,但是时至今日GAN已经是发展的如火如荼,改进提出的GAN版本呢也已经把A-Z字母全部用用完了,就是会有诸如AGAN,BGAN之类的。数量之巨达到了接近500种

话说回来还是DCGAN比较有名且是作为目前GAN网络的主要使用的类别,其网络架构的举例如下:

可以看到图中的输入是一个100*1的z分布,通过一种deconvolution逆卷积的过程最后变成了一张图片,那么这个逆卷积过程又可以乘坐Transposed Convolution,怎么求逆卷积ConvTranspose2d(fractionally-strided convolutions)?其操作过程具体如下:

这里我并不想解释理论的推导,我直接说算法怎么实现的。也就是代码中如何实现。

当给一个特征图a, 以及给定的卷积核设置,我们分为三步进行逆卷积操作:
第一步:对输入的特征图a进行一些变换,得到新的特征图a’
第二步:求新的卷积核设置,得到新的卷积核设置,后面都会用右上角加撇点的方式区分
第三步:用新的卷积核在新的特征图上做常规的卷积,得到的结果就是逆卷积的结果,就是我们要求的结果。

以下当然就要解释怎么做了。
在说怎么做之前,我们下规定一下符号,右上角加撇点的为修改之后的:
特征图a: H e i g h t Height Height, W i d t h Width Width
输入的卷积核: kernel 的size = S i z e Size Size, 步长为 S t r i d e Stride Stride,padding 就是 p a d d i n g padding padding。

新的特征图: H e i g h t ′ = H e i g h t + ( S t r i d e − 1 ) ∗ ( H e i g h t − 1 ) Height'=Height+(Stride-1)*(Height-1) Height′=Height+(Stride−1)∗(Height−1), W i d t h Width Width同样的。这里说一下这个新的特征图是怎么得到的:我们在输入的特征图基础加上一些东西,专业名词叫做interpolation,也就是插值。
这就涉及到两个问题,插在哪里,插什么。
插什么?插得就是0。
插在哪里?在原先高度方向的每两个相邻中间插上" S t r i d e − 1 Stride-1 Stride−1"列0。我们知道对于输入为 H e i g h t Height Height的特征图来说有 H e i g h t − 1 Height-1 Height−1个位置,所以,最终我们的特征图在原先的基础上加上 ( S t r i d e − 1 ) ∗ ( H e i g h t − 1 ) (Stride-1)*(Height-1) (Stride−1)∗(Height−1)

新的卷积核: S t r i d e ′ = 1 Stride'=1 Stride′=1,这个数不变,无论你输入是什么。kernel的 s i z e ′ size' size′也不变,= S i z e Size Size, p a d d i n g ′ padding' padding′为 S i z e − p a d d i n g − 1 Size-padding-1 Size−padding−1.

然后,我利用新的卷积核和新的特征图,得到最终的逆卷积结果。
根据公式可以知道输出的特征图(用输入的符号表示)的大小是多少了,下面我给出简单的推导。

先给出公式:
H e i g h t o u t = ( H e i g h t i n + 2 ∗ p a d d i n g − k e r n e l s i z e ) / s t r i d e s + 1 Height_{out}=(Height_{in}+2*padding-kernel_{size})/strides+1 Heightout​=(Heightin​+2∗padding−kernelsize​)/strides+1
这里补充一句,padding的size只是针对一边的,所以要乘以2.

带上上面新的卷积核和新的特征图设置情况,可以得到
( H e i g h t + ( S t r i d e − 1 ) ∗ ( H e i g h t − 1 ) + 2 ∗ ( S i z e − p a d d i n g − 1 ) − S i z e ) / 1 + 1 (Height+(Stride-1)*(Height-1) +2*(Size-padding-1) - Size)/1+1 (Height+(Stride−1)∗(Height−1)+2∗(Size−padding−1)−Size)/1+1
化简可得: ( H e i g h t − 1 ) ∗ S t r i d e − 2 ∗ p a d d i n g + S i z e (Height-1)*Stride-2*padding+Size (Height−1)∗Stride−2∗padding+Size

上面这幅图就是pytorch官网给出的计算方法,和这里给出是一样的。当然这里先忽略output_padding是什么。

有兴趣可以算一下从这个是否满足反向计算的一致性。

最后,这里给一个例子参考,特别是怎么计算到新的特征图的,尤其是怎么插值(interpolation)。
 

对图的说明:
输入特征图A: 3 ∗ 3 3*3 3∗3
输入卷积核K:kernel为 3 ∗ 3 3*3 3∗3, stride为2, padding为1
新的特征图A’: 3 + ( 3 − 1 ) ∗ ( 2 − 1 ) = 3 + 2 = 5 3 + (3-1)*(2-1) = 3+2 = 5 3+(3−1)∗(2−1)=3+2=5 注意加上padding之后才是7。
新的卷积核设置K’: kernel不变,stride为1,padding= 3 − 1 − 1 = 1 3-1-1=1 3−1−1=1
最终结果: ( 5 + 2 − 3 ) / 1 + 1 = 5 (5+2-3)/1+1=5 (5+2−3)/1+1=5
 

接下来了解了新提出的JS散度,我们来看看DCGAN和VAE的实况对比吧:

这里可以看到在真实图像的处理上DCGAN完胜VAE,此时的VAE沦为了一个中间过程。看到这里是不是DCGAN就无敌了无懈可击了呢,其实DCGAN可以说还是存在他的问题的:

在大多数情况下P和Q两个分布是不会过拟合的,因为这两个数据分布是在低维空间中的而manifold学习是在高维空间中的,那么过拟合即使有也可以忽略。但是下面这种情况就不好说了:

如果初始情况下P和Q的分布都是均匀分布,但是两者的均值μ相距甚远,以至于完全没有在分布上有重叠部分,通过代入这个KL和JS散度进行计算我们会发现爱你,KL散度求导趋于无穷大而JS散度的导数始终为log2这样会导致梯度下降更新过程的一个梯度爆炸和梯度弥散现象,导致无法更新逼近最优解。具体的这个描述如下图:


可以看到如果P是μ=0如果q的μ>20此时KL和JS散度导数都会离散化因为对一条几乎平行的线其斜率几乎为0此时梯度下降就不会朝着我们想要的方向更新了,而是原地踏步。

这里一个新的理论就提出了也就是GP原理下面看看其在GAN上的应用于前两者的对比:

我们称在损失函数loss中加入了这样一个GP函数的而不是KL和JS散度得GAN网络为WGAN。那他的巧妙之处在哪里呢,不像前两者的逼近公式,这个GP理论采用的Wasserstein Distance来计算两个分部之间的距离,采取最优的搬砖理论,也就是我们对原来的分布离散成很多柱状图,然后去进行柱状图里边的平移来实现逼近我们的目标分布。最优化的这个目标函数也就是找到了一种最优的搬砖方法。

那么如何计算这个Wasserstein Distance距离呢,我们参看下图:里面引入了利普希茨第一定律作为约束条件,就是我们的这个两个分布之间Wasserstein Distance距离中的斜率小于等于1

将利普希茨条件代入我们的loss函数就可以得到如下表达式,具体推导这里不赘述:

可以从下图的实例中看出该方法比DCGAN在开始的收敛过程中更加稳定,通过学者研究证明WGAN可以经过更少的参数调优也能够实现较好的收敛效果,而DCGAN则非常依赖于参数和网络结构的不断寻优调整。

好的基本的GAN的理论就回顾到这里,接下来是关于GAN的实战!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值