[读论文] Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks

Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks
Alec Radford, Luke Metz, Soumith Chintala
arXiv:1511.06434 [2015]

Intro

之前我们曾经介绍过Generative Adversarial Nets。原作者Goodfellow在那篇文章中提出了一个基本的框架:生成器以一个随机采样的噪声向量作为输入,并输出一张图片。判别器用来判断这张图片是真实世界中的图片,还是由生成器产生的。在这个对抗(Adversarial)训练的过程中,生成器和判别器进行零和博弈并最终收敛。

GAN这个框架有很多优点:收敛、不依赖马尔科夫链、只需要用BP算法计算梯度等。然而这个方法还有很多问题。

首先,这种方法并不能学习到真正的数据分布\(p_g(x)\)。由于其中的生成器和判别器使用了神经网络,所以训练出来的生成模型更像一个黑盒子:给定输入,产生输出。而其中内部机制并不明晰。

除此之外,训练过程并不稳定:训练器的训练过程应该与生成器的训练过程保持同步。特别在判别器没有更新的情况下,绝对不能更新太多次生成器,否则可能会发生“Helvetica Scenario”现象,也就是不论输入的随机采样的噪声向量\(z\)是啥,都会得到同样的生成结果\(x\)。

本篇博客介绍的文章(Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks)就是在GAN的基础之上,引入了一系列约束(constraints),结合CNN(Convolutional Neural Nets)在一定程度上解决了这个问题。并且在后面附带了大量的实验来证实他们提出的这个模型的强大。

首先,本篇论文的作者也认为GAN在训练中非常不稳定:

GANs have been known to be unstable to train. Often resulting in generators that produce nonsensical outputs.

所以这篇文章在增加训练稳定性、提高特征学习能力等方面做了不少工作:

  1. 作者提出了深度卷积GAN (Deep Convolutional GANs, DCGAN),并且在这个架构上增加了一些约束,使得在大多数情况下能够稳定地训练
  2. 作者将训练好的判别器(Discriminator)用来进行图片分类的任务,结果发现效果要比其他无监督的算法要好(可能是由于这种方法判别器能更好地学习到知识的特征表达)。
  3. 作者将模型学习到的filters可视化,发现一些filters学习到了如何去“画”一些特殊的对象(也就是说学习到的filter是合理的靠谱的)。
  4. 作者发现生成器具备了“向量运算”的神奇性质,类似于word embedding可以操纵向量,并且能够按照“语义”生成新内容。

很神奇是不是?下面看看DCGAN的真容

Approach and Model Architecture

对于卷积神经网络部分,作者用上了几个最近被证实有效的对CNN架构的修改。

  1. 把所有的pooling (例如maxpooling)等用"stride"替代。这能让网络学习到自己的空间上的降采样。作者将这个方法用在了生成器(使用stride上采样)和判别器上。
  2. 去掉了卷积特征之后的全连接层。改用global average pooling,这虽然会影响收敛速度但是能增加模型的稳定性。
  3. 使用了Batch Normalization,这能够通过让输入到每一个节点的数据都保持0均值1方差,从而稳定训练,并且能够帮助训练更深层的模型。这个方法非常重要,它能够防止模型永远只能输出相同的样本,也就是上面提到的“Helvetica Scenario”现象。这个现象是GAN在实际使用中遇到的最大的问题。

除此之外,作者在生成器中除了输出层以外,激活函数都是用ReLU,输出层激活函数使用Tanh。这能够让模型在训练中更快地达到饱和并且能对彩色样本有更好的效果。而且,使用leaky rectified activation效果也不错(尤其是对一些高分辨率的图片)。

总结来说,作者给出了一个关于稳定训练的DCGAN的guideline:

  • 将所有的pooling层替换成strided convolution(判别器)和fractional-strided convolution(生成器)。
  • 在生成器和判别器中使用Batch Normalization 。
  • 在更深的架构中删除全连接的隐层。
  • 对于生成器:在输出层使用Tanh激活函数,其余层使用ReLU。
  • 对于判别器:在每一层都是用LeakyReLU。

下面是一张生成器结构的示意图:

Experiment

作者在三个数据集上训练了DCGAN,分别是:Large-scale Scene Understanding(LSUN), Imagenet-1k 和一个比较新的面部数据库。

论文中给出了一组训练参数,对调参有一些指导意义:

  1. 所有模型都使用了batch size=128的梯度下降方法进行训练。
  2. 所有的权值都是用0均值,0.02标准差的正态分布进行初始化
  3. LeakyReLU的斜率值(slope of the leak)都是0.2.
  4. 使用Adam optimizer进行训练。
  5. 作者发现,使用学习率0.001有些高,所以使用了0.0002
  6. Momentum的patient如果是0.9可能会导致训练的波动比较大,所以改成0.5能帮助训练得更稳定一些。

