【DCGAN】民科带你读文章: 用DCGAN补全图片

2017 年 8 月 29 日 GAN生成式对抗网络

 用DCGAN补全图片 

作者:王栋

来源:硅谷程序汪


在七月初的长周末里,我去了加州北边的旅游景点转了转,发现到处人山人海,拍出来的照片也人头攒动。于是我想,如果能把这些人轻松地从图片中PS掉就好了。


Image CC licensed, https://www.flickr.com/photos/_belial/4574420578


进行了一些简单的研究,发现这件事情并不容易,因为风景图片太过于丰富,而我既没有足够的训练数据,也没有足够的计算资源(后来意识到我应该研究content aware image completion)。但我乘着这个机会读完了一年前收藏的一篇文章“Image Completion with Deep Learning in TensorFlow”,也跑了一下他们的程序,收获颇丰,于是今天来讲讲这篇文章是怎么利用DCGAN (Deep Convolutional Generative Adversarial Networks)来自动补全人脸。


原文较长,我这里会省略第一部分基础,将主要精力放在DCGAN的理论基础以及如何使用DCGAN补全人脸上,其中很多地方我会加上他们的程序注释,帮助大家更好的理解。


DCGAN入门


GAN是今天要讲的问题的算法基础,它是由Ian Goodfellow在2014年NIPS提出的,全名叫“Generative Adversarial Networks”,是通过机器学习自动生成图片的经典之作。


传统的机器学习都是在优化算法输出和目标输出之间的相似度,然而对于图片这一问题,每个像素之间的相似度其实对图片整体效果的影响并不大。于是GAN提出通过两个网络,G (Generator)D (Discrimintor)来分别生成图片和评价图片好坏。


生成网络G的目标是生成尽量真实的图片去欺骗D,判别网络D的目标是尽量区别G生成的图片和真实图片,GD一起构成了一个博弈过程(下文会提到)。


先来说说G,对于任意给定随机向量z,我们通过一段代码生成图片(函数G在下文中会提到)。

z=np.random.uniform(-1, 1, n)

def G(z):

    ...

    Return image sample

image = G(z)


这里的G(z)就是一个深度生成网络,在2016年ICLRAlec Radford,Luke MetzSoumith Chintala发表了“Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks”,提出了用深度卷积生成图片。


想要了解fractionally strided convolution的工作原理,首先要知道什么是基本的CNN,在我之前的一篇文章中有简要的介绍,但最好还是看一下“A guide to convolution arithmetic for deep learning”的介绍。下图就是一段利用3X3的矩阵对5X5的图片进行步长为2,padding为1的卷积的过程。



通常,对图片做卷积,得到的小矩阵可以看做一个小图片块,维度逐步减小,但是在生成网络中我们想要通过一个简单的向量生成一个大的图片。Fractionally strided convolution就是这样一个反向生成的过程,也是反卷积的一种。我们对卷积后的图片每一个点增加值为0的边界,然后用原先3X3的矩阵扫描,最终如下图一样将一个3X3的卷积后矩阵变成5X5的卷积前矩阵。



通过一系列fractionally strided convolution,我们最终可以得到一个64X64的图片。



这一过程写成代码大致是这样:

def generator(self, z):

   # 将输入映射到gf_dim*8*4*4大小的conv nn上
   self.z_, self.h0_w, self.h0_b = linear(

       z, self.gf_dim*8*4*4, 'g_h0_lin', with_w=True)
   self.h0 = tf.reshape(self.z_, [-1, 4, 4, self.gf_dim * 8])
   h0 = tf.nn.relu(self.g_bn0(self.h0))


   # 不断地缩小conv nn层数,增加dimension
   self.h1, self.h1_w, self.h1_b = conv2d_transpose(h0,
       [self.batch_size, 8, 8, self.gf_dim*4], name='g_h1', with_w=True)
   h1 = tf.nn.relu(self.g_bn1(self.h1))

   h2, self.h2_w, self.h2_b = conv2d_transpose(h1,
       [self.batch_size, 16, 16, self.gf_dim*2], name='g_h2', with_w=True)
   h2 = tf.nn.relu(self.g_bn2(h2))

   h3, self.h3_w, self.h3_b = conv2d_transpose(h2,
       [self.batch_size, 32, 32, self.gf_dim*1], name='g_h3', with_w=True)
   h3 = tf.nn.relu(self.g_bn3(h3))


   # 将最终conv nn转化成3色图片
   h4, self.h4_w, self.h4_b = conv2d_transpose(h3,
       [self.batch_size, 64, 64, 3], name='g_h4', with_w=True)
   return tf.nn.tanh(h4)


