授权自AI科技大本营(ID:rgznai100)

本文约5200字,建议阅读10+分钟

本文作者基于代码实现系统的思路,详细阐述了 DRAW 的概念、架构和优势等。

[ 导读 ]最近,谷歌 DeepMInd 发表论文(DRAW: A Recurrent Neural Network For Image Generation),提出了一个用于图像生成的递归神经网络,该系统大大提高了 MNIST 上生成模型的质量。为更加深入了解 DRAW,本文作者基于 Eric Jang 用 158 行 Python 代码实现该系统的思路,详细阐述了 DRAW 的概念、架构和优势等。

首先我们先解释一下 DRAW 的概念吧

递归神经网络是一种用于图像生成的神经网络结构。DRAW Networks 结合了一种新的空间注意机制,该机制模拟了人眼的中心位置,采用了一个顺序变化的自动编码框架,使之对复杂图像进行迭代构造。

该系统大大提高了 MNIST 上生成模型的质量,特别是当对街景房屋编号数据集进行训练时,肉眼竟然无法将它生成的图像与真实数据区别开来。

DRAW 体系结构的核心是一对递归神经网络:一个是压缩用于训练的真实图像的编码器,另一个是在接收到代码后重建图像的解码器。这一组合系统采用随机梯度下降的端到端训练,损失函数的最大值变分主要取决于对数似然函数的数据。

DRAW 的架构

DRAW 网络类似于其他变分自动编码器,它包含一个编码器网络,该编码器网络决定着潜在代码上的 distribution(潜在代码主要捕获有关输入数据的显著信息),解码器网络接收来自 code distribution 的样本,并利用它们来调节其自身图像的 distribution 。

DRAW 与其他自动解码器的三大区别

 

编码器和解码器都是 DRAW 中的递归网络,解码器的输出依次添加到 distribution 中以生成数据,而不是一步一步地生成 distribution 。动态更新的注意机制用于限制由编码器负责的输入区域和由解码器更新的输出区域 。简单地说,这一网络在每个 time-step 都能决定“读到哪里”和“写到哪里”以及“写什么”。

左:传统变分自动编码器

右:DRAW网络

在生成过程中,从先前的 P(z)中提取一个样本 z ,并通过前馈译码器网络来计算给定样本的输入 P(x_z)的概率。

