original="https://static.leiphone.com/uploads/new/article/740_740/201711/5a12e07bd1b2f.jpg?imageMogr2/format/jpg/quality/90" data-image-enhancer="larger than 645" />
雷锋网 AI 科技评论按:苹果从 iOS11 开始正式在系统中带有机器学习 API,同步提供了许多基于机器学习/深度学习的手机功能。其实这之前苹果就已经做了很多研究和开发,但当他们决定在手机上运行深度神经网络、提供好用的功能同时还不要干扰正常的用户体验的时候,重大的挑战同样也等待苹果解决。
近日苹果机器学习博客的一篇新文章就介绍了苹果是如何设计、实现在 iPhone 上运行的人脸检测系统的,不仅模型设计花了功夫,运行环境的优化也用了多种技巧。结合苹果机器学习博客往期的几篇文章,我们也继续感受到许多企业、许多创业者所说过的,有创新只是第一步,把创新变成实实在在的产品还有很长的路要走、还有很多的困难要克服。
雷锋网 AI 科技评论把这篇文章全文翻译如下:
自 iOS10 以来,苹果开始把基于深度学习的人脸检测方法融入系统中。随着苹果的 Vision 框架的发布,开发者们可以在自己的 app 中运用这项技术以及许多其它的计算机视觉算法。为了能够保护用户隐私以及高效地在本地设备上运行,苹果在开发过程中也遇到了不小的困难。这篇文章中就讨论了这些困难,并且介绍了苹果的人脸检测算法是如何解决这些困难的。
简介
苹果最初是通过 CIDdetector 类中 Core Image 框架的一个公有 API 提供人脸检测功能的。苹果自己编写的应用(比如照片)内部也在使用这个 API。最早版本的 CIDdetector 基于 Viola-Jones 检测算法(雷锋网 AI 科技评论注:Viola Jones Face Detector 是 Paul viola 和 Michael J Jones 在 CVPR2001 论文中共同提出的一种人脸检测框架。它极大地提高了人脸检测的速度和准确率,是第一个实时的人脸检测算法,即便到现在也还有巨大影响力),然后苹果又在 CIDdetector 中加入了一些基于传统计算机视觉方法的优化。
随着深度学习逐步发展,以及深度学习在计算机视觉中的应用越来越多,顶级的人脸检测算法准确率也有了大踏步的提升。苹果的开发人员们意识到自己需要重新思考面部识别的做法,以便跟上这种新的范式。与传统计算机视觉方法相比,深度学习学到的模型消耗的内存要多几个数量级,更不用提需要更多的磁盘空间以及对计算资源的渴求。
即便今天的智能手机已经有了长足的性能增长和丰富的功能支持,典型的高端手机仍然不足以让基于深度学习的计算机视觉模型运行起来。业界内比较普遍的做法是绕过这个困难,通过云计算 API 提供深度学习功能。在基于云计算的方案中,移动设备需要把图像发送到服务器,在服务器上运行深度学习推理,分析、检测其中的人脸。云计算服务通常要使用性能强劲的、带有大量可用显存的桌面级 GPU。大规模的深度神经网络模型,甚至多个大规模网络的融合模型就可以在服务器端运行,让客户端(比如智能手机)享受到深度学习带来的种种好处,而且无需在本地运行(实际上也无法在本地运行)。
苹果的 iClould Photo Library 就是一个视频和图像的云存储解决方案,按理说可以方便地用服务器识别用户已经上传的内容。然而,由于苹果对用户隐私做出了很高的承诺、以高标准处理用户信息,他们就无法在 iCloud 服务器上做计算机视觉的相关计算。每张上传到 iClould Photo Library 的照片、每段上传的视频都是首先在设备上加密之后才上传服务器的,要解密也只有这个 iCloud 账户下注册的设备才可以解密。所以,如果要给客户们带来基于深度学习的计算机视觉解决方案的话,苹果只能直接面对、尝试解决这个困难:让深度学习算法在 iPhone 本地运行。
苹果的开发人员们面对的困难有好几个。
首先,深度学习模型要作为操作系统的一部分,随着手机一起来到用户手中,这会占据珍贵的设备中的 NAND 闪存存储空间;其次,模型需要加载到 RAM 中,并且需要消耗可观的 GPU 和/或 CPU 计算时间;基于云的服务往往是专用服务器,其上的所有资源都可以集中提供给一个视觉问题使用,而在设备上本地进行的计算就需要和其它正在运行的应用一起共享系统资源;最后,计算过程必须足够高效,在合理的短时间内就能处理完一个很大的照片库,同时还不能有大幅度的功耗增加、不能有明显的发热。
这篇文章余下的篇幅就介绍了苹果是如何设计深度学习人脸检测算法、如何克服困难达到顶级的准确率的。主要讨论的内容有:
如何全面利用 GPU 和 CPU(使用 BNNS 和 Metal)
优化网络推理、图像加载和缓存时的内存使用
如何在与 iPhone 的其它大量同时运行的功能时间不造成冲突的条件下实现这个网络
从 Viola-Jones 算法到深度学习
当苹果的开发人员们在 2014 年开始研究基于深度学习的图像中的人脸检测方法时,深度卷积网络(deep convolutional networks,DCN)才刚刚开始在物体检测任务中崭露头角。当时最突出的是一个名叫“OverFeat”的方法,它让很多简单的卷积神经网络思想变得流行起来,也表明了深度卷积网络扫描图像寻找物体时的高效性。
OverFeat 在神经网络的全连接层和卷积网络的卷积层之间找到了平衡,它的做法是把相同空间维度的过滤器的有效卷积作为输入。这项研究清楚地表明,一个感受野大小固定(比如 32x32 大小,带有 16 像素的自然步幅)的二分分类网络可以高效地应用于任意大小的图像(比如 320x320 的图像),并且生成合适大小的输出映射(这种情况下大小为 20x20)。OverFeat 这篇论文也提供了巧妙的做法,通过高效地降低网络步幅产生更高密度的输出映射。
苹果的开发人员们根据 OverFeat 论文中学到的新观点构建了最初的模型架构,做出了一个全卷积网络( 图1),它可以执行如下两个功能:
一个预测输入中是否包含人脸的二分类分类器
一个回归函数,预测一组参数,它们形成的边界框能最好地框出输入中的人脸
为了训练这样的网络,苹果的开发人员们做了好几种不同的实验。比如,一种简单的训练方式就是建立一个数据集,其中包含大量固定大小的图像块,这些图像块的大小和模型允许的最小输入大小相同;这样,每个图像块在经过网络之后都只得到一个输出。训练数据集是平衡到理想状态的,也就是说一半的图像块里包含一张脸(正例),另一半图像里不包含人脸(负例)。对于每一个正例,都会同步提供给模型这张脸的真实位置(x,y,w,h)。然后苹果就以前述的两条网络功能为目标,训练优化这个网络。经过训练后,网络就可以预测图像块中是否包含有一张人脸;如果包含有人脸的话,它同时还会输出图像块中人脸的位置坐标和大小。
图 1. 一个用于人脸识别的修改过的深度卷积网络架构
由于网络是全卷积的,它可以高效地处理任意大小的图像,并且产生二维输出映射。映射中的每个点都对应着输入图像中的一个小块,并且包含了网络对图像块中是否包含人脸、输入中的人脸位置和大小的预测结果。
有了这样的网络以后,就可以在它的基础上构建相对标准的图像处理流水线进行人脸检测。这个流水线由一个多尺度的图像金字塔、人脸检测网络和后处理模块组成。这里,为了处理各种不同大小的图像需要一个多尺度的图像金字塔。人脸识别网络在图像金字塔的每一个尺寸下都会执行,每个尺寸都要选出候选的检测结果。接下来后处理模型就会把不同大小的候选检测结果组合起来,生成一个边界框列表,对应着整个网络对图像中人脸预测的最终结果。
图 2. 面部检测工作流程
这种做法开始有点接近能够在设备上运行、而且能详尽地扫描整张图像的深度卷积网络了。不过网络的复杂度和大小仍然是运行时的性能瓶颈。克服这个困难意味着不仅要把网络限制、简化为一个简单的拓扑结构,同时还要限制网络中的层的数量、每个层中通道的数量、以及卷积层的卷积核大小。这种种限制就凸显出了一个严重的问题:产生的预测结果让人觉得可以接受的网络结构必然非常复杂,多数时候要超过 20 层,而且有数个一个网络中嵌套另一个网络的模块。把这样的网络用在前述的图像扫描框架中可以说是完全不可行的了,性能表现和电量消耗都无法接受。实际上,这样规模的网络都没办法加载到移动设备的内存中去。下面苹果的开发人员们就面临了一个巨大的挑战:如何训练一个简单、紧凑的网络,让它能够模仿高度复杂的网络的行为,达到可比拟的准确率,同时还能高效、节省资源地运行。
苹果的开发人员们决定利用一种新的方法,它有个非正式的称呼是“老师-学生”训练(雷锋网 AI 科技评论注: FitNets: Hints for Thin Deep Nets)。这种方法带来了一种新的机制,它可以训练第二个又窄又深的网络(“学生”),过程里要让它的输出和上文描述的大的、复杂的网络(“老师”)高度吻合。学生网络是由简单的多次重复的 3x3 卷积和池化层结构组成的;网络架构经过了高度订制,让它能够最好地利用苹果在 iPhone 中搭载的神经网络推理引擎的计算能力。
这样,苹果终于找到了一个用于人脸识别的深度神经网络算法,而且是可以直接在设备上执行的。苹果的开发人员们进行了数次训练迭代,最终得到了一个具有足够精度的网络模型,可以支持苹果规划的相关应用。虽然这个网络现在已经足够准确、也能够运行了,但是在把它真正部署到上百万用户的设备中去之前,还有许许多多的工作要做。
优化图像处理流水线
在产品设计的抉择中,深度学习相关的实际考量也产生了深深的烙印,因为苹果想要做的是开发者也可以方便使用的软件框架,苹果把它称作 Vision。有一件事很快就变得明显起来,那就是只靠优秀的算法还不足以建立一个优秀的软件框架。苹果还需要建立一个经过高度优化的图像处理流水线。
苹果并不希望让开发者考虑图像缩放、图像转换以及图像来源之类的问题。不管是处理摄像头实时捕捉的视频流、处理视频、还是处理磁盘以及网上的图像,人脸检测都应当达到好的工作效果。它应当在各种图像表示和格式下都能工作。
苹果也很在意电量消耗和内存使用,尤其是在视频流传输和图像捕捉的时候。内存消耗量有可能造成一些问题,比如在拍摄 6400 万的全景照片时就需要消耗很多内存。为了消除这些风险,苹果用了一些技巧,比如区域降采样编码、自动拼贴,以便能够在大图像上执行计算机视觉任务,即便是在非典型的宽高比下。
另一个挑战是颜色空间的匹配。苹果有许多种不同的色彩空间 API,但是他们并不想让开发者们为了色彩空间的事情费脑筋。Vision 框架就会自动处理色彩匹配的问题,这样也就进一步降低了在任何应用中使用计算机视觉算法的门槛。
Vision 框架还通过中间过程的高效处理和复用进行了一些优化。人脸检测、面部关键点检测以及其它一些计算机识别任务都可以在同一张缩放后的中间过程图像上工作。通过算法接口抽象、为待处理的图像或者缓冲找到归属地,Vision 可以创建、缓存中间过程图像,无需开发者做任何操作就可以提高多种计算机视觉任务执行时的性能表现。
反过来说也有很大好处。从中心接口的角度来看,算法开发的方向可以是更高的复用程度或者更多的中间过程共享。Vision 框架承载着几个不同的、独立的计算机视觉算法。为了让不同的算法更好地协同工作,实现算法时设计的分辨率和色彩空间也应当尽可能多地在不同的算法之间共享。
为设备的本地执行做优化
如果面部检测 API 既不能在实时应用中使用、又不能在系统后台进程中工作,那么即便它设计得便于使用,也不会让用户感受到任何乐趣。对用户来说,识别照片库中的人脸应当运行得非常流畅,或者一张照片拍好以后马上就能对它进行分析。但同时他们也不希望电量快速下降,或者让系统的性能表现慢得像龟爬。苹果的移动设备都是同时要执行多个任务的设备,要么在后台执行的计算机视觉功能也就不应当显著影响系统其它功能的执行速度。
苹果的开发人员采取了几个策略来最小化内存消耗和 GPU 使用。为了减小内存消耗,iOS 中通过分析计算图的方法为神经网络的中间层分配地址;这样可以把多个层通过假名指向同一块缓冲区。虽然这个过程是完全确定性的,但这个技巧既对性能没有造成什么影响、也没造成地址的碎片化,就减小了内存消耗。CPU 和 GPU 上也都可以使用这个方法。
在 Vision 框架中,面部检测器下需要运行 5 个网络(如前文图2,每个网络对应一种图像金字塔中的图像尺寸)。这 5 个网络有同样的权重和参数,但是输入的形状、输出以及中间层有所区别。为了进一步减小内存消耗,苹果在这 5 个网络共同形成的计算图上开启了运行时的内存优化算法,也显著减小了内存消耗。另外,多个网络可以复用同一组权重和参数缓冲区,也降低了内存需求。
为了达到更快的运行速度,苹果的开发人员们利用了这个全卷积网络的本质特点:为了匹配输入图像的分辨率,所有的大小都是动态缩放的。相比于把图像规格化到方形网格的像素点中,让网络大小匹配图像的大小则可以大幅度减少总的操作数目,由于操作的拓扑逻辑并不会被尺寸缩放改变,剩余的分配器还有很高的性能,动态尺寸缩放并不会带来内存分配相关的性能开销。
为了保证后台运行深度神经网络的时候用户界面仍有足够的响应性和流畅性,苹果的开发人员把网络中每一层的 GPU 运算任务不断拆分,直到每个子任务消耗的时间都不超过千分之一秒。这样,当用户界面动画这样的高优先级任务出现的时候驱动程序就可以先切换给它们执行,减轻、甚至有时候完全杜绝了帧率下降的问题。
以上的所有方法结合起来就共同保证了用户可以尽情享用本地计算的、低延迟的、隐私保护的深度学习推理功能,同时无需知道他们的手机正在以每秒数百 GFlops 的速度运行着神经网络。
如何使用 Vision 框架
苹果是否真的达到了自己设定的“开发一个高性能、便于使用的面部检测 API”目标呢?开发者可以自己尝试一下 Vision 软件,自己做个判断。以下是入门方法:
观看 WWDC 演讲:Vision 软件框架:构建在 Core ML 之上
阅读开发者文档 Vision 软件框架参考
试一试 Core ML 和 Vision 框架:iOS11 中的机器学习导览
(完)
via Apple Machine Learning Journal