反卷积被应用到各种模型生成当中,大家对这方面有疑问可以看看Ldy在github上的文章“Transposed Convolution, Fractionally Strided Convolution or Deconvolution”。


从G到D


有了生成网络,下一步就需要能够评价生成图片的评价系统D。这个评价系统D(x)输入是图像x,返回x来自真实图片分布P_data的可能性。评价网络应该在数据来自P_data的情况尽量返回1,在来自生成网络分布P_g的情况下返回0。最简单的DCGAN采用convolutional network来进行评价。



代码如下:

def discriminator(self, image, reuse=False):
   if reuse:
       tf.get_variable_scope().reuse_variables()


   h0 = lrelu(conv2d(image, self.df_dim, name='d_h0_conv'))
   h1 = lrelu(self.d_bn1(conv2d(h0, self.df_dim*2, name='d_h1_conv')))
   h2 = lrelu(self.d_bn2(conv2d(h1, self.df_dim*4, name='d_h2_conv')))
   h3 = lrelu(self.d_bn3(conv2d(h2, self.df_dim*8, name='d_h3_conv')))
   h4 = linear(tf.reshape(h3, [-1, 8192]), 1, 'd_h3_lin')


   return tf.nn.sigmoid(h4), h4


训练GAN


在我们训练这个评价函数D(x)的时候,我们需要

- 对于每一个来自P_datax,最大化D(x)

- 对于每一个不是来自P_datax,最小化D(x)


生成网络G(z)试图欺骗D,所以会根据D的反馈优化输出的图像,也就是最大化D(G(z)),相当于优化1-D(G(z)),因为D的返回值在(0,1)区间内。整体过程就和GAN论文中提到的一样,是一个极小极大值过程(Minimax game),一方面我们最大化D的判断准确率,令一方面我们最小化G生成图片和真实图片的差异。


在训练过程中,我们会分别更新判别网络D和生成网络G中的参数,具体过程伪代码可以参见GAN论文。



定义lossoptimizer的代码大致如下:

# 针对真实图片的Loss

self.d_loss_real = tf.reduce_mean(

  tf.nn.sigmoid_cross_entropy_with_logits(logits=self.D_logits, labels=tf.ones_like(self.D)))

# 针对假图片的Loss

self.d_loss_fake = tf.reduce_mean(

  tf.nn.sigmoid_cross_entropy_with_logits(logits=self.D_logits_, labels=tf.zeros_like(self.D_)))

# 针对生成网络G的Loss

self.g_loss = tf.reduce_mean(

  tf.nn.sigmoid_cross_entropy_with_logits(logits=self.D_logits_, labels=tf.ones_like(self.D_)))


# 针对网络D和G的分别优化函数

d_optim = tf.train.AdamOptimizer(

   config.learning_rate,

   beta1=config.beta1).minimize(

      self.d_loss, var_list=self.d_vars)

g_optim = tf.train.AdamOptimizer(

   config.learning_rate,

   beta1=config.beta1).minimize(

      self.g_loss, var_list=self.g_vars)


我进行了几千轮训练,这里是运行https://github.com/bamos/dcgan-completion.tensorflow代码后得到的人脸生成效果,感觉还不是很好,由于没有GPU,所以训练花费时间很长,我还需要等几天。



