生成对抗网络-改进方法|深度学习(李宏毅)(二十四)

视频地址:
①B站:https://www.bilibili.com/video/BV15W411i7uP?p=2
②油管:https://www.youtube.com/watch?v=KSN4QYgAtao

之前的博客地址:
①生成对抗网络-基本概念|深度学习(李宏毅)(二十二)
②生成对抗网络-理论部分|深度学习(李宏毅)(二十三)

一、GAN的通用框架

  1. f-divergence

之前说GAN的Discriminator的设计与JS散度有关,事实上可以设计Discriminator和任何f-divergence有关。f-divergence的定义如下:

f-divergence衡量分布和之间的差异程度,满足在和完全一致的情况下取得最小值为,在有所差异的情况下值为一个正数,这一点可以通过凸函数的性质得到:

和完全一致时:

和有差异时:

事实上KL散度就是f-divergence的一个特例:






  1. Fenchel Conjugate

每一个凸函数都有一个共轭函数(Conjugate Function),记作,公式为:

这个函数也就是说要找出给定的情况下变动能达到的最大值,限制必须要在的定义域内,以下图为例,给定不同的,代入所有的能得到的最大值就是:

共轭

按照上面的方式能够理解前面的公式。那么的图像是什么样子的呢?我们可以按照以下方式来考虑,在给定,使变动,那么就能得到一条以为斜率的直线,对于不同的就对应着不同的直线:

共轭

而此时,要求,就只需要从的位置坐垂线,这样与垂线相交最上面的直线对应的就是能使得取得最大值的:

共轭

那么在整个的定义域上,将位于最上面的直线的片段连接起来就是的图像了,当然这只是便于理解的一种形象化的思路:

共轭

按照上面的思路,可以很直观地看出也是凸函数。

另外,我们按照上面的方式把有关的共轭函数的每条直线都画出来:

f(x)=xlogx

得到的共轭函数的图像像是一个指数函数,其实的共轭函数就是,求解共轭函数可以直接用数学的方法计算出来,对于来说,先把代入前面共轭函数的表达式:

对于括号里面的式子,给定,需要求解来使最大化,可以直接对求导,也就有,然后解得,也就是说,对于给定的,能使得最大的就是,将代入原来的式子就可以求得共轭函数了:

另外(在满足是闭凸函数的条件下,这里就不深究了)有是的共轭函数,也是的共轭函数,也就是说:

是互为共轭函数:

这叫做二次共轭。

  1. 上述内容与GAN的联系

由上面二次共轭的内容,那么对于f-divergence中的凸函数,就可以用来替换它:

现在对于任意的一个,它的输入是,输出是,将代入上面的式子中,一定有以下关系:

上面的不等式是恒成立的,我们也就得到了的下界,来调整函数使得这个下界取得最大值就可以用这个最大值来近似:

如此我们就得到了的关于和的期望的形式,也就是说我们现在可以通过从和中采样来完成的求解。在GAN中分布也就是,分布也就是,因此也就有:

能使得和的最小的也就是最优化的Generator,我们按照以下公式求解Generator:

G^{*}=\underset{G}{argmin}\; D_{f}(P_{data}||P_{G})\\ =\underset{G}{argmin}\; \underset{D}{max}\left \{E_{x\sim P_{data}}[D(x)]-E_{x\sim P_{G}}[f^{*}(D(x))]\right \}\\ =\underset{G}{argmin}\; \underset{D}{max}\; V(G,D)

这样也就回到了我们之前讲过的GAN的目标函数,我们之前说过GAN不一定要极小化JS散度,也可以定义不同的来极小化其他散度,而上面的式子的价值就在于提供了一种定义的方法,即事实上GAN可以用任何f-divergence来作为衡量和的差异的度量,求得这种f-divergence的函数的共轭函数就可以得到目标函数。

在模型能力较差时使用不同的散度可能会有不同的效果,下面展示了使用KL散度和JS散度来拟合数据的效果:

效果对比

图中显示KL散度更倾向于产生多样化的数据,JS散度的分布则比较狭窄,GAN有时会产生比较狭窄的数据,也就是mode collapse,根据上图可以尝试使用KL散度(但事实上也没什么效果)。

参考链接:https://arxiv.org/abs/1606.00709

  1. Single-step Algorithm

在原来讲过的GAN的训练算法中,我们的做法是在每次迭代中先更新Discriminator的参数多次,然后更新Generator的参数一次,这相当于在一个外循环中嵌套了一个内循环。在f-GAN提出了Single-step的训练算法,也就是在每次迭代中Discriminator和Generator的参数只更新一次,并且是在一次反向传播中更新:

