你来手绘涂鸦,人工智能生成「猫片」:edges2cats图像转换详解 ...
星云动态
在 2 月 19 日推出以后,这个实现很快受到了大家的关注,甚至连 Yann LeCun 这样的重量级人物也在其中开始了自己的「创作」。
这一神奇的应用是如何实现的?让我们看看作者 Christopher Hesse 带来的教程吧。
相关链接:
Edges2cats:
Github:
Isola 等人在 pix2pix 中得到的结果看起来很不错,它是对抗性网络的一种绝佳实现,所以我将 Torch 上的代码移植到了 Tensorflow 中。在 Github 上单文件版(single-file)的实现 pix2pix-tensorflow 已经可供下载:
下面是 pix2pix 的一些例子,我将从论文开始一步步解释这到底是什么。
「术士的宝石,是魔力无边的宝石,它能点石成金、创造不朽、复生鬼魂、杀死巨魔,它无所不能。」——Wizard People, Dear Readers
pix2pix 也许不能复生鬼魂,但是如果你给它一个包含了普通石头和其相对金子形态的数据集,那么 pix2pix 还真能点石成金。
运行代码
# make sure you have Tensorflow 0.12.1 installed firstpython -c "import tensorflow; Print (tensorflow.__version__)"# clone the repogit clone https://github.com/affinelayer/pix2pix-tensorflow.gitcd pix2pix-tensorflow# download the CMP Facades dataset http://cmp.felk.cvut.cz/~tylecr1/facade/python tools/download-dataset.py facades# train the model# this may take 1-9 hours depending on GPU, on CPU you will be waiting for a bitpython pix2pix.py \ --mode train \ --output_dir facades_train \ --max_epochs 200 \ --input_dir facades/train \ --which_direction BtoA# test the modelpython pix2pix.py \ --mode test \ --output_dir facades_test \ --input_dir facades/val \ --checkpoint facades_train
终端
在经过一段时间的训练后,你大概会得到类似于以下的输出:
pix2pix 是怎样运作的?
pix2pix 使用了一种条件生成式对抗网络(Conditional Generative Adversarial Networks)来学习从输入图像到输出图像的映射。
这个网络由两个主要部分组成,生成器(generator)和辨别器 (discriminator)。生成器接收了输入图像,经过转变来得到输出图像。辨别器将输入图像与未知图像(不管是数据集中的目标图像,或是辨别器产生的输出图像)进行比较,并尝试猜测该图像是否由生成器生成。
一个数据集的例子就是输入图像是黑白图片,但是目标图像是这个图像的彩色版本:
在这种情况下,生成器就会去尝试学习如何让黑白图像变为彩色:
辨别器看到生成器彩色化的尝试,就会去试着学习分辨生成器彩色化的图像和数据集中真正有颜色的目标图像之间的区别。
为什么要这么麻烦呢?这篇论文其中的一个重点就是辨别器为训练生成器提供了一个损失函数,你不需要手动指定。人工设计(Hand-engineered)的转换代码已经由经过训练的神经网络所替代,所以为什么不能把手动设计的损失函数运算也替代了呢?如果这起作用的话,在你还在担忧计算机会取代你的工作时,它们就已经开始接管工作了。让我们来看一看对抗式网络的两个组成部分:生成器和辨别器。
生成器
生成器的工作就是对一张输入图像进行我们想要的转换,以生成目标图像。输入图像应该是黑白图像,输出图像我们想让它成为彩色版本。生成器的结构叫做「编码器—解码器」(encoder-decoder),在 pix2pix 模型中,编码器—解码器看起来就如下图所示:
这里的容量给你一种紧挨着张量维度的形状感。样例中的输入是一个带有 3 个颜色通道(红、绿、蓝,全部等于一个黑白图像)的 256x256 图像,并且输出相同。
生成器获得一些输入,并试图用一系列的编码器(卷积+激活函数)减少它,直到成为一个较小的表征。想法是通过这种方式压缩它我们希望在最后一个编码层之后有一个更高层面的表征。解码层执行相反操作(去卷积+激活函数),并且反转编码层的行动。
为了提高论文中图到图传输的表现,作者使用 「U-Net」取代了 encoder-decoder。它们在做同样的事,不同的是有了直接连接编码层和解码层的跳跃连接。
跳跃连接给了网络一个忽略编码/解码部分的选择,如果它对其毫无用处。
这些图解略有简化。例如,网络的第一层和最后一层之间没有批标准层,中间的个别层有丢失的单元。论文中使用的着色模式对于输入和输出层有着很多不同的通道。
辨别器
辨别器(The Discriminator)的目标就是接收两张图像,一张是输入图像,另一张是未知图像(其可能是辨别的目标或者是生成器输出的图像),辨别器的工作就是识别第二张图像到底是不是从生成器(the generator)输出的。
该结构看起来就像是生成器的编码部分一样,只不过稍微复杂一点。输出是 30×30 的图像,其中每一个像素值(从 0 到 1)表示未知图像相应部分的置信度。在 pix2pix 的实现中,30×30 图像中每一个像素都对应着 70×70 块输入图像的置信度(因为输入图像是 256×256 的,所以这些图像块有很多重叠)。这种构架就称之为「区块生成对抗网络(PatchGAN)」。
训练
为了训练该网络,我们需要分两步进行:即训练辨别器(discriminator)和训练生成器(generator)。
为了训练辨别器,首先生成器需要生成一张输出图像。辨别器再根据输入/目标对(input/target pair)和输入/输出对(input/output pair)判定该图像有多大程度看起来是真实的。然后基于输入/输出对(input/output pair)和输入/目标对(input/target pair)的分类误差来调整辨别器的权重。
根据鉴别器的输出和输出与目标图像之间的差异来调节生成器的权重。
这里有一个技巧:当你在鉴别器的输出结果上训练生成器时,你实际上是在计算鉴别器的梯度,这意味着当鉴别器性能提升时,你是在训练生成器打败鉴别器。
其中的原理是这样:当鉴别器变的越来越好时,生成器也是。如果鉴别器擅长这项任务,生成器有能力通过梯度下降学习正确的映射函数,你应该得到一个逼真的生成输出。
验证
我们从一台装有 Nvidia GTX 750 Ti 显卡(~1.3 TFLOPS)的 Linux 主机上执行代码进行验证。由于计算能力的欠缺,验证并不广泛,并且只有 200 个 epoch 中的 facades 数据集被测验。
终端
git clone https://github.com/affinelayer/pix2pix-tensorflow.gitcd pix2pix-tensorflow python tools/download-dataset.py facadessudo nvidia-docker run \ --volume $PWD:/prj \ --workdir /prj \ --env PYTHONUNBUFFERED=x \ affinelayer/pix2pix-tensorflow \ python pix2pix.py \ --mode train \ --output_dir facades_train \ --max_epochs 200 \ --input_dir facades/train \ --which_direction BtoAsudo nvidia-docker run \ --volume $PWD:/prj \ --workdir /prj \ --env PYTHONUNBUFFERED=x \ affinelayer/pix2pix-tensorflow \ python pix2pix.py \ --mode test \ --output_dir facades_test \ --input_dir facades/val \ --checkpoint facades_train
出于对比,验证集中的第一个图像看起来像这样:
验证结果集:
实现
实现是一个单一文件 pix2pix.py ,尽可能在 TensorFlow 图谱之内。移植过程多是观察现有的 Torch 实现和 Torch 源代码,搞明白什么种类的层和设置被使用,以确保 TensorFlow 版本与原始版本尽可能一致。调试一个有问题的实现很耗时间,因此我细心地尝试这次转化以规避掉大量的调试。
pix2pix.py:
实现开始于创建生成器图,接着是鉴别器图,最后是训练系统。在运行时使用 Torchpix2pix 代码打印生成器和鉴别器图。我在 Torch 框架源中寻找不同的图层类型,并发现了当前的设置和操作,以及如何在 Tensorflow 中将其实现。
最理想的情况是能把 pix2pix 训练的网络权重导进 Tensorflow 以验证图形构造。但是这令人厌烦,而且我很不擅长 Torch,所以我没有那样做。
本代码中的大多数错误与 Tensorflow 的 build-graph-then-execute 模型相关,如果你习惯于命令式代码,那么 Tensorflow 会让你感到一点惊讶。
论文:Image-to-Image Translation with Conditional Adversarial Networks
摘要:为实现图像到图像转化(image-to-image translation)任务,我们研究了条件对抗网络。这些网络不仅会学习从输入图像到输出图像的映射,而且还学习损失函数来训练映射。这使得我们不必在此类任务中加入通常需要的不同的损失公式。我们的实验证明了这种方法在从有标记的地图中生成照片,利用单色线图生成照片,为黑白图填充色彩等任务中是有效的。我们证明了在此类模型的训练中,人类不再需要手动输入的映射函数以及损失函数。
转自:机器之心