大数据文摘作品
编译:王一丁、于乐源、Aileen
本文作者RyanDaul是Node.js的创始人,应该算是软件工程领域当之无愧的大犇了。他和我们分享了自己在谷歌大脑见习项目一年中的工作,成果,失败和思考。
去年,在通过对TensorFlow的研究得出一点点心得之后,我申请并入选了谷歌大脑举办的的首届见习项目(GoogleBrainResidencyProgram)。该项目共邀请了24名在机器学习领域有着不同背景的人士,受邀者将在为期一年的时间里和Google的科学家及工程师们在位于山景城的Google深度学习研究实验室中共同探索最前沿的深度学习科技。
这个为期一年的项目已经结束了,在此我将就这一年的经历作一个总结与分享。
最初拟定的目标是“修正”老电影或电视剧的画面。想象一下,上世纪90年代电视剧的粗糙画面或60年代的黑白电影,在色彩华丽的4K屏幕上播放的情景。
这应该是完全可行的:把4K视频转换成满是颗粒感的、低分辨率的、甚至是只有黑白两色的视频并不难,之后再通过某个训练出的监督模型来反转这个过程就可以“修正”了。而且,有数不尽的数据训练集,很棒不是吗!
先别急着兴奋——因为能做这事儿的技术还没有出现......不过我们确实离目标越来越近了。
为了更好地实现这个目标,以科技之名,我再一次搬离了布鲁克林来到了湾区。几天后我的日常生活就变成了与Google的机器学习专家进行讨论以及在庞大的软件架构中四处探索。
如果你想跳过技术细节,可以直接跳到总结部分。
本文作者RyanDaul开发了Node.js,一个流行的前端框架
超分辨率的像素递归
众所周知,在美剧《CSI犯罪现场》中使用的缩放技术在现实中并不存在,你无法将照片放大到任意倍数。但可行的是,在放大照片的同时将像素可能构成的合理图形进行推测并呈现,这也是实现我目标的第一步–逆向提高图片的分辨率。
在文献中,这一问题被称之为“超分辨率”问题,是一个科学家们尝试了很久都没有解决的难题。
根据以往的经验,我们认识到只是训练一个卷积模型最小化低分辨率图像与高分辨率图像的平均像素差值无法彻底地解决这一问题。因为这一类模型训练的目的是平均化输入图像和目标图像的整体差值,这就导致了生成的图片非常模糊。
对我们而言,理想模型应该针对不同区域做出一个最佳的选择,尽可能的对细节做出全方位的优化。比如说,输入一张模糊的树的图片,我们希望我们的模型能分别对树的躯干、树枝、树叶进行优化,哪怕原图中没有相应的细节也没有关系。
起初,我们打算用条件型生成对抗网络(conditionalGAN)来解决这个问题,但经过几次失败的尝试后,我们换成了另一种有望解决该问题的新型生产式模型——PixelCNN。(换成PixelCNN不久,SRGAN就发布了,它用GAN来解决超分辨率问题并能输出相当不错的结果。)
PixelCNN和传统的卷积神经网络十分不同,它将图像生成问题转化成了一个像素序列选择问题。核心思想借鉴与于LSTM(长短时记忆网络)这样的门控递归网络,尽管他们通常被应用于单词或字符序列的生成上,但无可否认效果是非常好的。PixelCNN巧妙地构建出一个卷积神经网络(CNN),它能基于先前的像素的概率分布来生成下一个像素,也就是说同时具备了序列模型和卷积神经网络的特点。
vandenOord等人所绘
让我没想到的是,通过PixelCNN生成的图像看起来非常自然。与对抗网络试图在生成与鉴别中找到一个精确的平衡不同,PixelCNN的目标只有一个,所以面对超参数的变化,它有更好的稳健性,也更容易被优化。
对于用PixelCNN解决超分辨率问题的首次尝试,我试图用ImageNet提供的图片进行训练,但事实证明这个目标还是有些太高了。(相较于很多生成式模型使用的CIFAR-10、CelebA或LSUN数据集,ImageNet更加的复杂)我很快地就发现——像素来序列生成图像的过程极其缓慢。
当输出图像的尺寸大于64x64时,生成一张图片的耗时超过数个小时!但当我降低了输出图像的尺寸并使用脸部或卧室类的小型数据集后,就开始慢慢得到了一些振奋人心的结果了。
用名人脸部图像数据集训练出来的超分辨率像素递归模型所生成的高分辨率图像。
左侧为测试数据集所用的8x8低分辨率输入图像。中间为PixelCNN模型所输出的32x32高分辨率图像,右侧是原始的32x32分辨率图像。我们的模型优先整合脸部特征,而后去合成较为逼真的头发与皮肤方面的细节。
就计算资源而言,在Google不会因GPU或CPU的数量而受限,所以如何扩大训练的规模便成为该项目的另一个目标——因为即便采用这些小型的数据集,在单个GPU上完成训练也要花上数周的时间。
异步随机梯度下降(AsynchronousSGD)是最理想的分布式训练方法。使用这种方法,你可以用N台机器,每一台都独立训练同一模型,并在每个时间步长共享一次权重参数。
权重参数被托管在一台单独的“参数服务器”上,该服务器在每个时间步长内都进行“远程过程调用(RPC)”,以获得最新数值并发送梯度更新。
如果整个数据流非常顺畅,就可以通过增加线程的方式线性增加模型每秒内的训练次数。但因为每个线程都是独立训练的,随着线程数的增加会越来越容易导致在当前线程还没有完成一次训练或更新时,它所使用的权重就已经过期了。
如果是为了解决分类问题,这对神经网络的影响不大,把训练的规模扩增到几十台机器不难。但PixelCNN却对过时的梯度极其敏感,这就导致了通过增加硬件的数量来使用异步随机梯度下降算法所带来收益微乎其微。
另一个方法,是用同步随机梯度下降算法(SynchronousSGD)。使用这一方法,所有线程在每个时间步长内进行同步,每次下降的梯度会被平均,这保证不会出现权重过期的问题。
从数学的角度看,它与随机梯度下降算法是一样的,既机器越多,批处理能力越强。但同步随机梯度下降算法(SyncSGD)的优势是,它允许各线程使用更小、更快的批尺寸,从而来增加每秒训练的次数。
但同步随机梯度下降算法也有自己的问题:首先,它需要大量的机器经常进行同步,这就无可避免的会导致停机时间的增加;其次,除非将每台机器的批尺寸设为1,否则它无法通过增加机器的数量来增加每秒训练的次数。最终,我发现对我而言最简单有效的设置是用一台8GPU的机器使用同步随机梯度下降算法进行训练,即便如此每次训练仍需花上数天的时间。
拥有大量计算能力的另一好处是可以对超参数的优化进行大规模的暴力搜索。不确定该使用什么样的批尺寸进行训练?挨个试一遍!在找到论文中所用的配置前,我曾尝试过数百种配置。
另一个难题是如何量化评估结果。如何才能证明我们的图像比基准模型更好?衡量超分辨率效果的传统方法,是对比输出图像与原始图像在对应像素点之间的距离(峰值信噪比,PSNR)。
虽说我们的模型输出的脸部图像在质量上明显更好,但在像素对比上,平均看来还不如基准模型所输出的模糊图像。我们还尝试用PixelCNN本身的相似度测量来证明我们的样本比基准版本有着更佳的像素分布,但同样失败了。最后,我们把这项任务交给了大众——询问参与调查的人哪些图像看上去更真实,这才证明了我们模型的价值。
超分辨率的像素递归论文: