前言
在生成对抗网络(Generative Adversarial Network,简称 GAN)发明之前,变分自编码器(VAE)被认为是理论完备,实现简单,使用神经网络训练起来很稳定,生成的图片逼近度也较高,但是人眼还是可以很轻易地分辨出真实图片与机器生成的图片。但在2014年GAN被提出之后,在之后的几年里面里迅速发展,生成的图片越来越逼真。
1 GAN
1.1 相关介绍
GAN模型的核心思想就是博弈思想,是生成器(造假者)和判别器(鉴别者)之间的博弈,在提出GAN的原始论文中,作者举了货币制造的例子。即像一台验钞机和一台制造假币的机器之间的博弈,两者不断博弈,博弈的结果假币越来越像真币,直到验钞机无法识别一张货币是假币还是真币为止。
1.2 原理
1.2.1 网络架构
生成对抗网络包含了两个子网络:生成网络(Generator,简称 G)和判别网络(Discriminator,简称 D),其中生成网络 G 负责学习样本的真实分布,判别网络 D 负责将生成网络采样的样本与真实样本区分开来。
生成网络G(𝒛) :生成网络 G 和自编码器的 Decoder 功能类似,从先验分布$p_z$(∙)采样获得潜在空间点向量,经过网络生成图片样本$\bar{x}$~$𝑝_𝑔(x|z)$。
生成器的网络($𝑝_𝑔(x|z)$)可以由深度神经网络来参数化,如:卷积网络和转置卷积网络。下图中从均匀分布$𝑝𝒛$(∙)中采样出隐藏变量$z$,经过多层转置卷积层网络参数化的$𝑝_𝑔(x|z)$分布中采样出样本$x_f$,从输入输出层面来看,生成器 G 的功能是将隐向量𝒛通过神经网络转换为样本向量$x_f$,下标𝑓代表假样本(Fake samples)。
判别网络D(𝒙):判别网络和普通的二分类网络功能类似,网络的输入数据集由采样自真实数据分布$p_𝑟$(∙)的样本$x_𝑟$ ~ $𝑝_𝑟$(∙)和采样自生成网络的假样本$x_𝑓$ ~ $𝑝_𝑔(x|z)$组成。判别网络输出为$x$属于真实样本的概率𝑃($x$为真|$x$),我们把所有真实样本$x_r$的标签标注为真(1),所有生成网络产生的样本,所有生成网络产生的样本$x_f$标注为假(0),通过最小化判别网络 D 的预测值与标签之间的误差来优化判别网络参数。
1.2.2 网络训练
GAN 博弈学习的思想体现在在它的训练方式上,由于生成器 G 和判别器 D 的优化目标不一样,不能和之前的网络模型的训练一样,只采用一个损失函数。所以我们要分别对生成器和判别器进行训练。
判别网络D(𝒙):它的目标是能够很好地分辨出真样本$x_r$与假样本$x_f$。则其损失函数既要考虑识别真图像能力,又要考虑识别假图像能力,而不能只考虑一方面,故判别器的损失函数为两者的和。因此 D 的分类问题是二分类问题,以图片生成来说,交叉熵损失函数定义为:
因此判别网络 D 的优化目标是:
将最小化转成最大化的问题并写成期望的形式:
具体代码如下:D表示判别器、G为生成器、real_labels、fake_labels分别表示真图像标签、假图像标签。images是真图像,z是从潜在空间随机采样的向量,通过生成器得到假图像。
1 | # 定义判断器对真图像的损失函数 |
生成网络G(𝒛) :我们希望$x_f$ = 𝐺(𝒛)能够很好地骗过判别网络 D,假样本$x_f$在判别网络的输出越接近真实的标签越好。也就是说,在训练生成网络时,希望判别网络的输出𝐷(𝐺(𝒛))越逼近 1 越好,最小化𝐷(𝐺(𝒛))与 1 之间的交叉熵损失函数:
将最小化转成最大化的问题并写成期望的形式:
等价成:
其中𝜙为生成网络 G 的参数集,可以利用梯度下降算法来优化参数𝜙。具体代码如下:
1 | z = torch.randn(batch_size, latent_size).to(device) |
通过对生成器和判别器的损失函数的求解,GAN的架构如下:
算法流程为:
1.3 用GAN生成图像
本次实验为了方便,我使用的是 MNIST 手写数字数据集,下面进行每部分的代码实现。
1.3.1 判别器
定义判别器网络结构,这里使用LeakyReLU为激活函数,输出一个节点 并经过Sigmoid后输出,用于真假二分类。
1 | class Discriminator(nn.Module) : |
1.3.2 生成器
生成器与AVE的生成器类似,不同的地方是输出为nn.tanh,使用nn.tanh 将使数据分布在[-1,1]之间。其输入是潜在空间的向量z,输出维度与真图像相同。
1 | class Generator(nn.Module) : |
1.3.3 训练模型
1 | for epoch in range(MAX_EPOCH) : |
效果,分别展示epoch为1、100、200时生成的图片,其中当epoch为200时噪声就已经很少了,但是对数字的分布结构并不能很好的描述出来。
2 GAN变种
2.1 CGAN
AVE和GAN都能基于潜在空间的随机向量z生成新图片,GAN生成的图 像比AVE的更清晰,质量更好些。不过它们生成的都是随机的,无法预先控制你要生成的哪类或哪个数。我们希望 生成某个数字,生成某个主题或类别的图像,实现按需生成的目的,这样的应用应该非常广泛。CGAN正是针对这类问题而提出的。
2.1.1 原理
在GAN这种完全无监督的方式加上一个标签或一点监督信息,使整个网络就可看成半监督模型。其基本架构与GAN类似,只要添加一个条件y即可,y就是加入的监督信息,比如说MNIST数据集可以提供某个数字的标签 信息,人脸生成可以提供性别、是否微笑、年龄等信息,带某个主题的图像 等标签信息。
对生成器输入一个从潜在空间随机采样的一个向量z及一个条件y,生成 一个符合该条件的图像G(z/y)。对判别器来说,输入一张图像x和条件y,输 出该图像在该条件下的概率D(x/y)。
2.1.2 PyTorch实现
CGAN实现采用的数据集依然是 MNIST 手写数字数据集,其实现过程与原始的GAN的相差不大,主要差异时是标注信息的添加。
1 | import torch |
利用网格(10×10)的形式显示指定条件下生成的图像:
可视化指定单个数字条件下生成的数字:
可视化生成器和判别器损失值如下 :
由上图可知,CGAN的训练过程不像一般神经网络的过程,它是判别 器和生成器互相竞争的过程,最后两者达成一个平衡。
2.2 DCGAN
在前面中无论是原始的GAN还是CGAN我们建立的网络都是基于全连接网络构建的,这样的网络由于图片的维度较高,网络参数量巨大,不能很好地学习到图片地特征,导致训练效果不佳。DCGAN提出了使用转置卷积层实现的生成网络,普通卷积层来实现的判别网络,大大地降低了网络参数量,同时图片的生成效果也大幅提升,展现了 GAN 模型在图片生成效果上超越 VAE 模型的潜质。注:虽然使用卷积网络会大大降低参数量,但是所需要的样本数要更多一些。
2.3 CycleGAN
CycleGAN 是一种无监督方式,主要用于图片风格相互转换的。CycleGAN 基本的思想是,如果由图片 A 转换到图片 B,再从图片 B 转换到A′,那么A′应该和 A 是同一张图片。因此除了设立标准的 GAN 损失项外,CycleGAN 还增设了循环一致性损失(Cycle Consistency Loss),来保证A′尽可能与 A 逼近。
2.4 WGAN
GAN 的训练问题一直被诟病,很容易出现训练不收敛和模式崩塌的现象。WGAN 从理论层面分析了原始的 GAN 使用 JS 散度存在的缺陷,并提出了可以使用 Wasserstein 距 离来解决这个问题。在 WGAN-GP 中,作者提出了通过添加梯度惩罚项,从工程层面很好的实现了 WGAN 算法,并且实验性证实了 WGAN 训练稳定的优点。
3 训练GAN的技巧
- 批量加载和批规范化,有利于提升训练过程中博弈的稳定性。
- 使用tanh激活函数作为生成器最后一层,将图像数据规范在-1和1之间,一般不用sigmoid。
- 选用Leaky ReLU作为生成器和判别器的激活函数,有利于改善梯度的稀疏性,稀疏的梯度会妨碍GAN的训练。
- 使用卷积层时,考虑卷积核的大小能被步幅整除,否则,可能导致生成的图像中存在棋盘状伪影。
全部代码可以参考此处
参考
- 《Python深度学习基于PyTorch》
- 《TensorFlow深度学习》