\theta _{D}^{t+1}\leftarrow \theta _{D}^{t}+\eta \nabla_{\theta _{D}}V(\theta _{G}^{t},\theta _{D}^{t})\\ \theta _{G}^{t+1}\leftarrow \theta _{G}^{t}-\eta \nabla_{\theta _{G}}V(\theta _{G}^{t},\theta _{D}^{t})

二、Wasserstein GAN

  1. Wasserstein Distance

Wasserstein GAN是一个GAN的变种,在WGAN中度量分布差异程度的标准不再是各种散度,而是wasserstein distance,也叫earth mover's distance。把两个分布比作两堆土,将其中一堆铲成另一堆土所需移动的土的最小平均距离就是wasserstein distance。举例来说,在下图中的一维空间中,两个分布都集中在一个点上,距离为,将移动到上的wasserstein distance就是:

example

更具体的,如下图,对于两个分布和,现在要将移动到,存在多种方案,不同的方案就会有不同的距离:

多种方案

不过总是会存在最优的方案,这个最优方案对应的平均移动距离就是wasserstein distance:

最优方案

可以将每一种移动的方案(每一种方案记作)表示成一个矩阵的形式,这个矩阵上每一个元素代表从的位置移动到的位置的土的量,这里有两个约束就是矩阵中每一行的和等于对应的位置的概率,每一列的和等于对应的位置的概率:

moving plan

以表示从的位置移动到的位置的土的量,那么一个方案对应的平均移动距离就是:

假设移动方案的取值空间是,那么wasserstein distance就是穷举所有的方案,其中最小距离的方案对应的距离:

仍然使用演化的例子,可以说明wasserstein distance为什么比JS散度更加优越,在下面的例子中,期待一步步训练最终能够与重合,使用JS散度对于中间状态来说其值就全部是,这样就缺乏促使像好的方向演化的“动力”,而使用wasserstein distance对于中间状态来说就能得到不一样的值:

演化
  1. 目标函数

在原来的GAN中,可以使用下列式子来定义和之间的f-divergence:

在WGAN中也有类似的式子来定义和之间的wasserstein distance:

这个式子中不是任意的,而是一个1-Lipschitz函数,Lipschitz函数的定义如下:

上面的式子中表明的变化小于倍的的变化,这样的限制说明Lipschitz函数是一种变化不剧烈的函数,在时就是1-Lipschitz函数。比如下面图中的两个函数,绿色的就是1-Lipschitz函数,而蓝色的不是:

1-Lipschitz函数

现在说明一下为什么要有这个限制呢。还是以一维的分布为例,在下图中的和之间的距离为。如果没有1-Lipschitz函数的限制,为了让公式中大括号内的式子最大,只需要:

无1-Lipschitz限制

而如果有1-Lipschitz函数的限制的话,那么为了让公式中大括号内的式子最大,只能取得:

有1-Lipschitz限制

另外一个角度解释wasserstein distance的优势就是,如下图,原来的GAN中会有一个sigmoid函数,可能最终得到的的图像就像下图蓝色的线,有一个明显的问题就是有概率存在的地方是没有梯度的,也就是梯度消失问题,这样就没办法让有“动力”移动到,而对于加了1-Lipschitz限制的wasserstein distance,则可能会得到绿色的线,这样就会有一个梯度来促使有“动力”移动到:

梯度
  1. 算法

我们想要求解一个1-Lipschitz函数,来让公式中大括号内的式子最大,但是如果直接微分来做的话就不满足1-Lipschitz函数的限制,在实际中的做法是使用weight clipping的做法,也就是强制Discriminator的参数在和之间:

After parameter update, if ,then ; if , then .

Weight clipping的做法并不能保证满足是1-Lipschitz函数的限制,但是可以保证是K-Lipschitz,不过并没有关系,因为按照这样的方法求解出来的最大值是与wasserstein distance成正比的:

如果不做weight clipping的话还是会使得没有限制,会产生下图中的后果,而如果做了weight clipping就会使有一定限制,从而可以使有一定的梯度来促使有“动力”移动到:

weight clipping

不过要注意的是,使用weight clipping以后只能保证满足K-Lipschitz的限制,而不能保证所有满足K-Lipschitz的限制的对应参数都在和之间,也就是说不满足在和之间的某些参数也是有可能满足K-Lipschitz的。有关weight clipping的方法就不再深究,因为后面会介绍更加合适的训练方法。

WGAN训练的算法与原来的GAN的训练有很多相似之处,只需要做一点改动即可:

Initialize:
  初始化的参数和的参数。