这里有两张DCGAN生成器所生成的图片: 这张图片是当模型训练1个epoch时,生成器产生的结果。

这张图片是当模型训练5个epoch时,生成器产生的结果。

紧接着,作者又用了一些数据来验证DCGAN各方面的能力。

DCGAN作为特征抽取器

首先,作者使用了DCGAN作为特征抽取器,在CIFAR-10的数据上训练了一个分类器。下面是分类精度的结果: 这里需要注意的一点是,为了验证DCGAN能够抽取图片的特征,所以作者使用了Imagenet-1k进行训练,然后使用CIFAR-10进行分类性能测试。从表格中能看出,DCGAN+L2-SVM已经能取得不错的效果了。虽然不如Exemplar CNN,但作者觉得后续还有微调的空间。

然后作者又用相似参数进行了街景房间门牌号数据集(StreetView House Numbers dataset, SVHN)做了测试。使用了DCGAN的判别器中抽取到的特征之后,能够达到state-of-the-art的效果(22.48%错误率)。并且作者证实,达到这个效果并不是因为用了CNN,因为他们发现用了结构完全一样的纯CNN的模型,就达不到这个效果了(28.87%错误率)。看来对抗学习是有效果的。

下面也是一个性能对比:

可视化

接下来,作者对网络内部做了可视化。

首先,作者在latent空间进行了简单的修改。作者认为,如果在这个潜在空间做出一些微小的移动导致了语义上的变化(例如多了一张床或者窗户等),这也就说明模型学习到了相关知识的语义上的表达。

下图前九行是在9个随机采样的点(\(z\))处用插值的方法施加微小变化而生成的图片。明显看出这些是在一个卧室中视角做出一些微小的变化。尤其是第六行,这个房间逐渐从一个没有窗户的卧室变成了一间拥有大窗子的卧室。第十行里的电视则慢慢变化为一扇窗子。

然后又做了一个判别器中特征的可视化

操纵生成器的特征表达

在做了这些可视化之后,作者又想尝试操纵生成器的特征表达。

“遗忘”掉特殊的对象

首先,作者尝试去让生成器“遗忘掉”一些特定的对象。如果隐变量中的某些变量决定了对象是否被生成出来,那么删除这些变量,是不是能让生成的图像中不包含这些对象?

原文中关于这个实验记载的不是太明确,下面是我个人的理解:

作者通过一个设计实验来达到这个效果:生成150个样本,其中有52个样本包含了窗子,然后将这个窗子的位置人为地标志出来。然后在倒数第二层卷积层上使用一个logistic regression来判断这个激活函数是否控制着窗子的生成。如果在卷积层的某个filter上发现在标志着窗子的位置范围内有值,则将这个filter抹掉。然后我们会发现,我们生成的图片中的窗子真的被删掉了。

上图中,上面一行是带窗子的生成图片,下面一行是抹掉“生成窗子的feature map”之后的生成器所生成的图片。

向量可计算性

除了上面这些特性之外,作者还发现了一个有趣的性质,就是图像之间也可以像word embedding一样进行计算的:

需要注意的是:首先,用来计算的向量其实是\(z\)而不是生成图片。其次,应该拿三个类似效果的\(z\)取平均之后再进行运算。例如我们首先找到能够三个能够产生smiling woman的\(z\),取平均之后为\(z_1\),然后找到三个能够生成natural woman的\(z\)取平均后为\(z_2\),然后再找到三个能够生成natural man的\(z\)取平均后为\(z_3\),最终经过计算可以得到\(z_4=z_1-z_2+z_3\)。再用这个得到的\(z_4\)就能生成smiling man的图片。

类似上面介绍“卧室变换”的方法,作者也有插值的方法做了“面部朝向”的实验。就是说,将脸朝左到朝右的两个\(z\),插值出了一大堆“过渡”的\(z\),然后得到了这样的效果:

上面就是对这篇文章的一个介绍。感觉这篇文章文法上比较难读懂,其中有不少的地方都是我的推断,如果有错误希望能指出。

个人认为这个工作其实挺简单:提出一个模型和训练方案,以解决GAN不稳定的问题。但这篇文章的价值其实体现在了两个方面:1,作者深厚的调参功底和实验技巧并在文章中总结出了大量的经验,对使用GAN的后来者有明显的借鉴作用。2,作者做了大量的实验,并且尽可能地去分析GAN在“Representation Learning”中的奇效。所以这篇文章的工作还是相当充分的!

Friskit

继续阅读此作者的更多文章