当前位置: 主页 > L生活妝 >和 Google 顶尖工程师一起研究机器学习一整年,这是我的 >

和 Google 顶尖工程师一起研究机器学习一整年,这是我的

作者: 分类: L生活妝 发布于:2020-06-25 浏览(362)


去年,在通过对 TensorFlow 的研究得出一点点心得之后,我申请併入选了谷歌大脑举办的的首届见习项目(Google Brain Residency Program)。该项目共邀请了 24 名在机器学习领域有着不同背景的人士,受邀者将在为期一年的时间里和 Google 的科学家及工程师们在位于山景城的 Google 深度学习研究实验室中共同探索最前沿的深度学习科技。

这个为期一年的项目已经结束了,在此我将就这一年的经历作一个总结与分享。

最初拟定的目标是「修正」老电影或电视剧的画面。想像一下,上世纪 90 年代电视剧的粗糙画面或 60 年代的黑白电影,在色彩华丽的 4K 屏幕上播放的情景。

这应该是完全可行的:把 4K 视频转换成满是颗粒感的、低分辨率的、甚至是只有黑白两色的视频并不难,之后再通过某个训练出的监督模型来反转这个过程就可以「修正」了。而且,有数不尽的数据训练集,很棒不是吗!

先别急着兴奋——因为能做这事的技术还没有出现…… 不过我们确实离目标越来越近了。

为了更好地实现这个目标,以科技之名,我再一次搬离了布鲁克林来到了湾区。几天后我的日常生活就变成了与 Google 的机器学习专家进行讨论以及在庞大的软体架构中四处探索。

如果你想跳过技术细节,可以直接跳到总结部分。

和 Google 顶尖工程师一起研究机器学习一整年,这是我的

众所周知,在美剧《CSI 犯罪现场》中使用的缩放技术在现实中并不存在,你无法将照片放大到任意倍数。但可行的是,在放大照片的同时将像素可能构成的合理图形进行推测并呈现,这也是实现我目标的第一步–逆向提高图片的分辨率。

在文献中,这一问题被称之为「超分辨率」问题,是一个科学家们尝试了很久都没有解决的难题。

根据以往的经验,我们认识到只是训练一个卷积模型最小化低分辨率图像与高分辨率图像的平均像素差值无法彻底地解决这一问题。因为这一类模型训练的目的是平均化输入图像和目标图像的整体差值,这就导致了生成的图片非常模糊。

对我们而言,理想模型应该针对不同区域做出一个最佳的选择,儘可能的对细节做出全方位的优化。比如说,输入一张模糊的树的图片,我们希望我们的模型能分别对树的躯干、树枝、树叶进行优化,哪怕原图中没有相应的细节也没有关係。

起初,我们打算用条件型生成对抗网络(conditional GAN)来解决这个问题,但经过几次失败的尝试后,我们换成了另一种有望解决该问题的新型生产式模型—— PixelCNN。(换成 PixelCNN 不久,SRGAN 就发布了,它用 GAN 来解决超分辨率问题并能输出相当不错的结果。)

PixelCNN 和传统的卷积神经网络十分不同,它将图像生成问题转化成了一个像素序列选择问题。核心思想借鉴与于 LSTM(长短时记忆网络)这样的门控递归网络,儘管他们通常被应用于单词或字符序列的生成上,但无可否认效果是非常好的。 PixelCNN 巧妙地构建出一个卷积神经网络(CNN),它能基于先前的像素的概率分布来生成下一个像素,也就是说同时具备了序列模型和卷积神经网络的特点。

和 Google 顶尖工程师一起研究机器学习一整年,这是我的

让我没想到的是,通过 PixelCNN 生成的图像看起来非常自然。与对抗网络试图在生成与鉴别中找到一个精确的平衡不同,PixelCNN 的目标只有一个,所以面对超参数的变化,它有更好的稳健性,也更容易被优化。

对于用 PixelCNN 解决超分辨率问题的首次尝试,我试图用 ImageNet 提供的图片进行训练,但事实证明这个目标还是有些太高了。(相较于很多生成式模型使用的 CIFAR-10、CelebA 或 LSUN 数据集,ImageNet 更加的複杂)我很快地就发现——像素来序列生成图像的过程极其缓慢。

当输出图像的尺寸大于 64×64 时,生成一张图片的耗时超过数个小时!但当我降低了输出图像的尺寸并使用脸部或卧室类的小型数据集后,就开始慢慢得到了一些振奋人心的结果了。

和 Google 顶尖工程师一起研究机器学习一整年,这是我的

用名人脸部图像数据集训练出来的超分辨率像素递归模型所生成的高分辨率图像。