图片补全的过程


现在我们有了判别网络D(x)和生成网络G(z),接下来我们会用到“Semantic Image Impainting with Perceptual and Contextual Losses”中提到的方法补全图片。


想要补全一张图片y,一种听起来比较合理但实际上不太可行的方法就是直接优化D(y)。论文中给出了一个样例我并没有完全看懂,大意是说这样的做法可能得到的图片既不满足原始数据分布P_data,也不满足生成概率P_g希望对这一部分认识深刻的人可以给我留言讲解一下。



为了解决图片补全这一问题,该论文提出了一个binary mask的概念,也就是一个只包含0和1的矩阵M,我们将原始图片y和这一矩阵M每一个元素相乘,矩阵M中为1的位置就会透过原始图片。如果我们的生成函数G产生了图片G(z),就可以与(1-M)中每一个元素相乘,得到补全部分。全图则是M⊙y+(1-M)⊙G(z)


为了找到这样的图片G(z),我们定义两种不同形式的loss


Contextual Loss:也就是上下文相关的Loss,这里我们需要补全的图片上下文就是原图中我们可以看到的部分M⊙y,我们需要最小化||M⊙G(z)-M⊙y||,这种情况写成代码就是:

self.contextual_loss = tf.reduce_sum(tf.contrib.layers.flatten( tf.abs(

tf.multiply(self.mask, self.G) - tf.multiply(self.mask, self.images))), 1)


Perceptual Loss,也就是关于生成图片多么像真实图片的Loss,也就对应着上文中提到的log(1-D(G(z)))


我们将Contextual LossPerceptual Loss通过一个lambda合并到一起,就得到了全新的Loss,结合上面提到的Perceptual Loss,这段代码可以写为:

self.perceptual_loss = self.g_loss

self.complete_loss = self.contextual_loss + self.lam * self.perceptual_loss


将这上面所有的东西合并到一起,我们就可以不断地生成新的图片,计算最终loss对应生成向量z的导数,然后通过自己实现的Adam Optimizerplaceholder z进行调整,一切都在代码里:

for idx in xrange(0, batch_idxs):
   batch_images = ...
   batch_mask = np.resize(mask, [self.batch_size] + self.image_shape)
   zhats = np.random.uniform(-1, 1, size=(self.batch_size, self.z_dim))

   v = 0
   for i in xrange(config.nIter):
       fd = {
           self.z: zhats,
           self.mask: batch_mask,
           self.images: batch_images,
       }
       run = [self.complete_loss, self.grad_complete_loss, self.G]
       loss, g, G_imgs = self.sess.run(run, feed_dict=fd)

       v_prev = np.copy(v)
       v = config.momentum*v - config.lr*g[0]
       zhats += -config.momentum * v_prev + (1+config.momentum)*v
       zhats = np.clip(zhats, -1, 1)


以下是一段最终效果动画,我目前还处于人脸生成阶段,还没有对补全进行测试,所以暂时没有什么心得可以分享。



小结


感谢大家阅读今天的民科与你分享环节。突然想起之前收藏的这篇文章,于是试了试里面的算法,学到了不少东西但也发现简单的GAN在我现有的计算资源和数据上并不能得到很好的效果,经过一番调查我又发现了不少有趣的文章:


1. Neural Fill: Content Aware Image Fill with Generative Adversarial Neural Networks

2. Globally and Locally Consistent Image Completion

3. Scene Completion Using Millions of Photographs

4. Image Completion with Structure Propagation


等我再给自己充充电,再与大家继续分享,希望喜欢程序汪的朋友多多关注和分享我的内容,也希望大家与我多多交流,支持我的贡献一个GPU机器吧。



高质量延伸阅读

☞ 【学界】清华朱军团队探索DNN内部架构,采用对抗性例子监督网络生成及错误

☞ 【原理】深入浅出:GAN原理与应用入门介绍

