一点 GAN -之一:简述
记录一点学到的无用知识
[TOC]
一些直觉
What I cannot create, I do not understand. - Richard Feynman
费曼的这句话可谓脍炙人口,而且,不像大多数名人口中说出的名言一样,它相当有道理。学数学的时候,我常有这样的体会。就算你把整本书背过,如果你并不能完完整整地把每个定理的证明,庖丁解牛成直径一厘米的牛肉粒,then eventually your learn nothing 。
这句话的逆否命题显然有相当多的佐证:你了解四则运算法则,理解语法树,所以可以写出程序来 parse 一个算式,进而「创造」一个计算器;你知道🐰兔子的样子,所以你可以纸上勾勒出一只兔子,不管是躺着的还是坐着的,荷兰兔还是垂耳兔,只要你想画一只兔子,那么画出来的都是兔子。
那么,你的知识里关于兔子的那一部分是什么呢?
没准可以看做是一个函数。
你可以想象成,你是一个「兔子」生成器,而你生成的兔子显然不是一成不变的,因为几乎所有事都可能影响你在下笔时从尾巴或耳朵开始着笔—如果借用计算机的术语,你接受的一切影响在你的内部形成了一个「熵池」,这个「熵池」为你的创作源源不断地提供随机因素—譬如下笔的位置,你想画的兔子种类,是否在吃胡萝卜…这个「熵池」对你的影响,显然是一个概率分布,经过你(一个兔子生成函数)的变换,变成了你生成的兔子的概率分布。
这还没完,大家都会画兔子,但是你们会画皮卡丘吗?
一般人会做的事情:照着教程或者凭空想象->试着画几笔->发现不像->google pikachu->对着皮卡丘改动自己的画->就这样吧
总结下来,就是根据真实的样本,不断修改自己的画作,同时修正脑海中的记忆(参数),直到自己画的皮卡丘看起来跟真的差不多为止。
That‘s basically what GAN ( Generative Adverserial Network ) does.
注意,以上的类比绝不准确,任何类比都不准确。但这可能为那些想知道 GAN 在做什么,而又不想看数学的人一个直觉,即:GAN 在用一个 parameterized distribution 逼近真实样本的分布。
一些架构
GAN 通常分为两个部分,generator ( denoted as $G$ ) , discriminator (denoted as $D$ ) 。
其中 $G$ 的作用就是通过接收一个 ramdom noise ( often denoted as $z$ ), 来生成一个样本的概率分布 $G(z;\psi)$,其中 $\psi$ 是 $G$ 的参数。$G$ 通常是一个 deconvolution net, 例如 DCGAN 里的 generator 。
而 $D$ 的作用则是一个二分类器,可能的实现有:MLP (vanilla version) ;一个 CNN extractor ,后接一个 sigmoid ;或者一个 autoencoder+重建损失 (in EBGAN, we will reach it later) 。$D$ 的作用是区别 $G$ 生成的样本与真实样本。我们用 $D(x)$ 代表这个二分类器输出的 $x$ 为正例(真实样本)的概率。
理论上来说,GAN 的训练分两步就够了:
- 为了用 $G$ 近似真实样本的概率分布,我们首先应该用真实样本和生成样本训练D,以期得到一个可以完美分类真实样本和生成样本的分类器。假设我们训练得到了这个分类器,那么此时D(x)就是x是正例的概率。通过训练,我们实际上得到了$P(c|X)$, 其中c为类别(正例或负例), X为可能的样本。
- 为了得到$P(X|c=1)$ , 继续训练 $G$ 来最小化$E_{z∼p_z(z)}(1-P(c=1\mid G(z)))$ 。如果训练完美, 那么此时$G(z), z∼some\ distribution$ 就是$P(X|c=1)$
在最初 Ian et all 的 Generative Adversarial Nets 里,把 GAN 形容为一个 minimax game (极大极小博弈),按照这种说法,GAN 要做的就是下面的这个任务:
这其实就是以上的两步训练过程,内层的最大化就是第一步,做的其实是最小化 $D(X)$ 与 $P(c|X)$ 的 cross entropy loss。外层的最小化就是第二步, 做的是在最小化 $E_{z∼p_z(z)}(1-P(c=1\mid G(z;\psi)))$ 。
以上的训练过程看起来很清晰,我们只需要两步就能得到真实数据的分布,但现实中却并非如此。
第一,我们的 generator 并不是一个真正的「生成样本」的分布,通常我们的用作 generator 的模型的 capacity 都是有限的,它很大可能只是生成了所谓「生成样本流形」中一个子流形。所以如果我们用这样的 generator 生成的样本和真实样本去训练 $D$ ,是不可能得到真正的 $P(c|X)$ 的,直觉上而言,因为这样的 discriminator 只能把一个子流形与真实样本模型分开,所以这个 discriminator 可能太「松」。
第二,$D$ 的 capacity 也有限。
所以,在现实中,我们没法用两步优化就得到真实样本的概率分布。Ian et all 在论文里提出了一种交替优化的方法解决这个问题。
这个算法其实就是:用 SGD ,先对做 k 步 equation (1) 内部最大化,再做外部的最小化。论文证明了这个算法在模型的 capacity 足够强,$D$ 每次优化都达到最优的时候,$G$ 学习到的概率分布收敛于真实分布。
证明的具体过程在 Ian et all 的论文里写的很详细,这里不表。但这个证明中间还说明了一件事:如果训练中 $D$ 达到最优的话,那么 equation (1) 外部的 loss function (也是内部的最优化结果)就是 $p_{data}$ 和 $p_g$ 的 Jensen–Shannon divergence 的一个线性函数:
$C(G) = -log(4)+2 · JSD \left (p_{data}\middle| p_g \right) $
而 JSD 非负,且当且仅当在 $p_{data}$ 和 $p_g$ 相等时为0,所以此时这个 minimax game 达到最优。
注意,这时得到的 $C(G)$ ,也即外部最小化的 loss function ,是关于 $G$ 的,对于不同的 $G$ 优化同一个 loss function 是无意义的,这也是我们交替进行最大化与最小化的目的:最大化得到当前 $G$ 对应的最好的 loss function ,然后最小化这个 loss function 得到更好的 $G$ 。
一点直觉: 关于 GAN 最有名的说法应该是「两个玩家进行博弈以期达到纳什均衡」,这或许是 “A” — adverserial 的来源。你尽可以这样想,也尽可以将以上的训练过程与一些直觉 里的例子进行类比—尽管他们不准确,但这多有趣:一个玩家完善他的伪装,另个玩家根据偶尔现形的他的行踪,升级自己的侦查系统;伪装者又根据试探、猜测和潜入,涂画他的伪装以对抗新型的侦察系统…模型可以很有趣,只要我们不看数学(误)。
关于参数更新
在原论文中,作者提到了 equation (1) 在训练式的 gradient vanishing 问题:
当训练刚开始时候,$D(G(z))$ 很小,这时候 $log(1-D(G(z)))$ 趋向饱和,而 $logD(G(z))$ 的导数却很可观,所以与其最小化 $log(1-D(G(z)))$ 不如最大化 $logD(G(z))$ 。
Vanilla 版本的参数更新:
$θ_{t+1}←θ_t-\epsilon_{t}\frac{\partial}{\partial\theta}𝔼_{z∼N}log(1-D(G(z;θ_t);ψ_{t+1}))$
第二种参数更新方法:
$θ_{t+1}←θ_t+\epsilon_{t}\frac{\partial}{\partial\theta}𝔼_{z∼N}log(D(G(z;θ_t);ψ_{t+1}))$
其中 $\theta_{t}$ 为 t 时刻的 $G$ 的参数,$\psi_t$ 为 t 时刻的 $D$ 的参数,$\epsilon_t$ 为 t 时刻的学习率
在 Ferenc Huszár 的 blog 里,提出了第三种参数更新方法,就是将两种更新的 $\Delta_{t}$ 相加:
这样就避免了两端可能的 saturate 问题。而且 Ferenc 证明了,相对于第一种更新(在最小化 JSD),新的 $\Delta_t$ 其实在最小化 KLD。KLD 与 JSD 有一些相同的性质,比如非负和当且仅当两个分布相同时才为 0 ,所以新的 loss function 也是有意义的。
另外,如果 $D$ 最后有一个 sigmoid 层输出概率的话,新的 loss function 其实是 score ,就是 sigmoid 层之前的输出,所以采用新的参数更新方法,还可以避免 sigmoid 的计算(我想是微不足道的)。
EBGAN (energy-based view GAN)
Legun 的实验室九月放出了一篇论文:EBGAN ,即 energy-based GAN ,意在从 energy 的角度来阐述 GAN 。图为它的 architecture:
EBGAN 的 $D$ 是一个 auto encoder ,其中 auto encoder 的误差就是所谓的 energy ,可以通过 Gibbs distribution 转化成概率分布。$D$ 的 loss function 如下:
$[·]^+$ 为 $max(·, 0)$
其中的直觉是,训练这个 auto encoder 使其输出的能量函数对于两种样本有一个距离 ,这样的 loss function 有很多,上面的 margin loss 只是其中的一种,直观上讲,训练它等同于将能量在 [0, m] 中的不同类别的样本往不同的方向推,最小化真实样本的 energy 直到 0,最大化生成样本的 energy 直到 m,以此起到 「分辨」 两种样本的作用。
我不知道为什么用 auto encoder 来拟合这个能量函数,可能是因为对于某个分布来说,能量低的地方,样本就多一点,对于这些地方的样本的重建误差就少一点( still not sure )。
因为 energy 可以通过 Gibbs distribution 转换成概率分布,所以 energy-based view 可以跟 probabilistic view 联系起来。如果用 energy 的观点来看 vanilla GAN 的话,那么原来的 loss function 的 margin 就是 $\inf$ ,它倾向于把真实样本的 energy 「推」到 $-\infty$ ,把生成样本的 energy 「推」到 $+\infty$ ,作者认为,这样的 margin 太松了,其实只要有一定的margin, $D$ 的作用就够了。
关于 EBGAN ,Ferenc 将其他 GAN 的 energy 观点与其比较,认为 EBGAN 从本质上来说,并不比其他 GAN 更 energy-based ,同时他也不清楚 auto encoder 在这里起到了什么作用,而且作者并没有证明为什么拟合 $D$ 的 loss function 正好使得 $D$ 的输出是 energy。文章在这。
值得一提的是,EBGAN 这篇论文提出了一个训练 $G$ 时的正则项,目的是为了让生成的样本更加多样化,直觉很简单,就是把一个 batch 里的所有样本通过 encoder 后得到的 code,取一个两两的 cos ,再取平均。这样当这个正则化项达到最小时,其实就是这些样本的 code 在 encoding space 最接近两两垂直的时候。这个正则化项长这样:
Repelling Regularizer
顾名思义,batch 内的图片将会互相排斥,直到相互垂直。
Info-GAN (to be supplemented)
在 GAN 里,我们可以把一些服从一定先验的 latent code 转化成一张图片,一段音频 ,但这些 latent code 都是毫无意义的(至少在人类看来),那能不能通过某种训练,使得这些 latent code 有某种我们可以理解的意义? Info-GAN 就做了这样的工作,它把一开始的 latent code 分为两部分,一部分满足一定先验,与 vanilla GAN 的latent code 相同,记为 $z$ ,另一部分就是我们想要的表示,记为 $c$ 。
那么问题又来了,如果用原来的训练方法,GAN 完全可以学到跟 $c$ 毫无关系的分布,那么这时候把 latent code 分为两部分就毫无意义了。另一方面, GAN 是无监督的,如果有 label ,我们可能可以优化 $G$ ,使得 $c$ 正好代表样本的某个属性,比如,3D 人脸图片中的角度。但我们现在没有 label ,我们所能够做的,只有想办法让这些图片的属性在不同的 $c$ 下尽量区别开来,最好是 $c$ 的每个分量代表某种属性,当这个分量变化时,生成样本的属性也会随之连续变化。用文章中的话讲,就是让 $c$ 的各个分量 distangled with each other 。至于这样会学出什么属性,在训练前其实完全糊涂,但如果训练得当,$c$ 的某个分量一定会学到最显著的那个维度,我觉得这取决于你给的样本的丰富度。
Info-GAN 是从信息角度考虑的,如果 $c$ 真的是这个样本的一个理想的表示,那么从 $c$ 就可以得到样本,从样本也可以得到 $c$ ,换句话说,这两者之间拥有完全可逆的函数关系,这个时候 $c$ 与 $G(c, z;\psi)$ 之间的信息就是完全一样的(这当然是不可能的,因为 $z$ 也要起作用),换句话讲,此时 $I(c, G(c, z;\psi))$ 达到最大值。反过来,如果 $c$ 与 $G(c, z;\psi)$ 之间完全没有关系,那么此时 $I(c, G(c, z;\psi))$ 达到最小值 0 。所以这就给了我们一个直觉,只要最大化 这两者之间的互信息,就能得到与 $c$ 密切相关的生成样本。Info-GAN 将这个互信息作为正则项添加到了原来的 loss function 中:
那我们只需要一种可以计算 $I(c, G(c, z;\psi))$ 的途径就行了,这并不简单,因为我们需要计算 $P(c|X)$ ,而它是没法直接计算出来的,所以我们需要用 $Q(c|X)$ 来代替它,以获得 $I(c, G(c, z;\psi))$ 的一个下界:
但内部的 expection 还是需要从 $P(c|X)$ sample 点,所以直接用个 total exception theorem ,就可以变成如下形式:
而 $Q(c|x)$ 是可以通过 $D$ 再加上一个 softmax layer 来拟合的,所以我们可以直接对新的 $V_I$ 进行优化。因为我们只对 $D$ 上加了一个 softmax layer ,所以这个正则项几乎是 cost-free 的。
Info-GAN 的效果如下:
Ferenc 的 blog 里也对 Info-GAN 做了一个 mini-review ,而且他将 vanilla GAN 也用最小化互信息的角度阐释了一遍。事实上,可以把传入 $D$ 的是否是真样本看做一个伯努利分布,并且也看做 $c$ 的一部分,记为 $t$ ,这时 $G$ 可以看做是原来的 generator 和真实样本的 sampler 之和 $G’$,当 $t$ 为 1 时就传入真实样本,$t$ 为 0 时就传入生成样本,这样通过最小化 $D$ 传出的 $I(x, t)$ 就可以达到与 vanilla GAN 相同的效果。注意在 Info-GAN 里我们是在最大化 $c$ 与 $X$ 的互信息,因为我们想得到一个和 $c$ 更相关的 $X$ ,但在 vanilla GAN 里我们想让 $G’$ 与 $t$ 更无关,所以要最小化互信息。这种观点下的 loss function 其实也可以写成 $I(t, X)-\lambda I(c, G(z, \psi))$ 。详情也可见 李映真 的 blog 。
Feeling Lucky
GAN 发展太快了,自从 Ian et all 2014 年发布第一篇 GAN 论文开始,有非常多相关研究业已面世,这次介绍的 EBGAN 和 Info-GAN 只是最近的代表。关于 GAN 的训练(如 DCGAN),阐释,和应用层出不穷。因为 GAN 可以看做是提供了一种 non-trivial 的优化目标,所以作为生成模型应用可以很广泛,比如 音乐生成 ,文本生成,Style-Structure GAN ,SRGAN 。因为 GAN 受计算能力限制,生成高分辨率的图像很难( EBGAN 可以生成 256 x 256 的图片),所以有人提出可以生成一些低分辨率的图像进行合成以得到高分辨率图片,这就是 Deep Generative Image Models using a Laplacian Pyramid of Adversarial Networks 的方法。
先这样吧。