左侧为测试数据集所用的 8×8 低分辨率输入图像。中间为 PixelCNN 模型所输出的 32×32 高分辨率图像,右侧是原始的 32×32 分辨率图像。我们的模型优先整合脸部特徵,而后去合成较为逼真的头髮与皮肤方面的细节。

就计算资源而言,在 Google 不会因 GPU 或 CPU 的数量而受限,所以如何扩大训练的规模便成为该项目的另一个目标——因为即便採用这些小型的数据集,在单个 GPU 上完成训练也要花上数週的时间。

异步随机梯度下降(Asynchronous SGD)是最理想的分布式训练方法。使用这种方法,你可以用 N 台机器,每一台都独立训练同一模型,并在每个时间步长共享一次权重参数。

权重参数被託管在一台单独的「参数服务器」上,该服务器在每个时间步长内都进行「远程过程调用(RPC)」,以获得最新数值并发送梯度更新。

如果整个数据流非常顺畅,就可以通过增加线程的方式线性增加模型每秒内的训练次数。但因为每个线程都是独立训练的,随着线程数的增加会越来越容易导致在当前线程还没有完成一次训练或更新时,它所使用的权重就已经过期了。

如果是为了解决分类问题,这对神经网络的影响不大,把训练的规模扩增到几十台机器不难。但 PixelCNN 却对过时的梯度极其敏感,这就导致了通过增加硬件的数量来使用异步随机梯度下降算法所带来收益微乎其微。

另一个方法,是用同步随机梯度下降算法(Synchronous SGD)。使用这一方法,所有线程在每个时间步长内进行同步,每次下降的梯度会被平均,这保证不会出现权重过期的问题。

从数学的角度看,它与随机梯度下降算法是一样的,既机器越多,批处理能力越强。但同步随机梯度下降算法(Sync SGD)的优势是,它允许各线程使用更小、更快的批尺寸,从而来增加每秒训练的次数。

但同步随机梯度下降算法也有自己的问题:首先,它需要大量的机器经常进行同步,这就无可避免的会导致停机时间的增加;其次,除非将每台机器的批尺寸设为 1,否则它无法通过增加机器的数量来增加每秒训练的次数。最终,我发现对我而言最简单有效的设置是用一台 8GPU 的机器使用同步随机梯度下降算法进行训练,即便如此每次训练仍需花上数天的时间。

拥有大量计算能力的另一好处是可以对超参数的优化进行大规模的暴力搜索。不确定该使用什幺样的批尺寸进行训练?每个都试一遍!在找到论文中所用的配置前,我曾尝试过数百种配置。

另一个难题是如何量化评估结果。如何才能证明我们的图像比基準模型更好?衡量超分辨率效果的传统方法,是对比输出图像与原始图像在对应像素点之间的距离(峰值信噪比,PSNR)。

虽说我们的模型输出的脸部图像在质量上明显更好,但在像素对比上,平均看来还不如基準模型所输出的模糊图像。我们还尝试用 PixelCNN 本身的相似度测量来证明我们的样本比基準版本有着更佳的像素分布,但同样失败了。最后,我们把这项任务交给了大众——询问参与调查的人哪些图像看上去更真实,这才证明了我们模型的价值。

超分辨率的像素递归 论文

PixColor:着色问题的另一次尝试 和 Google 顶尖工程师一起研究机器学习一整年,这是我的

Slim 的创造者 Sergio Guadarrama 一直在研究图像着色问题,他曾和我描述过这样一个试验:获取一张 224×224×3 的图像,将其置于 YPbPr 色彩空间中(该空间图像的灰度、颜色相互分离),首先将颜色通道降至 28×28×2 的超低分辨率,再用双线性插值法再把颜色通道放大,所得图像与高色彩分辨率的原始图像相比几乎没有差别。

和 Google 顶尖工程师一起研究机器学习一整年,这是我的

这一现象表明,着色问题可以简化成低分辨率颜色预测问题。我原本已準备好彻底放弃 PixelCNN 了,因为显然它无法输出大尺寸的图像,但转念一想其用来生成 28×28×2 的图像还是很可行的,并最终通过使用 4 位颜色数值而非 8 位,进一步的简化了着色问题。

Sergio 构建了一个「美化」神经网络,它能美化低分辨率颜色的图像,并将溢出边界的颜色推回至正确位置–构造仅仅是使用 L2 损失函数将图片与图片进行比较。我们还用一个预训练好的 ResNet 作为辅助神经网络,以避免需要额外添加一个新的损失函数的需求,这中做法我们在超分辨率项目中就使用过。