☞ 【学界】宅男的福音:用GAN自动生成二次元萌妹子

☞ 【几何图景】GAN的几何图景:样本空间的Morse流,与鉴别网络D为何不可能真正鉴别真假

☞ 【理解】GAN 的理解与 TensorFlow 的实现

☞ 【意义】GAN 的发展对于研究通用人工智能有什么意义?

☞ 【应用】生成式对抗网络GAN有哪些最新的发展,可以实际应用到哪些场景中?

☞ 【从头开始GAN】Goodfellow开山之作到DCGAN等变体

☞ 【智能自动化学科前沿讲习班第1期】上海交大倪冰冰副教授:面向图像序列的生成技术及应用初探

☞ 【智能自动化学科前沿讲习班第1期】University of Central Florida 的Guojun Qi:LS-GAN

☞ 【智能自动化学科前沿讲习班第1期】微软秦涛主管研究员:从单智能体学习到多智能体学习

☞ 【智能自动化学科前沿讲习班第1期】王坤峰副研究员:GAN与平行视觉

☞ 【原理】十个生成模型(GANs)的最佳案例和原理 | 代码+论文

☞ 【插画】AI可能真的要代替插画师了……

☞ 【教程】经得住考验的「假图片」:用TensorFlow为神经网络生成对抗样本

☞ 【模型】基于深度学习的三大生成模型:VAE、GAN、GAN的变种模型

☞ 【大会】还记得Wasserstein GAN吗?不仅有Facebook参与,也果然被 ICML 接收

☞ 【开发】 用GAN来做图像生成,这是最好的方法

☞ 【学界】邢波团队提出contrast-GAN:实现生成式语义处理

☞  【专栏】阿里SIGIR 2017论文:GAN在信息检索领域的应用

☞ 【学界】康奈尔大学说对抗样本出门会失效,被OpenAI怼回来了!

☞ 警惕人工智能系统中的木马、病毒 ——深度学习对抗样本简介

☞ 【生成图像】Facebook发布的LR-GAN如何生成图像?这里有一篇Pytorch教程

☞ 【智能自动化学科前沿讲习班第1期】国立台湾大学(位于中国台北)李宏毅教授:Anime Face Generation

☞ 【变狗为猫】伯克利图像迁移cycleGAN,猫狗互换效果感人

☞ 【论文】对抗样本到底会不会对无人驾驶目标检测产生干扰?又有人发文质疑了

【智能自动化学科前沿讲习班第1期】王飞跃教授:生成式对抗网络GAN的研究进展与展望

【开发】看完立刻理解GAN!初学者也没关系

【专栏】基于对抗学习的生成式对话模型的坚实第一步 :始于直观思维的曲折探索

☞ 【重磅】平行将成为一种常态:从SimGAN获得CVPR 2017最佳论文奖说起

☞ 【最新】OpenAI:3段视频演示无人驾驶目标检测强大的对抗性样本!

☞  【干货】生成对抗网络(GAN)之MNIST数据生成

☞ 【论文】CVPR 2017最佳论文出炉,DenseNet和苹果首篇论文获奖

☞   AI侦探敲碎深度学习黑箱

☞ 【深度学习】解析深度学习的局限性与未来,谷歌Keras之父「连发两文」发人深省

☞   苹果重磅推出AI技术博客,CVPR合成逼真照片论文打响第一枪

☞ 【Ian Goodfellow 五问】GAN、深度学习,如何与谷歌竞争

☞ 【巨头升级寡头】AI产业数据称王,GAN和迁移学习能否突围BAT垄断?

☞ 【高大上的DL】BEGAN: Boundary Equilibrium GAN

☞ 【最详尽的GAN介绍】王飞跃等:生成式对抗网络 GAN 的研究进展与展望

☞ 【最全GAN变体列表】Ian Goodfellow推荐:GAN动物园

☞   二十世纪的十大科学骗局

☞ 【DCGAN】深度卷积生成对抗网络的无监督学习,补全人脸合成图像匹敌真实照片