Step1 学习:
  ①从数据库中随机抽样个样本;
  ②从一个分布(比如高斯分布或者均匀分布)中采样个噪声样本(noise sample);
  ③获得生成的数据,其中;
  ④目标函数记作,通过最大化(梯度上升)来更新,也就是,目标函数为:

  ⑤


Step2 学习:
  ①同样从一个分布(比如高斯分布或者均匀分布)中采样个噪声样本(noise sample);
  ②目标函数同样记作,通过最小化(梯度下降)来更新,也就是,目标函数为:

同样地每次迭代中Step1重复多次,Step2重复一次,不同的是WGAN的不会在最后一层加一个sigmoid函数了。

  1. 其他issue

这里对比了WGAN和原来的GAN的效果的对比图,可以看到WGAN生成的效果是明显要好一些的:

效果对比

还有另一点要说的是在WGAN中Discriminator的loss是可以用来衡量和之间的差异的,这是因为Discriminator的loss代表的是wasserstein distance,而原来的GAN的Discriminator的loss是不可以用来衡量分布之间的差异的(原因之前说过了:1.采样;2.数据是高维空间中的低维流形)。这里放一些效果图,在下面的图中可以看出随着wasserstein distance(也就是Discriminator的loss)的下降,生成的效果是越来越好的:

效果

这一点的意义就在于以前我们没有一个衡量的标准来说明一个Generator生成的对象好还是不好(虽然图像好坏可以肉眼大概评估一下,但是一些其他的对象可能就很难衡量了),但是现在我们可以通过Discriminator的loss表示的wasserstein distance来作为一个评估的手段了。

WGAN论文链接:https://arxiv.org/abs/1701.07875

三、Improved WGAN

  1. Gradient Penalty

对于1-Lipschitz函数,存在以下等价关系:

也就是说满足1-Lipschitz的对的梯度总是小于等于的,受这一点的启发,我们可以修改WGAN的目标函数如下:

上面的式子在时会产生loss,调节的大小可以使得对的梯度尽可能地小于等于。使用这种损失函数就可以舍弃weight clipping的做法,不再需要对做限制也可以学习到一个能够尽可能满足1-Lipschitz的限制的。

在实际操作中我们不可能对所有进行积分,因此我们要改写上面的惩罚项为一个依某种惩罚分布的期望,这样就可以使用采样的方式来计算了:

直觉上这个应该是个均匀分布,但事实上在Improved WGAN的论文中对有特殊的设计。具体的,得到一个采样样本的过程如下图所示,首先从抽取一个点,然后从抽取另一个点,然后连接起来得到一条线,线段的中间就是采样点:

penalty分布

原论文中解释这样的分布的用意在于,如果我们想要让所有的都满足1-Lipschitz,这是intractable的,如果只让这和之间的满足1-Lipschitz的话是可以实现的而且是比较合理的,因为这个区域内的点影响如何移向,并且实验中取得不错的效果。

另外实际上论文中使用的损失函数也不是上面那一个,而是下面这个:

也就是说在实践中并非要让尽可能地小,而是要让和之间区域的对的梯度,尽可能地接近。这样的做法在直观上是很容易解释的,由损失函数可以看出我们期待要让分布中的的尽可能大,而要让分布中的的尽可能小,那么中间区域的对的梯度就越大越好,同时又要是小于等于的,因此最终解出来的最优的对的梯度总是倾向于:

梯度接近1

仅仅惩罚大梯度也是可以work的,不过上面的方式在实验中收敛地更快且效果更好。

  1. 对比实验

下面的图对比了weight clipping和gradient penalty中的权重的分布,发现weight clipping的权重大多集中在clipping的位置:

对比

下面的图对比了使用weight clipping和gradient penalty去拟合黄点数据分布的效果,明显gradient penalty效果好一些:

对比

下面的图对比了不同GAN的效果,发现Improved WGAN的效果是最好的:

对比
对比
  1. 文本生成

将句子按照独热编码的方式表示成一个矩阵就可以用来做句子的生成,由于句子长短不一,可以添加一个使用一个null的token来填补空白位置:

句子的表示

对于GAN产生的句子,其中很难产生,而是对于一个词来说一般都是一个大的数,伴随一些接近于的数,导致生成的数据和真实的数据是没有重叠的,因而使用传统的GAN的话,量出来的JS散度永远都是,而WGAN就可以解决这个问题,使用wasserstein distance来度量差异的话就是比较合理的:

问题

下面展示一些文本生成的结果:

文本生成

还可以用来做唐诗的生成:

文本生成

Improved WGAN的论文链接:https://arxiv.org/abs/1704.00028

你可能感兴趣的:(生成对抗网络-改进方法|深度学习(李宏毅)(二十四))