通过以上所有技巧,不论是通过大众评估还是颜色直方图交叉测量,我们能够在 ImageNet 的训练集上实现最佳的结果。事实证明,一个训练好的 PixelCNN 模型产生的图像具有良好的数据分布性,而且没有发生过任何模型崩溃的问题。

和 Google 顶尖工程师一起研究机器学习一整年,这是我的

由于模型为每个灰度输入的可能着色声明了一个概率分布,我们可以对该分布进行多次取样,以获取同一输入的不同着色。下图用结构相似度(SSIM)很好地展示了分布的多样性:

和 Google 顶尖工程师一起研究机器学习一整年,这是我的

为证明我们的模型可生成不同的样本,我们用多尺度 SSIM 对比了同一输入的两种输出。上图显示了 ImageNet 测试数据集的 SSIM 距离直方图。图中在多个 SSIM 间距上分别显示了每对图像。SSIM 值为 1 表示两张图像完全相同。

该模型还远称不上「完美」,因为 ImageNet 儘管庞大,但不能代表所有的图像。我们的模型在处理非 ImageNet 图像时并不理想。真实的黑白照片(不同于彩色照片转化出的黑白照片)会得出许多不同的分布数据,也会出现很多彩色照片中所没有的物体。比如,Model T 汽车的彩色照片不多,ImageNet 图像集中可能一张都没有。或许採用更大的数据集和更好的数据扩增方法可以改善这些问题。

如果想了解输出图像的质量,可以来看看这些图:

当我们模型处于训练中期时处理的一小组非常难处理的图像:

用我们的模型处理 ImageNet 上的随机数据集:

作为对比,下面是用其他算法来处理同一 ImageNet 测试数据集的结果:

所有完整的细节都可以在我们的论文中找到:

这一年期间,我曾间歇性地投入过许多业余的小项目,儘管它们都没成功,但其中有几个值得一提的项目:

质因数分解一向都是个难题,儘管近期在质数分布领域又有了突破,也依旧很有挑战性。我们的想法是,如果为神经网络提供足够多的训练样本,看看它能否找出一些新的东西?

Mohammad 和我尝试过两种方法:他修改了 Google 机器翻译的 seq2seq 模型,该模型把一个半质大数的整数序列作为输入,并以预测其素因数中的一个做为输出;我则使用一个较为简单的模型,它将定长整数作为输入,并用几个全连接层来预测输入的分类:质数或合数。

但这两种方法最后都只学到了最为明显的规律(如果尾数为 0,那它就不是质数!),最后我们只能抛弃这个想法。

受 Michael Gygli 的项目启发,我想看看能否用一个鉴别器充当它自己的生成器。为此,我构建出一个简单的二元分类卷积神经网络来判断输入的真假。

Michael Gygli 的项目:

既给出一张噪点(拍出来有一点点明显颗粒的照片,这些颗粒称为噪点)图片并让它使用梯度自我更新来生成图像(也称为 deep dreaming),训练的目标是令该网络把「真实」类别的输出达到最大化。该模型通过交替生成「假」实例来进行训练,跟典型的 GAN 中的鉴别器一样,通过升级权重来区分真假实例。

起初我的想法是,因为这个模型不需要像 GAN 那幺複杂的架构设计,所以应该会极大地降低训练的难度。而事实上,这个模型在 MNIST 数据集上的确输出了不错的结果,如下栏所示:每一纵列都是由噪音图片一步步推进成为红色的 MNIST 数值。

和 Google 顶尖工程师一起研究机器学习一整年,这是我的

但我没法在 CIFAR-10 数据集上达到同样的效果,并且它的实用性也极为有限。很遗憾,因为我觉得「对抗做梦(Adversarial Dreaming)」将会是一个很酷的论文标题。

鉴于 PixelCNN 训练一次需要很长的时间,我便想试试能不能用一个训练好的 PixelCNN 模型训练出前馈式、图像对图像卷积神经网络生成器(8×8 至 32×32 尺寸的 LSUN 卧室图片集)。我所设置的训练方法是:在前馈式网络的输出上进行自动回归,在 PixelCNN 下更新权重以便将两张图片的相似率最大化。但这个设计失败了,它生成了非常奇怪的图像:

如前所述,很多模型都不适用于异步随机梯度下降算法。最近,一篇名为 DCASGD 的论文提出了一种解决过时梯度问题的可能方法——在每一个线程更新自己的权重时使用差分向量。如果可以实现,这种方法可以大大减少每次需要的训练时间。不幸的是,我没能在 TensorFlow 上复原他们的结果,也就无法尝试我基于此方法的几个设想,可能还是哪里有 Bug。

DCASGD 的 论文