闲话少说,本期深圳 dli 训练营主要用到 digits 和 tensorflow 两个工具。tensorflow 大家都知道,不必介绍。但对 digits 就很陌生了,它是什么呢?
digits 是英伟达为普及深度学习开发的图形化操作界面,简单易用,旨在帮助初学者跨越入门障碍,迅速上手。因此,dli 的入门培训均建议学员从 digits 起步。
感谢三位童鞋朱婷、彭艳蕾与马晓培编译本文花费的心血。
前一节展示了如何设计一个fcn ,来预测每个窗口的某个类的概率分布。显然,窗口的数量取决于输入图像的大小、窗口的大小和扫描输入图像时窗口之间的步长。理想情况下,一个图像分割模型将生成图像中所有像素的概率分布。在实践中如何做到呢?这里将使用fcn paper上的一个方法。
当输入图像遍历卷积化的 alexnet 的连续层时,像素数据的输入被高效地压缩成一组粗化的、更高级的特性表征。图像分割的目的是篡改这些粗化的特征来重建细分类,对输入中的每个像素都是如此。事实证明,这在解卷积层中很容易实现。这些层执行与卷积层相反的操作:给定了卷积输出,一个解卷积层会将输入生成输出,从而给出过滤器的定义。记住,卷积中的跨层(或池化层)定义了处理输入时窗口的滑动距离,以此来衡量下游输出。相反,解卷积层的步幅是衡量上游取样的输出。若选择步幅为4,那么输出将是4倍大!
下一个问题是:给定模型中的最终卷积层,需要对其激活做多大幅度的升采样,才能使输出与输入图像的大小相同?我需要仔细检查每层并写下它的缩放因子。一旦每一层都这样处理,我只需将缩放因子相乘并汇总。让我们看看第一个卷积alexnet层。
conv1的步幅是4,因此缩放因子是1/4。所有层都重复这样做,我确定了总缩放因子在模型中是1/32,如table 2中概述那样。这样,解卷积层的步幅就是32了。
出于严谨,我不得不说,“在所有的空间维度上,一个步幅为s的卷积层,产生的输出都是输入的1 / s”这句话并不是完全正确的。在实践中,向输入加入填充p > 0将会增加激活数。相反,使用大小为 k > 1的核(kernels)将会减少输入端的激活数。在此限制下,如果你为卷积层提供了一个无限长的输入,输入/输出大小的比例在所有的(空间)维度上实际是1 / s。现实中,每一个卷积(池)层的输出被偏移了(p -(k - 1)/ 2)/ s。
例如,考虑conv1:因为这一层在两侧各有100像素的填充,它的输出比无填充的更大。通过上面的公式,我们可以计算出输出的每一侧在理论上有23.75个额外像素。随着添加更多层,这会累积起来。通过向后运行图,可以计算所有层的累计抵消。l1与l2层的组合(i.e. 在caffe术语中,l2是l1的底层,l1、l2 又分别抵消 o1、o2) 会抵消o2 / f + o1,这里f是l2的累积缩放因子。
参考表2对那些计算的汇总
表2:卷积化的alexnet中,遍布连续层的缩放因子和抵消补偿。* 对反卷积层来说缩放因子等于步幅,抵消等于(k - 1)/ 2 p。
表2表明,通过所有conv1到upscore的层时,神经网络的输出被18个像素根据输入做了相应移动。最后一个分割模型中的技巧,是一个修剪网络输出、移除每个边界上额外的18像素的层。这很容易在caffe 的 crop layer 中实现,下面的清单中对这些做了定义。
你可能会注意到,这个版本的alexnet的内边距(padding)比你经常在conv1层遇到的多一点。这背后有两个原因:一个原因是,产生了更大的初始化偏移,以补偿连续层没有吃进图像的缺失。然而,主要的原因是网络以最佳方式处理输入图像的边界 ,以命中网络可接受域的中心,大概就是这样。
现在,我有了从fcn paper复制fcn fcn-alexnet模型所需的一切。我们可以放松一下,欣赏一些synthia数据集里的图像。
synthia 数据集
synthia数据集最初发表在paper [5]。
synthia数据集的样本图像见图9。这些图像展示了用不同的对象类合成的城市场景,比如不同条件下的建筑物、道路、车辆和行人, 如昼夜。有趣的是,图片看起来特真实以致于有时候人们会被它们吸引:嗯,第一张图片上那个在路中间看报纸的人有点反常,这么干很危险。
在 digits 5.0 中,创建一个图像分割数据集十分简单,只需要选中输入和真实样本图像文件夹,点击“create”按键。digits 支持多种标签格式,比如画板图片(它的标签图像中的像素值是彩色画板的指数)和 rgb 图片(每种颜色指示一个类)。
在 digits 中创建数据集之后,你可以探索数据库在视觉上检查它们的内容,见图10。
在digits里训练模型,有数据集和对神经网络的描述就够了。如果你觉得用卷积alexnet太复杂太耗时的话,别烦恼:digits 5.0版有一个模型商店,而且就像你能想象的那样,fcn-alexnet可以从这个模型商店里下载!
但如果你决定要走一条更难的路,去创造自己的模型描述,就可能要找一个合适的权重初始值方案,比如说kaiming方法(另名msra),是目前最前沿的修正流线性单元形式。这个在caffe里很容易实现,只要加上一个权重过滤器 { type: "msra" }指向你的参数层就好了。如果在digits里用这种方法训练模型,很有可能得到像图11的曲线。从图中可以看出,结果并不尽如人意。验证集的准确程度在35%的时候达到最高(意思是说只有在验证数据集里35%的像素被准确地标记出来)。训练损失跟验证损失一致,意味着这个网络(模型)对训练数据集欠拟合。
图11: 用synthia数据训练fcn-alexnet网络(模型),在digits里面利用随机权重初始值方法得到的训练集/验证集的损失和准确率:蓝线--训练集的损失走势,绿线--验证集的损失走势,黄线--模型结果在验证集里的准确率
你可以在一个样例图片上试试运气,让digits帮你完成图片分割的可视化。你会发现网络(模型)会不分青红皂白的把所有元素都归类成“建筑物”,就像图12所示。原来在synthia数据中,“建筑物”是最具代表性的目标类别,而网络(模型)只是懒洋洋地进行了学习并把所有图片元素都标记成了“建筑物”才达到了35%的准确率。那么,一般可接受的处理这种网络(模型)在训练集里欠拟合的方法都有哪些呢?
拉长训练时间:只观察损失曲线的走势,训练过程貌似达到了最高,然而这很可能没什么帮助。网络(模型)很有可能进入了局域最小值而且不能从中脱离出来。
提高学习率同时减少每批量的大小:这样做可以鼓励陷入局域最小值不能自拔的网络(模型)去探索周围环境之外的区域,尽管这样会增大网络(模型)发散的风险。
增加模型大小:这种方法可以加大模型的表现力。
还有一种方法我发现在计算机视觉中应用得非常好:转化学习。更多请继续往下读。
图12:图片分割可视化的样本展示:网络(模型)把所有元素都归类成了“建筑物”。此样本是利用随机权重初始值的方法,在digits里用synthia数据训练fcn-alexnet网络(模型)得到的。
你不用非得从随机初始化权重开始,来训练一个模型。很多情况下,重新利用网络(模型)训练另外一组数据中的得到的认知,会很有帮助。这种方法在计算机视觉里通过cnn网络(模型)尤其奏效,因为很多低级的特征(线路,拐角,形状,纹理)可以马上应用在任意数据中。由于图片分割是在像素水平下做分类分析,从类似ilsvrc2012这样的图片分类数据集里做迁移学习十分合理。利用caffe这样做就变得相当简单---当然需要设立一个或两个陷阱!
记得在alexnet的fc6模型中(图8),权重的形状是4096×9216。在fcn-alexnet的conv6模型中,权重的形状是4096x256x6x6。这其实是一样的权重值,但是由于形状不同,caffe不能自动把权重转交到fcn-alexnet模型里。这个任务可以交给“net surgery(网络手术)”脚本来履行,脚本例子可以在github网站里的digits知识库找到。网络手术脚本的功能在于把参数从全连接层移植到对应的卷积层里。然而,你会发现从公共的digits模型商店里下载提前训练好的模型会更简单一些。图13展示了模型商店的界面:在“fcn-alexnet”旁边,点击“导入”,digits就会下载提前训练好的模型。
图13:digits模型商店
你可能会有另外一个顾虑,那就是怎样初始化早先加入到该文本的升采样层呢?别忘了,此升采样层并不是原始alexnet模型中的一部分。在fcn那篇论文中,作者建议随机初始化对应的权重,然后让网络(模型)学习它们。该篇论文的作者后来意识到,初始化这些权重其实很简单,通过做双线性插值,让升采样层充当放大镜就可以了。在caffe里,这种方法可以通过加上一个权重过滤器 { type: "bilinear" }指向升采样层来实现。
利用一个提前训练好的fcn-alexnet模型,你会注意到,在检测图14这种个别图像的时候,准确率会快速超过90%。检测到9个不同的类别,图形分割结果会变得更有说服力。但你还是会有点失望,因为物体轮廓仍然非常模糊。请继续往下读本文的最后一个章节:如何进一步提高分割模型的精确性和准确性。
图14:图片分割可视化的样本展示。此样本是利用一个提前训练好的ilsvrc2012-alexnet模型,在digits里用synthia数据训练fcn-alexnet网络(模型)得到的。
之前加进fcn-alexnet的升采样层,把conv7的输出值扩大了32倍。在实际应用中,这意着对于每个32×32的像素块,神经网络会做一次预测。这也就解释了为啥目标物体轮廓会那么模糊。那篇fcn文章介绍了另外一个非常棒的主意来解决上面的局限:跳过那些被加入的连接层,直接把pool3和pool4的输出值重新定向到网络的输出值上。由于那些汇总层(pool3, pool4)位于网络的靠后方向,它们就可以在低水平的特征上运作,从而能够抓到更细致的细节。
在一个叫做fcn-8s的网络结构中,那篇fcn文章介绍了一个基于vgg-16的网络,利用这个网络,最后输出结果可以是pool3的总和采样层×8,可以是pool4的采样层×2,还可以是conv7的采样层×4,如图15所示。这就引导出一种网络,能够在更细分的纹路生成预测,向下到8×8的像素块。
图15: fcn-8s跳过连接层的演示图。来源:fcn文献
为了方便使用,用户可以在公共的digits模型商店里下载一个提前训练好的fcn-8s。(你肯定不想自己动手卷积vgg-16)如果你用digits在sythia数据上训练fcn-8s,你会发现仅仅经过几个epoch(时期),验证集的准确率就能超越95%。更重要的是,当你在一个样本图片上做实验,观察digits的高超图片分割可视化的时候,你会看到更为清晰的物体轮廓,像图16中那样。
图16: 图片分割可视化的样本展示。此样本是利用digits在synthia数据上训练fcn-8s网络(模型)得到的。
读过本文之后,怎样开始做图片分割,你应该心里有谱了。digits 5会在12月份的第一个星期发布。访问digits网站继续学习,注册nvidia developer program账号,以便下载版本可用时及时收到通知。
digits在github上是一个可共享的开源项目。如果你想上手实践图片分割技术,请直接访问digits github项目网页,以便得到源代码。
[1] krizhevsky, a., sutskever, i. and hinton, g. e. “imagenet classification with deep convolutional neural networks”. nips proceedings. nips 2012: neural information processing systems, lake tahoe, nevada. 2012.
[2] christian szegedy, wei liu, yangqing jia, pierre sermanet, scott reed, dragomir anguelov, dumitru erhan, vincent vanhoucke, andrew rabinovich. “going deeper with convolutions”. cvpr 2015.
[3] simonyan, karen, and andrew zisserman. “very deep convolutional networks for large-scale image recognition.” arxiv technical report arxiv:1409.1556. 2014.
[4] long, jonathan, evan shelhamer, and trevor darrell. “fully convolutional networks for semantic segmentation.” proceedings of the ieee conference on computer vision and pattern recognition 2015: 3431-3440.
[5] ros, german, laura sellart, joanna materzynska, david vazquez, and antonio m. lopez; “the synthia dataset: a large collection of synthetic images for semantic segmentation of urban scenes.” proceedings of the ieee conference on computer vision and pattern recognition 2016: 3234-3243.
[6] he, kaiming, xiangyu zhang, shaoqing ren, and jian sun “delving deep into rectifiers: surpassing human-level performance on imagenet classification.” proceedings of the ieee international conference on computer vision 2015: 1026-1034.
====================================分割线================================
本文作者:三川