本博文主要讲解和总结生成对抗神经网络,也即是耳熟能详的GAN神经网络原理,将从数学层面详细的进行总结和分析。
我们可以这样理解上图:首先随机初始化第一代的 generator v1 ,利用 generator v1 生成的 sample 作为负样本,真实的 sample 作为正样本,训练出第一代的 Discriminator v1 ,这里可以将所有的 Discriminator 视为 Binary classifier ,这样第一代的分类器就能辨别出第一代的生成器所生成的样本;随之我们可以由第一代的分类器,使得 generator v1 能够演化成 generator v2 ,也就是第二代的生成器,第二代生成器生成的样本能够够顺利的骗过 Discriminator v1 ,也就是 Discriminator v1 可能会将 generator v2 生成的sample错误的判别为正类,由此我们再以 generator v2 生成的sample作为负样本,真实样本作为正样本,再训练出第二代的分类器 Discriminator v2 ;由此一直进行下去,我们可以不断的迭代更新分类器,生成器。
上面简单的总结了下整个的 learn 的过程,这里稍微详细的讲下 Discriminator 是如何 learn 的。
初代生成器 generator v1 通过 Randomly sample a vector 生成一些样本标记为0,将 real sample 标记为1,由此构建出了正负样本数据集,可以训练出第一代的生成器 Discriminator v1 ,以后每代的生成器都是如此 learn 出来的。
那么 generator 具体是如何 learn 迭代更新的呢?
第一代的生成器 generator v1 生成的样本,肯定比较 fake ,与真实样本差距较大,那么第一代的 Discriminator v1 就会 output 出一个比较低的分数来反映该生成样本的真实程度,接下来要做的就是 update generator v1 的参数,得到第二代 generator v2 ,这个新的生成器产生的样本要很 realistic ,就是要能骗过第一代生成器,那么该 generator v2 是如何 learn 生成呢?
上面只是大致的讲了下其原理,下面将从数学层面详细的进行总结分析。
我们可以从 Pdata(x) 中随机 sample 出几个样本 {x1,x2,...,xm} ,假定 θ 已经给定,那么我们可以计算出上面 sample 出的 xi 在生成样本集中的机率。
那么我们可以有最大似然函数得到从 Pdata(x) 中随机 sample 出的这几个样本 {x1,x2,...,xm} 在生成样本集中的概率:
这里需要稍微讲下 KL 散度相关知识。
相对熵,又称KL散度( Kullback–Leibler divergence),是描述两个概率分布P和Q差异的一种方法。它是非对称的,这意味着D(P||Q) ≠ D(Q||P)。特别的,在信息论中,D(P||Q)表示当用概率分布Q来拟合真实分布P时,产生的信息损耗,其中P表示真实分布,Q表示P的拟合分布,相对熵越小表示拟合的越好。
设 P(X) 和 Q(X) 是 X 取值的两个离散概率分布,则 P(X) 对 Q(X) 的相对熵为:
在最开始时,大家把 Gaussian Mixture Model 当做 PG(x;θ) ,可能由于模型过于简单,或者又是 Gaussian Mixture Model 与 Pdata(x) 差太多,没有办法真正的模拟 Pdata(x) ,生成的样本与真实样本差距太大。
那么 PG(x;θ) 可以很复杂,所以现在广泛用 nerual network 当做 PG(x;θ) , θ 就是 nerual network 的参数。理论上说单隐层神经网络可以逼近任何连续函数。但是因为 nerual network 很复杂,所以对从 Pdata(x) 中随机 sample 出几个样本 {x1,x2,...,xm} ,比较难的求出其概率,则 difficult to compute the likelihood 。
那么问题来了,怎么样更新G的参数,使其能拟合 Pdata(x) 呢?
那么 D 是如何检测 G 与 Pdata(x) ,定义一个函数 V(G,D) ,
那么 V 是如何定义呢?
在给定 G 时, maxV(G,D) 可以表示 PG 和 PD 之间的差异程度(原因看下面),那么要找出 D∗ ,使得 V(G,D) 最大:
继续推导:
由此可见,求得的 D∗ 能衡量 Pdata 与 PG 相似程度。再将 D∗ 代入到 V 中得:
需要注意的是KL散度是非对称的,这里需要介绍下 Jensen−Shannon divergence (对称性):
由此可见, maxV(D,G) 可以表示 PG和PD之间的差异程度,在求得 D∗ 和 V(G,D∗) 后,剩下的问题就是求 G∗ 了。
也就是求下式:
我们可以 user gradient descent 求 G∗ :
求出 D∗1 ,使得 V(G0,D) 最大。
V(G0,D) is the JS divergence between PG and Pdata
在给定 D∗1 情况下,求 θG←θG−η ∂V(G,D∗1) ,求得 G1
这一步需要注意:在固定 D∗ 时,在 use gradient descent 更新 G 时,其V不一定在减小啊,甚至可能会比之前的 V(G0,D) 还要大?
上图中,横坐标表示 D ,纵坐标表示 V ,故在 update G 时,步伐不能太大。
在给定 G1 情况下,求得 D∗1 ,使得 V(G1,D) 最大
我们需要 Maximize 上面的 V ,由此上式可以转变成求:
上式中的 xi 是从 Pdata 中 sample 出来的; x˜i 是从 PG 中 sample 出来的。
可以将 D 看着一个二分类器,那么 xi 是从 Pdata 中 sample 出来的,为正类样本; x˜i 是从 PG 中 sample 出来的,为负类样本。也即是:
那么其损失函数为:
注意下: L 为损失函数,其两项之前应有负号。
需要注意:在 learn D 时,需要 train 多次,就是训练多个 epoch ,而在 learn G 时,只需要一次。