在推理过程中,输入 x 被传递到编码器网络,在潜在变量上产生一个近似的后验 Q(z|x) 。在训练过程中,从 Q(z|x) 中抽取 z,然后用它计算总描述长度 KL ( Q (Z|x)∣∣ P(Z)−log(P(x|z)),该长度随随机梯度的下降(https://en.wikipedia.org/wiki/Stochastic_gradient_descent)而减小至最小值。

在每一个步骤中,都会将先前 P(z)中的一个样本 z_t 传递给递归解码器网络,该网络随后会修改 canvas matrix 的一部分。最后一个 canvas matrix cT 用于计算 P(x|z_1:t)。

在推理过程中,每个 time-step 都会读取输入,并将结果传递给编码器 RNN,然后从上一 time-step 中的 RNN 指定读取位置,编码器 RNN 的输出用于计算该 time-step 的潜在变量的近似后验值。

损失函数

最后一个 canvas matrix cT 用于确定输入数据的模型 D(X | cT) 的参数。如果输入是二进制的,D 的自然选择呈伯努利分布,means 由 σ(cT) 给出。重建损失 Lx 定义为 D 下 x 的负对数概率: 

The latent loss 潜在distributions序列  的潜在损失 被定义为源自   的潜在先验 P(Z_t)的简要 KL散度。

鉴于这一损失取决于由   绘制的潜在样本 z_t ,因此其反过来又决定了输入 x。如果潜在 distribution是一个 这样的 diagonal Gaussian ,P(Z_t) 便是一个均值为 0,且具有标准离差的标准 Gaussian,这种情况下方程则变为  

网络的总损失 L 是重建和潜在损失之和的期望值: 

对于每个随机梯度下降,我们使用单个 z 样本进行优化。

L^Z 可以解释为从之前的序列向解码器传输潜在样本序列 z_1:T 所需的 NAT 数量,并且(如果 x 是离散的)L^x 是解码器重建给定 z_1:T 的 x 所需的 NAT 数量。因此,总损失等于解码器和之前数据的预期压缩量。

改善图片

正如 Eric Jang 在他的文章中提到的,让我们的神经网络仅仅“改善图像”而不是“一次完成图像”会更容易些。正如人类艺术家在画布上涂涂画画,并从绘画过程中推断出要修改什么,以及下一步要绘制什么。

改进图像或逐步细化只是一次又一次地破坏我们的联合 distribution P(C) ,导致潜在变量链 C1,C2,…CT−1 呈现新的变量分布 P(CT) 。

诀窍是多次从迭代细化分布 P(Ct|Ct−1)中取样,而不是直接从 P(C) 中取样。

在 DRAW 模型中, P(Ct|Ct−1) 是所有 t 的同一 distribution,因此我们可以将其表示为以下递归关系(如果不是,那么就是 Markov Chain 而不是递归网络了)。

DRAW模型的实际应用

假设你正在尝试对数字 8 的图像进行编码。每个手写数字的绘制方式都不同,有的样本 8 可能看起来宽一些,有的可能长一些。如果不注意,编码器将被迫同时捕获所有这些小的差异。

但是……如果编码器可以在每一帧上选择一小段图像并一次检查数字 8 的每一部分呢?这会使工作更容易,对吧?

同样的逻辑也适用于生成数字。注意力单元将决定在哪里绘制数字 8 的下一部分-或任何其他部分-而传递的潜在矢量将决定解码器生成多大的区域。

基本上,如果我们把变分的自动编码器(VAE)中的潜在代码看作是表示整个图像的矢量,那么绘图中的潜在代码就可以看作是表示笔画的矢量。最后,这些向量的序列实现了原始图像的再现。

好吧,那么它是如何工作的呢?

在一个递归的 VAE 模型中,编码器在每一个 time-step 会接收整个输入图像。在 DRAW 中,我们需要将焦点集中在它们之间的 attention gate 上,因此编码器只接收到网络认为在该 time-step 重要的图像部分。第一个 attention gate 被称为“Read”attention。

“Read”attention分为两部分:

选择图像的重要部分和裁剪图像

  • 选择图像的重要部分

为了确定图像的哪一部分最重要,我们需要做些观察,并根据这些观察做出决定。在 DRAW中,我们使用前一个 time-step 的解码器隐藏状态。通过使用一个简单的完全连接的图层,我们可以将隐藏状态映射到三个决定方形裁剪的参数:中心 X、中心 Y 和比例。

  • 裁剪图像

现在,我们不再对整个图像进行编码,而是对其进行裁剪,只对图像的一小部分进行编码。然后,这个编码通过系统解码成一个小补丁。

现在我们到达 attention gate 的第二部分, “write”attention,(与“read”部分的设置相同),只是“write”attention 使用当前的解码器,而不是前一个 time-step 的解码器。

实际应用便是如此吗?

虽然可以直观地将注意力机制描述为一种裁剪,但实践中使用了一种不同的方法。在上面描述的模型结构仍然精确的前提下,使用了 gaussian filters 矩阵,没有利用裁剪的方式。我们在 DRAW 中取了一组每个 filter 的中心间距都均匀的 gaussian filters 矩阵 。

代码一览

我们在 Eric Jang 的代码的基础上,对其进行一些清理和注释,以便于理解。

Eric 为我们提供了一些伟大的功能,可以帮助我们构建 “read” 和 “write” 注意门径,还有过滤我们将使用的初始状态功能,但是首先,我们需要添加新的功能,来使我们能创建一个密集层并合并图像。并将它们保存到本地计算机中,以获取更新的代码。

# fully-conected layerdef dense(x, inputFeatures, outputFeatures, scope=None, with_w=False):    with tf.variable_scope(scope or "Linear"):        matrix = tf.get_variable("Matrix", [inputFeatures, outputFeatures], tf.float32, tf.random_normal_initializer(stddev=0.02))        bias = tf.get_variable("bias", [outputFeatures], initializer=tf.constant_initializer(0.0))        if with_w:            return tf.matmul(x, matrix) + bias, matrix, bias        else:            return tf.matmul(x, matrix) + bias# merge imagesdef merge(images, size):    h, w = images.shape[1], images.shape[2]    img = np.zeros((h * size[0], w * size[1]))    for idx, image in enumerate(images):        i = idx % size[1]        j = idx / size[1]        img[j*h:j*h+h, i*w:i*w+w] = image    return img# save image on local machine        def ims(name, img):    # print img[:10][:10]    scipy.misc.toimage(img, cmin=0, cmax=1).save(name)  

现在让我们把代码放在一起以便完成。

你可以在作者的github主页上查看更多:

https://github.com/shugert/DRAW

原文链接:

https://hackernoon.com/understanding-a-recurrent-neural-network-for-image-generation-7e2f83wdg

编辑:黄继彦

校对:杨学俊

158行Python代码复现:DeepMind提图像生成的递归神经网络DRAW相关推荐

  1. DeepMind提图像生成的递归神经网络DRAW,158行Python代码复现

    作者 | Samuel Noriega 译者 | Freesia 编辑 | 夕颜 出品 | AI科技大本营(ID: rgznai100) [导读]最近,谷歌 DeepMInd 发表论文( DRAW: ...

  2. 158行Python代码复现DeepMind递归神经网络DRAW

    作者 | Samuel Noriega 译者 | Freesia 编辑 | 夕颜 来源 | AI科技大本营(ID: rgznai100) [导读]最近,谷歌 DeepMind 发表论文( DRAW: ...

  3. 158 行 Python 代码,复现 DeepMind 递归神经网络 DRAW!

    作者 | Samuel Noriega 译者 | Freesia 编辑 | 夕颜 出品 | AI科技大本营(ID: rgznai100) [导读]最近,谷歌 DeepMInd 发表论文( DRAW: ...

  4. 40行Python代码,实现卷积特征可视化

    最近在阅读 Jeremy Rifkin 的书<The End of Work>时,我读到一个有趣的关于 AI 的定义.Rifkin 写到:「今天,当科学家们谈论人工智能时,他们通常是指『一 ...

  5. python怎么换背景_3行Python代码实现图像照片抠图和换底色的方法

    1.项目背景 对于不会PS的小伙伴,抠图是一个难度系数想当高的活儿,某宝照片抠图和证件照换底色均价都是5元RMB,所以今天要介绍的这款神工具,只要 3 行代码 5 秒钟就可以完成高精度抠图,甚至都不用 ...

  6. 服不服?40行Python代码,实现卷积特征可视化

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|深度学习这件小事 卷积神经网络(CNN)变革了计算机视觉 ...

  7. [转载] python 卷积_40 行 Python 代码,实现卷积特征可视化

    参考链接: 使用Python3跟踪鸟类迁移 卷积神经网络(CNN)变革了计算机视觉,并将彻底改变整个世界.因此,开发解释 CNN 的技术也同样是一个重要的研究领域.本文将向你解释如何仅使用 40 行 ...

  8. python人脸检测代码_如何用不到25行Python代码实现人脸检测

    本文我们会讲讲怎样利用不到 25 行 Python 代码和开源库 OpenCV,以很简单的方式实现人脸识别. 在正式开始前,先提以下两点小小的建议:先别急着跳到代码部分,最好在前文理解一下代码是干什么 ...

  9. 程序员的乐趣,生成自定义二维码,5 行 Python 代码就搞定

    选自 | towardsdatascience 作者 | Arindom Bhattacharjee 转自 | 机器之心 参与 | 杜伟.小舟 随处可见的二维码是怎么生成的?自己做一个试试吧. 随着互 ...

最新文章

  1. 揭秘特斯拉自动驾驶雄心:最大优势非算法或技术而是海量数据
  2. Mysql函数:Last_insert_id()语法讲解
  3. (转)如果知道dll文件是面向32位系统还是面向64位系统的?
  4. Cities(2020昆明C)
  5. RabbitMQ单机瞎玩(1)
  6. 【英语学习】【Daily English】U02 Daily Routine L03 Tuesday night is curry night
  7. 钱大妈关闭所有北京门店:低估了北京市场的难度
  8. 求树的直径+并查集(bfs,dfs都可以)hdu4514
  9. 图像处理保研面试_保研(六校面试)
  10. 现实世界的Windows Azure:采访Definition 6首席技术官Paul Hernacki
  11. 【优化算法】差分蜂群优化算法(DEABC)【含Matlab源码 1423期】
  12. sqlmap注入命令大全
  13. 计算机右键管理是什么软件,右键管理工具打不开怎么办【图文】
  14. 从美国人工智能年会看2017世界人工智能最新研究成果
  15. [译] MySQL 最佳实践 —— 高效插入数据
  16. linux 更新系统时间
  17. SCD-缓慢变化维-拉链表
  18. 直播回顾|论道原生:云原生时代的中间件
  19. Xposed 反检测
  20. 【Matlab】希腊字母

热门文章

  1. java夯实基础:final脑图
  2. 分布式熔断降级平台aegis
  3. 《css世界》的那些实用技巧
  4. puppet recurse 导致的性能问题一例
  5. ArcGis License 启动失败
  6. 数据架构简史:转换中的范式
  7. 在eclipse中搭建maven工程(第二种方法)
  8. 玩转Docker Ceph集群及对象存储
  9. 《BI项目笔记》创建标准维度、维度自定义层次结构
  10. MVC中实现多按钮提交(转)