【学界】让莫奈画作变成照片:伯克利图像到图像翻译新研究

☞ 【DualGAN】对偶学习的生成对抗网络

☞ 【开源】收敛速度更快更稳定的Wasserstein GAN(WGAN)

☞ 【Valse 2017】生成对抗网络(GAN)研究年度进展评述

☞ 【开源】谷歌新推BEGAN模型用于人脸数据集:效果惊人!

☞ 【深度】Ian Goodfellow AIWTB开发者大会演讲:对抗样本与差分隐私

☞   论文引介 | StackGAN: Stacked Generative Adversarial Networks

☞ 【专题GAN】GAN应用情况调研

☞ 【纵览】从自编码器到生成对抗网络:一文纵览无监督学习研究现状

☞ 【论文解析】Ian Goodfellow 生成对抗网络GAN论文解析

☞ 【VALSE 前沿】利用对抗学习改进目标检测的结果

☞ 【干货】全面分析GAN,以及如何用TF实现GAN?

☞   苹果首份AI论文横空出世,提出SimGAN训练方法

☞ 【推荐】条条大路通罗马LS-GAN:把GAN建立在Lipschitz密度上

☞   到底什么是生成式对抗网络GAN?

☞   看穿机器学习(W-GAN模型)的黑箱

☞   看穿机器学习的黑箱(II)

【Geometric GAN】引入线性分类器SVM的Geometric GAN

☞ 【征稿】“生成式对抗网络GAN技术与应用”专刊

☞ 【GAN for NLP】PaperWeekly 第二十四期 --- GAN for NLP

☞ 【学界 】 从感知机到GAN,机器学习简史梳理

☞ 【Demo】GAN学习指南:从原理入门到制作生成Demo

☞ 【学界】伯克利与OpenAI整合强化学习与GAN:让智能体学习自动发现目标

☞ 【解读】通过拳击学习生成对抗网络(GAN)的基本原理

☞ 【人物 】Ian Goodfellow亲述GAN简史:人工智能不能理解它无法创造的东西

☞ 【DCGAN】DCGAN: 一类稳定的GANs

☞ 【DCGAN】DCGAN:深度卷积生成对抗网络的无监督学习,补全人脸合成图像匹敌真实照片

☞ 【原理】 直观理解GAN背后的原理:以人脸图像生成为例

☞ 【干货】深入浅出 GAN·原理篇文字版(完整)

☞   带你理解CycleGAN,并用TensorFlow轻松实现

☞   PaperWeekly 第39期 | 从PM到GAN - LSTM之父Schmidhuber横跨22年的怨念

☞ 【CycleGAN】加州大学开源图像处理工具CycleGAN

☞ 【SIGIR2017满分论文】IRGAN:大一统信息检索模型的博弈竞争

☞ 【贝叶斯GAN】贝叶斯生成对抗网络(GAN):当下性能最好的端到端半监督/无监督学习

☞ 【贝叶斯GAN】贝叶斯生成对抗网络(GAN):当下性能最好的端到端半监督/无监督学习

☞ 【GAN X NLP】自然语言对抗生成:加拿大研究员使用GAN生成中国古诗词

☞    ICLR 2017 | GAN Missing Modes 和 GAN

☞ 【论文汇总】生成对抗网络及其变体

☞ 【AI】未来AI这样帮你一键修片,那还有PS什么事?

☞ 【学界】CMU新研究试图统一深度生成模型:搭建GAN和VAE之间的桥梁

☞ 【专栏】大漠孤烟,长河落日:面向景深结构的风景照生成技术

☞ 【开发】最简单易懂的 GAN 教程:从理论到实践(附代码)

☞ 【论文访谈】求同存异,共创双赢 - 基于对抗网络的利用不同分词标准语料的中文分词方法

☞ 【LeCun论战Yoav】自然语言GAN惹争议:深度学习远离NLP?

