如何使用深度学习去除人物图像背景

想把自拍背景改成马尔代夫?手把手教你用深度学习分分钟做到
想把自拍背景改成马尔代夫?手把手教你用深度学习分分钟做到
王小新 编译自 TowardsDataScience量子位 出品 | 公众号 QbitAI以前,从照片里抠出人像去掉背景,是要到处求PS大神帮忙的。大神时间有限,抠图这种消耗大量时间又不炫技的事,简直遭人嫌弃。现在好了,你自己可以成为有求必应的AI大神,天天帮妹纸抠图。TowardsDataScience博客最近发布了一篇详细的教程,教你用深度学习移除照片背景。量子位搬运过来翻译了一下:我们要移除怎样的背景呢?这是一个重要的问题,因为一个模型在目标和角度等方面表现得越具体,前后景的分离质量也越好。最初,我们想构建一个通用的背景移除器,能自动识别所有类型图像的前景和背景。但是看到第一个训练模型的效果后,我们决定把应用目标调整到一组特定图像中。因此,我们专注于处理自拍照和人像。△为(差不多是人类吧)自拍移除背景自拍照是一种前景突出且集中的图像,保证目标(脸+上身)和背景之间有良好分离,而且它以一个相当恒定的角度来拍摄同一个目标(或人),其中前景可包含一个或多个“人物”。考虑到这些假设,我们着手于研究相关背景、实施可行方案以及训练数小时的模型,以创建出一种能一键到位的背景移除工具。我们的时间主要花在了训练模型上,但是也没有低估正确部署的重要性。良好的分割模型仍不能与分类模型(如SqueezeNet)一样紧凑,我们还主动检查了服务器和浏览器的部署选项。如果你想进一步了解有关产品部署过程中的更多细节,服务器端见文末相关链接1,客户端见链接2。下面将会详细介绍相关模型的选择及训练过程。语义分割在衡量我们的任务与哪类深度学习和计算机视觉的研究相近时,很快得出最佳选择应该是语义分割任务。其他研究方向,如深度检测分离方法,也具有一定的借鉴意义,但似乎并不是很切合本项目。语义分割、图像分类与目标检测是目前三大最为热门的计算机视觉研究领域。分割实际上也是一种分类任务,将每个像素划分到某一类中。与图像分类或目标检测有所不同,分割模型真正展现了一些计算机对图像的“理解力”,不仅提出了“这张图中有一只猫”,而且在像素级上指出了猫的位置和特性。那分割任务的实现原理是什么?为了更好地理解它,我们查阅了这个领域的一些早期研究工作。最早的想法是采用一些已有的分类网络,如VGG和Alexnet。VGG网络于2014年提出,是一种用于图像分类的先进模型,由于其简单直观的结构,目前十分有用。在检查VGG低网络层时,我们注意到分类目标周围的激活值很高。高网络层有着更高的激活值,但是由于经过重复的池化操作,其本质变得粗糙。基于这些理解,我们猜测,对分类模型进行一些调整后,也可用于目标定位或分割。早期的语义分割研究是和分类算法一起出现的。文末链接3的文章中,展示了一些利用VGG网络得到的粗糙分割结果。输入图像高网络层的激活情况:公交车图像的分割效果,浅紫色(29)为公交车类别进行双线性上采样后:更为平滑的激活情况得到这些结果,只需将全连接层转换回(或保持)其原始形式,保持其空间特征,进而获得一个全卷积网络。在上面例子中,将一个分辨率为768×1024的图像输入到VGG,获得一个大小为24×32×1000的网络层。其中多次池化后的图像大小为24×32,网络类别数为1000,据此可导出上面的分割效果图。为了使预测效果更平滑,研究人员使用了双线性上采样层。在FCN论文(链接4)中,研究人员改进了上述思路。沿着网络方向,把一些层连接在一起,这提供了更丰富的解释。根据上采样率把它们分别命名为FCN-32、FCN-16和FCN-8。FCN网络层间连接示意图在网络层之间添加一些跳跃连接(skip connection),允许编码器从原始图像中预测出更精细的信息。后续的训练可能会大幅提高效果。这种连接方式并不像所估计的那么糟糕,也证实了深度学习方法在语义分割领域确实具有发展空间。FCN分割效果(图来自原论文)FCN网络提出了分割的概念,之后研究人员为此任务尝试了不同的结构。但是,其主要思路保持相似,即借鉴已有结构、加入上采样和添加跳跃连接,这些方法仍在新模型中表现突出。关于语义分割的发展综述可以移步量子位编译过的“语义分割中的深度学习方法全解:从FCN、SegNet到各版本DeepLab”和“卷积神经网络在图像分割中的进化史:从R-CNN到Mask R-CNN”,可以看出大多数网络都使用了编码器-解码器结构。回到本项目进行一些调研后,我们选定了三种可使用的模型,分别是FCN、U-net和Tiramisu(不要往甜品提拉米苏上想……它是极深的编码器-解码器结构,详情见文末链接5)。我们也考虑了mask-RCNN网络,但其网络实现似乎超出了本项目的范围。FCN的效果似乎没有预想的那么好,所以我们不考虑这个模型。我们还测试了另外两个提到的模型,发现Tiramisu网络在CamVid数据集上的分割效果较优,而且U-net也展现了其紧凑性和实时应用的优势。在网络实现上,U-net网络可利用keras库直接实现,Tiramisu网络也是可实现的。开始时,我们使用了Jeremy Howard在旧金山大学深度学习课程中最后一节中给出的Tiramisu网络代码实现(链接6)。掌握这两个网络后,我们开始利用一些数据集来训练模型。在我们首次尝试Tiramisu网络后,我们发现该模型有很大的应用潜力,因为它能捕捉图像中的锐利边缘。另一方面,U-net的效果不佳,分割图不忍直视。Tiramisu和U-net分割效果比较确定数据集在设定好模型后,我们开始寻找合适的数据集。与分类和检测数据集不同,分割数据并不常见,而且不可能通过人工标注来实现。常见的分割数据集有COCO数据集(包括大约8万张图像,有90个类别)、VOC pascal数据集(包括1.1万张图像,有20个类别)以及较新的ADE20K数据集。COCO:http://mscoco.org/VOC pascal:http://host.robots.ox.ac.uk/pascal/VOC/ADE20K:http://groups.csail.mit.edu/vision/datasets/ADE20K/我们选用COCO数据集,因为该数据集中包含更多的“人”像,这是本项目的目标类别。根据实际任务,我们仔细考虑了是只使用极其相关的图像类别,还是使用更加通用的数据集。一方面,使用一个具有更多图像和类别的通用数据集会使模型具有更好的泛化能力;另一方面,一晚上的训练时间就能遍历15万张图片。如果将整个COCO数据集输入到模型,每个图像平均会被输入两次,因此最好进行适当修剪。此外,这样做可得到一个使任务目标更集中的模型。还需要提到,Tiramisu网络最初是在CamVid数据集上训练的,但是CamVid数据集存在一些缺点,最主要是其图像非常单调,所有图像都是从汽车上拍的路面图。这就很容易理解,用这样的数据集来训练模型,即使图像中包含人物,对此任务也没有任何好处,所以简单实验后,我们决定寻找更合适的数据集。CamVid数据集的一些图像COCO数据集提供了可直接调用的API接口,据此我们可以准确地知道每张图像中的物体类别(根据预设定的90个类别)。经过几次实验后,我们决定稀释此数据集:首先我们挑出带有人物的所有样本,得到4万张图像;然后再删去图中有多个人物的样本,留下只有1人或2人的图像,这是训练模型的合适数据集;最后只留下人物形象占据20%~70%面积的图像样本,删去人物形象过小的图像或是一些奇怪的畸形样本。最终的数据集包含1.1万张图像,在这个阶段样本量已经足够。左边为优良图像;中间包含太多人物;右边的人物形象过小。Tiramisu模型上面已经提到,Jeremy Howard的课程中详细地介绍了Tiramisu模型。它的全名为“100层Tiramisu模型”,听起来像是一个庞大的模型,实际上只有900万个参数,十分紧凑。相比之下,VGG-16网络有多达1.3亿个参数。DenseNet是一种新提出的图像分类模型,其所有网络层都是互连的。Tiramisu模型基于DenseNet发展起来的,而且与U-net网络类似,向上采样层添加了跳跃连接。你应该还记得,这种结构与FCN论文中的提出思路是一样的,即使用分类结构和上采样层,并添加跳跃连接来微调网络。经典的Tiramisu结构DenseNet模型可以看作是Resnet模型的一种自然演化版本,它不只是“记住”了下一网络层之前的每个网络层,而是记住了整个模型中的所有网络层。这些连接称作快捷连接(highway connections),它导致了滤波器数量的逐层膨胀,前后数量差定义为“增长率”。Tiramisu模型的增长率为16,因此每层都增加16个新的滤波器,直到获得具有1072个滤波器的网络层。你可能会想,100层Tiramisu模型应该具有1600个滤波器,可是实际中利用上采样层去掉了一些滤波器。Densenet模型示意图,低层滤波器堆叠后贯穿整个模型。模型训练我们使用原论文中的默认参数来训练本模型,分别是标准的交叉熵损失和RMSProp优化策略(学习率为0.001和小衰减值)。在1.1万张图像中,70%分为训练集,20%分为验证集,10%分为测试集。以下所有图像均来源于上面设定的测试集中。为了使本项目训练方案与原论文保持一致,我们将epoch设为500张图像,这样也能在每次结果改进后定期保存模型,因为原论文中使用的CamVid数据集包含少于1000张图像,而我们拥有更大的训练数据集。此外,我们只训练了两个类别,分别是背景和人物,而原论文中共有12个类别。我们先尝试训练COCO数据集中的一些类别,但是发现对最终的训练效果没有太大的提升。数据问题数据集中的一些缺陷样本影响了评估分值:1.动物。模型有时会分割出动物图像,这导致了IoU(intersect over union)值降低。把动物添加到分割任务中,不管是同一个类别或作为新类别,都可能提高模型性能。2.身体部位。我们通过编程过滤得到本项目数据集,因此无法判断人物图像包含有整个人像,还是只出现某些部位,如手或者脚。这些身体部位图像不属于本项目范围,但在数据集中仍然存在。一张用手拿着食物逗猫的照片,属于缺陷样本。3.手持物体。数据集中的许多图像都是有关运动的,经常会出现棒球棒、网球拍和滑雪板等装备。在分割此类物体时,训练模型会弄混。和第一种缺陷相同,将它们归入同一类或是作为新类别,都将有助于提高模型性能。手持运动器材的人物图像4.粗糙的真实标注。COCO数据集以多边形进行标注,而不是精确到像素级。这种精度有时满足要求,但有些图像的真实标注非常粗糙,可能会阻碍模型的精细化学习。真实标注很粗糙的图像示例结果我们对模型结果很满意,但是还不够完美:模型在测试集上的IoU值达到84.6,目前最高可达85。要稳定到这个值很困难,因为对不同数据集和分割类别,性能略有波动。有些类别本身较容易划分,如房屋和道路,大多数模型能轻松达到IoU值为90的效果。更具挑战性的类别为树木和人类,大多数模型分割这两个类别时,一般只能达到IoU值约为60的效果。为了估计困难程度,本项目构建的网络只专注于单一类别的特定类型图像。我们希望这个模型能投入到实际应用中,目前的性能仍不满足上线部署的要求。但是我们认为此时应该先停下来讨论所得结果,因为大约有一半图像取得了良好的分割效果。下面是一些良好的示例,体现了模型的分割性能:左边为原图像,中间为真实标注,右边为测试分割效果调试与记录在训练神经网络时,有个重要内容叫做调试。在刚开始工作时,很想直接拿到数据和神经网络,就开始训练,看看会得到什么样的输出效果。然而,我们发现,跟踪每次变化非常重要,需要自主制定工具来检查每个步骤中的输出结果。下面是一些常见的问题,以及应对方法。1. 早期问题。模型可能还没开始训练,这可能是存在一些本质原因,或是预处理过程出现错误,如忘记标准化某个数据块。总之,简单的可视化输出能让你更快找出问题,这方面的更多内容可参考“神经网络中37个常见问题”(链接7)。2. 调试网络本身。在确保没有出现关键问题后,网络将会根据预定义的损失函数和指标开始训练。在分割过程中,主要评估指标为IoU值(intersect over union)。经过几次尝试后,我们决定使用IoU值作为模型的主要指标,而不是先前的交叉熵损失。另一个有用的操作为在每个epoch输出当前模型的预测效果,链接8给出了调试机器学习模型的几个建议。请注意,IoU值不是keras中标准的损失函数,但是很容易找到一些开源代码。我们使用了shgidi的代码(链接9)来绘制出每个epoch的损失值和模型预测效果。3. 机器学习版本控制。在训练模型时,要确定很多参数,其中有些很难理解。我们也还没找到合适的方法,只能贴出我们的详细参数单,并利用keras回调功能自动保存最佳模型(见下文)。4. 调试工具。在完成上述工作后,我们可以检查下每步结果,但是不能无间断地检查。因此,最重要的是要将上述步骤结合在一起,并创建一个Jupyter手册,这能让我们无间断地加载每个模型和每张图像,并快速地检查所有结果。通过这样,我们可以很容易地分析出模型间的差异、未知误区以及其他问题。通过参数调整和额外训练,逐步提高了模型性能。从左到右,模型性能有很大提升。为了保存目前在验证集上具有最佳IoU值的模型,我们利用了keras库中的callbacks函数。callbacks = [keras.callbacks.ModelCheckpoint(hist_model, verbose=1,save_best_only =True, monitor= ’val_IOU_calc_loss’), plot_losses]除了对可能的代码错误进行调试外,我们还注意到,模型失误是“可预测的”,如把身体的一部分“切掉”、人物主体被“侵蚀”、身体部位不必要的延伸、较弱的光线、图像质量较差以及一些其他细节。在添加不同数据集中的特定图像后,已经解决了这里面的一些问题,但是待解决的剩余问题仍然是一个很大的挑战。为了提升后续模型的分割效果,我们将针对一些“困难”(效果不佳)的图像使用图像增强操作。在上面,我们已经提到这个问题,即模型对部分数据集的处理失误。下面给出一些具体的模型失误例子。1. 衣服。很深或很浅的衣服有时会被理解为背景;2. “侵蚀”。即使是优良结果,人物主体也会出现“侵蚀”。主体出现“侵蚀”的例子3. 光线。图像中能经常见到弱光线和模糊的样本,但是COCO数据中没有这种情况。因此,除了要处理模型中这些常见问题外,我们还不能解决更高难度的图像集。这可通过获取更多数据和额外加入数据增强,来改进模型效果。同时,最好不要在弱光环境下使用这个应用程序。弱光条件下的图像分割效未来展望更深入的训练在训练数据上训练300个epoch后,得到了这个产品模型。在此期间,该模型开始出现过拟合效应。我们在临近产品发布时才得到这些结果,因此还没有结合数据增强的基本操作。将图像大小调整为224X224后,我们开始训练该模型。接下来,会使用更多的数据和更高分辨率的图像来训练模型,以期提高效果,其中COCO数据集中的原始图像大小约为600X1000。CRF和其他增强方法在某些阶段,我们发现模型在处理人物边缘时存在噪声。CRF方法(条件随机场)可以用来改进这一方面。博文(链接9)中结合CNN网络和CRF方法实现了一些案例。可是,这种方法不适用于本项目,也许当结果更粗糙的时候会有所提升。修边即使在目前结果中,分割效果仍不完美。对头发、精致的衣服、树枝和其他精细物体的分割效果仍然有提升空间,实际上是因为实际分割中不包含这些细节。分割如此细微图像的任务称为修边(Matting),这是一个不平常的挑战。下面是修边研究的最新成果,在今年年初发表在NVIDIA会议上。修边示例,输入也包括中间的trimap图。修边任务与图像处理的其他相关任务不同,因为其输入不仅包括原图像,还包括一个trimap图(给出图像边缘的粗略划分,包括前景、背景和待求未知区域)。这样,就将修边任务成了一种“半监督”问题。我们使用模型得到的分割图作为输入的trimap图,尝试实现修边操作,但是未达到显著效果。另一个问题,是缺乏合适的训练数据集。总结正如开头提到的,我们的目标是建立一个有意义的深度学习产品。参考链接1和链接2中的教程,部署任务变得更容易和更快捷。另一方面,训练出一个合适模型相当复杂,特别是想要尽快得到最佳模型时,需要更仔细的规划、调试和记录结果。要平衡好研究和尝试新事物之间,以及单调训练和改进之间的关系,是不容易的。由于使用深度学习方法,我们总会感觉,只需简单改动,就能得到理想的最佳模型,或许一次搜索或某篇论文就会指引我们找到它。但在实际中,真实的改进效果往往是从先前模型中不断“挤出”新思路。如上所述,我们仍觉得,根据已有工作还可发展出很多新想法。总而言之,我们在这个工作中获得了很多乐趣,这对几个月前的我们像科幻小说一样。非常希望能和大家一起讨论或解答相关问题相关链接1. 服务器端产品部署:/@burgalon/deploying-your-keras-model-fb2. 客户端产品部署:https://becominghuman.ai/deploying-your-keras-model-using-keras-js-2e5a29589ad83.利用VGG网络实现图像分割:https://warmspringwinds.github.io/tensorflow/tf-slim//upsampling-and-image-segmentation-with-tensorflow-and-tf-slim/4.FCN网络原论文:https://arxiv.org/pdf/.pdf5. Tiramisu网络论文:https://arxiv.org/pdf/.pdf6. Tiramisu网络的代码实现:http://files.fast.ai/part2/lesson14/7. 神经网络中37个常见问题:/37-reasons-why-your-neural-network-is-not-working-78. 如何调试神经网络:/how-to-debug-neural-networks-manual-dc2a200f10f29. 结合CNN网络和CRF方法的图像分割:https://warmspringwinds.github.io/tensorflow/tf-slim//image-segmentation-with-tensorflow-using-cnns-and-conditional-random-fields/10. 在你自己做出背景移除器之前,可以试试作者们的demo:https://greenscreen-/最后,量子位想说,本教程适合学习,如果你只是想通过抠图讨女朋友欢心,Prisma团队后来推出的新应用Sticky是个不错的选择—完加入社群量子位AI社群8群开始招募啦,欢迎对AI感兴趣的同学,加小助手微信qbitbot2入群;此外,量子位专业细分群(自动驾驶、CV、NLP、机器学习等)正在招募,面向正在从事相关领域的工程师及研究人员。进群请加小助手微信号qbitbot2,并务必备注相应群的关键词~通过审核后我们将邀请进群。(专业群审核较严,敬请谅解)诚挚招聘量子位正在招募编辑/记者,工作地点在北京中关村。期待有才气、有热情的同学加入我们!相关细节,请在量子位公众号(QbitAI)对话界面,回复“招聘”两个字。量子位QbitAI''
追踪AI技术和产品新动态
本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。
百家号 最近更新:
简介: 追踪AI技术和产品新动态
作者最新文章近日,Medium 上出现了一篇题为《Background removal with deep learning》的文章,讲述的是 greenScreen AI 在利用深度学习去除图像人物背景方面的工作与研究。本着开发一个有意义的深度学习产品的初衷,他们把任务锁定在了自拍和人物肖像上,并最终在已稀释的 COCO 数据集上取得了 84.6 的 IoU,而当下最佳水平是 85。简介在研究机器学习的最近几年里,我一直想着打造真正的机器学习产品。数月之前,在学习完 Fast.AI 上的深度学习课程之后,我清晰地意识到机会来了:深度学习技术的进步可以使很多之前不可能的事情变成现实,新工具被开发出来,它们可以让部署变的比以前更便捷。在前面提到的课程中,我结识了 Alon Burg,他是一位很有经验的网页开发者,我们达成一致来共同完成这个目标。我们一起设定了以下目标:1. 提升我们的深度学习技巧2. 提升我们的人工智能产品部署技巧3. 开发一款有用的、具有市场需求的产品4. 有趣(不仅对我们而言,也对用户而言)5. 分享我们的经验基于以上目标,我们探索了一些想法:1. 之前没有被做过的(或是没有被正确做过)2. 规划和实现的难度不大——我们计划两到三个月完成,每周一个工作日。3. 具有简单并且吸引人的用户接口——我们旨在做出人们能够使用的产品,而不仅仅停留在演示的目标上。4. 要有方便获取的训练数据——众所周知,有时候数据比算法更加昂贵5. 使用到前沿的深度学习技术(要是那种还未被 Google Allo、亚马逊以及其云平台上的合作者商业化的技术),但是也不能太前沿(这样的话我们可以在网络上找到一些例子)6. 要拥有实现「生产就绪」(production ready)结果的潜力我们的前期想法是做一些医疗项目,因为这个领域与我们内心所设想、所感受的东西更相近,医疗领域还有着大量唾手可得的成果。然而,我们意识到我们可能会在收集数据上碰到一些问题,也有可能会触及到法律,这是我们最后放弃医疗项目的原因。我们的第二个选择就是图像背景去除。背景去除是一个很容易手动或者半手动实现的任务(Photoshop,甚至 Power Point 都有这类工具),如果你使用某种「标记」或者边缘检测,这里有一个实例(/)。然而,全自动化的背景去除是一个相当有挑战性的任务,据我们所知,目前还没有一个产品具有令人满意的效果,尽管有人在尝试。我们要去除什么背景呢?这是一个重要的问题,因为就对象、角度而言,一个模型越是具体,分离的质量就会越高。我们的工作开始时,想法很庞大:就是要做一个通用的能够识别所有类型的图像中的前景和背景的背景去除器。但是当我们训练完第一个模型之后,我们明白了,集中力量在某类特定的图像集上会更好一些。所以,我们决定集中在自拍和人物肖像上。人物(类人)肖像的背景去除自拍有明显的和更为集中的前景(一个或者多个人物),这使得我们能够很好地将对象(人脸+上身)与背景分离,同时还有一个相对固定的角度,以及总是同一个对象(人物)。有了这些假设之后,我们踏上了研究、实现以及花数小时训练得到一个简便易用的背景去除产品的旅程。我们的主要工作是训练模型,但是我们不能低估正确部署的重要性。好的分割模型仍然不如分类模型那么紧密(例如 SqueezeNet),我们主动地检查了服务器模型和浏览器模型的部署选择。如果你想阅读关于我们产品的部署过程的诸多细节,你可以去浏览我们关于服务器端和客户端的博文。如果你想读到更多关于模型和训练的东西,那就继续吧。语义分割我们查看了和我们的任务类似的深度学习和计算机视觉任务,不难发现,我们的最佳选择就是语义分割任务。其他策略,比如通过深度检测来做分割也存在,但是对我们的目标而言并不成熟。语义分割是一个计算机视觉经典任务,它是计算机视觉领域的三大主题之一,其他两个分别是分类和目标检测。从将每一个像素归为一个类别来讲,分割实际上也是一个分类任务。然而与图像分类和目标检测不一样的是,分割模型事实上表现出了某种对图像的「理解」,在像素层面上不仅能区分「这张图像上有一只猫」,还能指出这是什么猫。所以,分割是如何工作的呢?为了更好地理解它,我们必须梳理一下这个领域的一些早期工作。最早的想法是采用一些早期的分类神经网络,例如 VGG、Alexnet。回溯到 2014 年,VGG 是图像分类任务中最领先的网络,它在今天也相当有用,因为它有着简单直接的结构。在查看 VGG 的前几层的时候,你可能会注意到从每一条目到类别都有高激活值。更深的层甚至还有更高的激活值,但是由于其重复池化动作,本质上它们是很粗糙的。有了这些理解之后,可以假定,在经过一些处理之后,分类训练也能用在寻找/分割对象的任务中。早期的语义分割结果是和分类算法一起出现的。在本文中,你可以看到我们使用 VGG 得出的一些简单的分割结果:后边层的结果:对 buss 图像的分割,浅紫色区域(29)代表校巴类别双线性上采样之后:这些结果仅来自于简单地将全连接层转换(或者修改)为它最初的形态,修改它的空间特征,得到一个全连接的卷积神经网络。在上面的例子中,我们把一张 768*1024 的图像输入到 VGG,然后就得到了 24*32*1000 的一个层,24*32 是图像的池化版本,1000 是 image-net 的类别数目,从这里我们能够得到上述的分割结果。为了使预测结果更加平滑,研究者还使用了简单的双线性上采样层。在全连接神经网络的论文中(Fully Convolutional Networks for Semantic Segmentation,https://arxiv.org/abs/),研究者提升了上述的想法。为了具有更加丰富的解释,他们把一些层连接在一起,根据上采样的比例,它们被命名为 FCN-32、FCN-16 和 FCN-8。在层之间添加一些跳跃连接使得从原始图像到编码的预测更加精细。进一步训练模型会让结果更好。这个技术表现出的效果并不像预料中的那么差劲,并且证明利用深度学习进行语义分割确实是有潜力的。FCN 论文中全连接神经网络的结果。全连接神经网络开启了分割的概念,研究者为这个任务尝试了不同的架构。主要思想是类似的:使用已知的架构、上采样以及使用跳跃连接,这些仍然在新模型中占据主要部分。回到我们的项目经过调研之后,我们选择了三个合适的模型开始研究:FCN、Unet 以及 Tiramisu——这是一个非常深层的编码器-解码器架构。我们还在 mask-RCNN 上有一些想法,但是实现这个似乎不在我们这个项目的范围之内。FCN 看上去并不相关,因为它的结果和我们想要的结果(即便是初始点的结果)不一样,但是我们提到的其他两个模型却表现出了不错的结果:CamVid 数据集上的 tiramisu 模型和 Unet 模型主要的优点是紧凑性和速度。在实现方面,Unet 是相当直接的(使用 keras),并且 Tiramisu 也是可实现的。我们使用 Jeremy Howard 上一次的深度学习课程中对 Tiramisu 较好的实现来开始我们的项目。我们使用这两个模型开始在一些数据集上训练。不得不说的是,当我第一次训练完 Tiramisu 之后,发现它的结果对我们而言更有优势,因为它有能力捕捉图像中的尖锐边缘,然而,Unet 看上去并不是那么好,甚至有一点搞笑。Unet 的结果稍有逊色数据在利用模型设定好我们的基础目标之后,我们就开始寻找合适的数据集。分割数据并不像分类和检测那样常见。此外,人工标注也不现实。最常用于分割的数据集是 COCO(http://mscoco.org/),这个数据集大约包括 8 万张图像(有 90 类),VOC pascal 数据集有 1.1 万张图像(有 20 类),以及更新的数据集 ADE20K。我们选择使用 COCO 数据集,因为其中「人」类的图像更多,这恰好是我们的兴趣所在。考虑到我们的任务,我们思考是否仅仅使用和我们的任务超级相关的图像,或者使用更加通用的数据集。一方面,一个更通用的数据集拥有更多的图像和类别,这使得我们能够应付更多的场景和挑战。另一方面,一次彻夜不歇的训练可以处理大约 15w 张的图像。如果我们在整个 COCO 数据集上引入模型的话,结果会是,模型处理每张图像的平均次数是 2 次,所以稍作修改是有益处的。此外,这会使得模型更聚焦于我们的目标。另一件值得提及的事情是 Tiramisu 模型最初是在 CamVid 数据集上训练的,它有一些缺陷,但最重要的是其图像很单调:所有图像都是道路上的车辆。你不难理解,从这样的数据集中学习对我们的任务并没有好处(即使图像中包含了人物),所以在短暂的实验之后,我们便改变了数据集。CamVid 数据集中的图像COCO 数据集附带相当直接的 API,这些 API 可以让我们知道每一张图像中是哪种类型的对象。在一些实验之后,我们决定稀释一下数据集:首先我们过滤出其中有人的图像,最终得到了 4 万张。然后,丢弃了有很多人在里面的图像,留下了只有一个或者两个人的图像,因为这是产品所需要的。最后,我们留下了 20%-70% 被标注为人的图像,去掉那些在背景中有一小部分是人的图像,还有那些具有奇怪的建筑的图像也一并去掉了(不过不是所有的都去掉)。我们最终得到的数据集只有 1.1 万张图像,我们觉得在目前这个阶段已经够用了。左:正常图像;中:有太多东西的图像;右:目标太小了。Tiramisu 模型之前说过,我们使用了 Jeremy Howard 的课程中讲述的 Tiramisu 模型。尽管它的名字「100 层 Tiramsiu」显得它很庞大,但是实际上它却是一个相当经济的模型,仅仅有 900 万个参数。相比之下,VGG-16 有 130M 个参数。Tiramisu 模型是基于 DensNet 的,DensNet 是一个最新的图像分类模型,所有的层都是相互连接的。此外,与 Unet 类似,Tiramisu 模型在上采样层上添加了跳跃连接。回想一下前文你就会发现,这个架构和 FCN 中呈现的思想是一致的:使用分类架构、上采样并且为精调添加跳跃连接。通用的 Tiramisu 架构DenseNet 模型可以看作是一个自然进化的 Reset 模型,但是,DenseNet 不是简单地把一层的信息「记忆到」下一层,而是在整个模型中记忆所有层。这些连接被称作高速连接。它造成了过滤器数目的膨胀,这被定义为「增长率」。Tiramisu 的增长率是 16,所以我们会给每一层添加 16 个过滤器,直至到达具有 1072 个过滤器的那一层。你也许期望着具有 1600 个过滤器的那一层,因为这是 100 层的 Tiranisu,然而,上采样会舍弃一些过滤器。DenseNet 模型框架——在整个模型中,前边层的过滤器是堆叠的训练我们遵循原始论文中的计划来训练模型:标准交叉熵损失,学习率为 0.001 的 RMSProp 优化器,较小的衰减。我们将数据的 70% 用来训练,20% 用来验证,10% 用来测试。下面的所有图像都来自我们的测试集。为了让我们的训练过程与原始论文一致,我们把 epoch 大小设置为 500 张图像。这也使得我们能够在结果中的每一次进展中周期地保存模型,因为我们是在很大的数据上训练模型的(那篇文章中用到的 CamVid 数据集仅有不到 1000 张图像)。此外,我们训练的模型只有两个类:背景和人物,然而那篇论文中的模型有 12 个类。我们首先尝试着在部分 COCO 类上训练,但是我们随后就发现这对我们的训练没多大作用。数据问题一些数据集的缺陷阻碍了我们模型的评分:动物—我们的模型有时候会分割动物,这也自然导致了较低的 IOU,会将动物添加到我们的主要分类中。身体部分—由于我们有计划地过滤了我们的数据集,所以没办法区分图像中的人是一个真实的人还是某个身体部位,例如手、脚。这些图像虽然不在我们的考虑范围之内,但是还是会处处出现。动物、身体部分以及手持物体手持物体——数据集中的很多图像都是和运动相关的。到处都是棒球拍、羽毛球拍以及滑雪板。从某种程度来说,我们的模型已经困惑于应该如何分割它们。与动物的例子一样,我们认为将它们添加到主分类或者独立的分类中会对模型的性能有所帮助。有一个物体的运动图像粗糙的真实情况——COCO 数据集中的很多图像都不是按照像素标注的,而是用多边形标注的。有时候这很好,但是其余时候真实情况过于粗糙,这可能会阻碍模型学习一些微妙的细节。真实情况很粗糙的图像结果我们的结果是令人满意的,尽管不太完美:我们在测试集上达到了 84.6 的 IoU,而当下最佳水平是 85。但是这个数字是微妙的:它会随着不同的数据集和类别浮动,有的类别本身就很容易分割,例如房屋、道路,在这些例子中很多模型都能很容易地达到 90 的 IoU。其他的更具挑战性的类别是树和人物,在这些类别中很多模型只能达到大约 60 的 IoU。为了克服这个困难,我们帮助我们的网络集中在某个单独的类别上,并且在有限种类型的图像中。我们仍然没有觉得我们的工作是「产品就绪」的,就像我们当初想让它成为的样子一样,但是现在恰恰是停下来讨论我们的结果的时间,因为在大约 50% 的图像上都能给出较好的结果。下面是一些很好的实例,给人的感觉就是一个不错的应用。图像、真实数据、我们的结果(来自我们的测试集)调试和日志训练神经网络时非常重要的一部分就是调试。立马开始是很吸引人的,得到数据和网络,开始训练,看一下会得到什么结果。然而我们会发现,追踪每一个动作是非常重要的,这样就能够为我们自己创建能够检查每一步的结果的工具。这里是一些常见的挑战以及我们的应对方法:前期问题—模型可能不能训练。有可能是因为一些本质原因,或者是一些预处理的错误,例如忘记了标准化某些数据块。无论如何,对结果的简单可视化是很有帮助的。关于这个主题,这里有一篇博客(/37-reasons-why-your-neural-network-is-not-working-7)。调试网络本身—在确定没有关键问题之后,训练通过预定义损失和指标开始。在分割中,主要举措是 IoU——在联合中交叉。把 IoU 作为模型(而不是交叉熵损失)的主要手段确实花了一些时间。另一个有帮助的实践是在每个 epoch 展示一些模型的预测。这里有一篇调试机器学习模型的好文章(/how-to-debug-neural-networks-manual-dc2a200f10f2)。注意,IoU 并不是 keras 中标准的指标/损失,但是你可以轻易在网上找到,比如这里(/udacity/self-driving-car/blob/master/vehicle-detection/u-net/README.md)。我们还使用这个要点绘制损失和每个 epoch 的预测。机器学习版本控制—在训练一个模型的时候,会面临很多参数,其中的一些是很微妙的。不得不说的是,除了热切地写下我们的配置(如下,使用 keras 的 callback 写下最佳模型),我们仍然没有发现完美的方法。调试工具—在做完上述所有步骤之后,我们就可以逐步检查我们的工作了,然而并不是无缝的,所以,最重要的就是把上述所有步骤结合在一起,创建一个 jupyter notebook 会让我们无缝地加载每一个模型和每一张图片,并且快速检查结果。这样的话我们就能容易地发现模型之间的不同、陷阱以及其他问题。这里是我们通过调整参数和额外训练之后得到的模型性能提升的例子:保存目前验证过程中的最佳模型:(keras 提供了一个非常好的 callback 函数,让这一步骤变得容易多了)callbacks = [keras.callbacks.ModelCheckpoint(hist_model, verbose=1,save_best_only =True, monitor= ’val_IOU_calc_loss’), plot_losses]除了对可能出现的代码错误的正常调试之外,我们还注意到模型的错误是「可预测的」,就像把看似在正常身体之外的身体部分切掉一样,大型分段上的「缺口」,非必要的扩展身体部分,糟糕的光照,低质量图像,以及很多细节。其中的一些注意事项在从数据集中添加具体的图片的时候就已经被处理了,但是其他的仍然是有待解决的难题。为了提升下一个版本的结果,我们会在「硬」图像上为我们的模型使用具体的扩展。我们在前面的数据集问题早就提到过这个问题。现在让我们来了解一下我们模型中的困难吧:1. 衣服—非常深色或者浅色的衣服容易被解释为背景2.「缺口」—即使是好的结果,里面也会有缺口衣服和缺口3. 光照——较差的光照条件和模糊在图像中是很常见的,然而 COCO 数据集中并不是这样的,所以,除了模型要处理的这些事情中的正常困难以外,我们的模型甚至还没有为更硬的图像做准备。这可以通过得到更多的数据来解决,此外,最好不要在晚上使用我们的应用。较差的光照条件的实例进一步处理的选项进一步的训练我们的产品结果来自 300 个 epoch 的训练。在这一阶段之后,这个模型开始过拟合了。我们的这些结果已经非常接近发布的版本了,所以也不可能再去做数据扩增了。在将图像调整到 224*224 之后,我们开始训练模型。使用更多更大的数据集进行进一步的训练也有希望提升结果(原始尺寸是 COCO 数据集上的 600*1000 的图像)。CRF 和其他的增强在某些阶段,我们发现我们的结果在边缘有一些噪声。能够精调这种问题的一个模型就是 CRF。在下面这篇博客中,作者展示了使用 CRF 的一个实例(http://warmspringwinds.github.io/tensorflow/tf-slim//image-segmentation-with-tensorflow-using-cnns-and-conditional-random-fields/)。然而,这对我们的工作并不是很有用,也许是因为它通常在结果比较粗糙的时候才会奏效。抠图即便是我们现在的结果中,分割也不是完美的。头发、衣服、树枝和其他物体都不可能被完美地分割,甚至是因为实况中也没有包含这些细节的标注。对这些片段的分割任务被称作抠图,这又是一个新的挑战。这里是一个今年年初在 NVIDIA 的会议上发表的最先进的抠图技术的例子(https://news./ai-software-automatically-removes-the-background-from-images/)。抠图实例——输入也包含 trimap 抠图任务和其余图像相关的任务是不一样的,因为它的输入不仅仅包含图片,还有 trimap——也就是图像边缘的轮廓,这使得这个任务成为了一个「半监督」问题。我们用抠图做了一小部分实验,使用我们的分割作为 trimap,然而并没有得到显著的结果。另一个问题就是缺少一个用于训练的合适的数据库。总结正如刚开始的时候说到的一样,我们的目标是开发一个有意义的深度学习产品。正如你在 Alon 的博客(/@burgalon)中看到的一样,部署总是快速且容易的。然而,训练一个模型确实困难,尤其是在进行整夜的训练时,需要仔细地计划、调试和记录结果。做好调研、尝试新事物以及平常的训练和改进之间的平衡也是不容易的。因为我们使用深度学习,所以我们总是觉得最佳的模型或者是最准确的模型离我们很近,并且还觉得谷歌搜索或者论文会指引我们。但是,实际上,我们的实际提升仅仅来自于更多地压榨原始模型。如上所述,我们仍旧觉得可以从原始模型中压榨出更多的提升空间。总结一下,我们在这项工作中做了很多有趣的事情,然而几个月之前这就像是科幻小说一样,我们乐意与大家讨论任何问题,希望在我们的网站上看到大家。
本文仅代表作者观点,不代表百度立场。本文系作者授权百度百家发表,未经许可,不得转载。
分享到微信朋友圈
打开微信,点击 “ 发现 ”
使用 “ 扫一扫 ” 即可将网页分享至朋友圈。
扫一扫在手机阅读、分享本文
百家号作者平台APP
扫码下载安卓客户端
便捷管理文章信息
随时查看文章收益}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信