☞ 【争论】从Yoav Goldberg与Yann LeCun争论,看当今的深度学习、NLP与arXiv风气

☞ 【观点】Yoav Goldberg撰文再回应Yann LeCun:「深度学习这群人」不了解NLP(附各方评论)

☞   PaperWeekly 第41期 | 互怼的艺术:从零直达 WGAN-GP

☞ 【业界】CMU和谷歌联手研制左右互搏的对抗性机器人

☞ 【谷歌 GAN 生成人脸】对抗创造新艺术风格,128 像素扩展到 4000

☞ 【原理】模拟上帝之手的对抗博弈——GAN背后的数学原理

☞ 【原理】只知道GAN你就OUT了——VAE背后的哲学思想及数学原理



登录查看更多
4

相关内容

相较原始的GAN,DCGAN几乎完全使用了卷积层代替全链接层,判别器几乎是和生成器对称的,整个网络没有pooling层和上采样层的存在,实际上是使用了带步长(fractional-strided)的卷积代替了上采样,以增加训练的稳定性
【书籍】深度学习框架:PyTorch入门与实践(附代码)
专知会员服务
163+阅读 · 2019年10月28日
GANs最新综述论文: 生成式对抗网络及其变种如何有用
专知会员服务
70+阅读 · 2019年10月19日
从DCGAN到SELF-MOD:GAN的模型架构发展一览
PaperWeekly
4+阅读 · 2019年4月22日
带你读论文 | 生成对抗网络GAN论文TOP 10
微软研究院AI头条
24+阅读 · 2019年4月11日
必读!TOP10生成对抗网络GAN论文(附链接)
数据派THU
16+阅读 · 2019年3月24日
GAN之父5篇文章细数GAN在人脸生成方向4年多进展
THU数据派
8+阅读 · 2019年1月22日
一文详解生成对抗网络(GAN)的原理,通俗易懂
人工智能头条
6+阅读 · 2018年5月6日
CycleGAN:图片风格,想换就换 | ICCV 2017论文解读
PaperWeekly
12+阅读 · 2018年3月14日
深度卷积对抗生成网络(DCGAN)实战
全球人工智能
14+阅读 · 2017年11月7日
【教程】详解如何使用Keras实现Wassertein GAN
GAN生成式对抗网络
7+阅读 · 2017年10月5日
【开发】 用GAN来做图像生成,这是最好的方法
GAN生成式对抗网络
6+阅读 · 2017年8月9日
Arxiv
4+阅读 · 2018年5月21日
Arxiv
4+阅读 · 2018年4月30日
Arxiv
10+阅读 · 2018年2月17日
Arxiv
9+阅读 · 2018年1月4日
Arxiv
4+阅读 · 2016年9月20日
VIP会员
相关资讯
从DCGAN到SELF-MOD:GAN的模型架构发展一览
PaperWeekly
4+阅读 · 2019年4月22日
带你读论文 | 生成对抗网络GAN论文TOP 10
微软研究院AI头条
24+阅读 · 2019年4月11日
必读!TOP10生成对抗网络GAN论文(附链接)
数据派THU
16+阅读 · 2019年3月24日
GAN之父5篇文章细数GAN在人脸生成方向4年多进展
THU数据派
8+阅读 · 2019年1月22日
一文详解生成对抗网络(GAN)的原理,通俗易懂
人工智能头条
6+阅读 · 2018年5月6日
CycleGAN:图片风格,想换就换 | ICCV 2017论文解读
PaperWeekly
12+阅读 · 2018年3月14日
深度卷积对抗生成网络(DCGAN)实战
全球人工智能
14+阅读 · 2017年11月7日
【教程】详解如何使用Keras实现Wassertein GAN
GAN生成式对抗网络
7+阅读 · 2017年10月5日
【开发】 用GAN来做图像生成,这是最好的方法
GAN生成式对抗网络
6+阅读 · 2017年8月9日
Top
微信扫码咨询专知VIP会员