1。深度学习模型为什么要减肥随着深度学习的发展,神经网络模型越来越复杂。计算量可达30-40GOP(1GOP=109次运算)。这些神经网络通常运行在GPU上,但是如果我们要在移动端/嵌入式端实现深度学习,那么这么庞大的模型是绝对不可能跑起来的。移动/嵌入式端的计算能力往往只有桌面GPU的1/100到1/1000。也就是说,在GPU上每秒40帧的深度学习CV算法,在移动端/嵌入式端只有每秒0.04-0.4帧。这样的性能会极大地影响用户体验。常用的深度学习网络计算在移动/嵌入式终端上运行深度学习模型。除了运行速度,能效也是一个关键指标。能效比是指一次操作所消耗的能量,决定了移动/嵌入式终端运行深度学习算法时电池可以使用多长时间。能效比与深度学习模型密切相关。下面我们会看到,深度学习模型的大小将决定算法运行时的片外内存访问频率,从而决定能效比。2.什么样的模特才算“苗条”?就像我们减肥不仅要看体重还要看体脂率一样,我们在为一个深度学习模型“减肥”的时候,不仅要看模型的计算量,还要看模型的大小。模型计算量是衡量深度学习是否适合移动或嵌入式计算的最重要指标,通常以GOP为单位表示。例如,流行的ResNet-18的计算量约为4GOP,而VGG-16约为31GOP。移动和嵌入式硬件的计算能力是有限的,因此模型需要的计算量越大,模型在移动端运行的时间就越长。为了让使用深度学习的应用能够顺利运行,模型的计算量应该尽可能的小。此外,深度学习的每一次操作都需要能量。模型计算量越大,完成推理所需的能量就越大。换句话说,消耗的电越多。在电池容量有限的移动端和嵌入式端,需要仔细计算模型一次推理所消耗的能量,因此深度学习模型的计算量不宜过大。如果说计算量是模特最简单、最直接的“体重”,那么模特尺寸就是稍微复杂、微妙的“体脂率”。深度学习模型的大小主要决定了模型进行推理所需的能量。那么模型的大小和推理消耗的能量有什么关系呢?首先,我们知道深度学习模型必须存储在内存中,而内存其实分为片内内存和片外内存。片上存储器是SRAM缓存,是处理器集成在芯片上的内存模块,用于快速访问重要数据。片上存储器占用宝贵的芯片空间,因此集成在处理器中的片上存储器的大小通常在1-10MB的量级。片外存储器是主板上的DDR存储器。这种内存可以有很大的容量(>1GB),但存取速度相对较慢。片上存储器非常接近处理器的核心电路,因此访问消耗的能量非常少。片外存储器远离处理器。一次访问消耗大量能量。更重要的是,访问片外存储器所需的能量是巨大的。.根据SongHan的论文估算,一次片外内存访问消耗的能量是乘加运算的200倍,是访问片上内存的128倍。换句话说,一次片外内存访问相当于做200次乘法运算!当然,具体程序中操作和内存访问所消耗的能量取决于有多少操作需要一次内存访问。严格的分析方法是屋顶线模型,但我们也可以从谷歌公布的数据中估计深度学习模型中操作次数与内存访问次数的比率。Google在TPU论文中公布了这个数据,从中可以看出LSTM模型的内存访问频率是最高的。平均64或96次计算需要访问内存一次才能得到重量数据;而CNN模型的内存访问频率相对较高。**,平均2888或1750次操作访问一次内存访问权重。这也很好理解,因为CNN充分利用了局部特征(localfeatures),它的权重数据有很多复用。根据前面的计算和内存访问能量数据,如果所有的权重数据都存储在片外内存中,那么两个CNN模型的计算和内存访问消耗的能量比为2:1和2.5:1,而在LSTM0和LSTM1模型中,运算和内存访问消耗的能量比分别是1:10和1:7!也就是说,当使用LSTM模型进行推理时,内存访问所消耗的能量占了绝大多数!因此,为了降低能耗必须减少片外内存访问,或者我们需要将模型的权重数据和每一层的中间计算结果尽可能的存储在片内内存中而不是片外记忆。这就是谷歌TPU使用高达28MB片上内存的原因。然而,用于移动和嵌入式系统的芯片成本不高,因此片上内存容量有限。这种情况下,我们就必须从深度学习模型的大小上想办法,尽量减小模型的大小,让模型尽可能多的存储在片上内存中,或者至少是权重一层网络的数据可以存储在片上存储器中。3、模型减肥的几种方法2016年可谓深度学习模型减肥元年。那一年,大家对深度学习的潜力印象深刻,同时开始认真考虑如何在移动硬件上运行深度学习,于是麻省理工学院的VivieneSze发表了第一款深度学习加速芯片Eyeriss,Bengio发表了BinarizedNetwork,Rastegari提出了XOR-Net,宋涵也发表了DeepCompression,可谓是百花齐放。给模型减重的方法可以分为两类:第一类是大幅度调整模型结构(包括网络拓扑连接、计算等),直接训练一个结构比较细长的模型;第二类是在已有模型的基础上进行小的修改,通常不涉及再训练(模型压缩)。Bengio的BinarizedNeuralNetwork可谓是一流模型的先驱,它将神经元的激活限制在-1或1,从而大大减少了计算量。谷歌一个多月前也发布了MobileNet,它使用深度卷积来减少计算量和模型尺寸。Depthwiseconvolution可以大大减少计算量,但同时不同特征之间的权值参数变成线性相关。理论上自由度降低了,但是由于深度学习网络本身的冗余,在实际测试中性能并没有下降多少。MobileNet的计算量只有1GOP左右,模型大小也只有4MB多一点,但是在ImageNet上却可以达到90%左右的top-5准确率。这条路上也有很多人在努力。前不久,Face++也发布了ShuffleNet,作为MobileNet的进一步演进,也实现了更小尺寸的模型。我们预计未来会出现更多这样的网络。对于GoogleMobileNet的几个模型,模型计算量大大降低,而top-5准确率并没有降低多少。图中1MAC=2OP的第二种方法,就是保持原来模型的大体结构,但是在不重新训练的情况下,通过各种方法进行压缩,即模型压缩。一种思路是在数据编码中找到一种方法。我们都知道,数据在计算机系统中是以二进制形式表示的。传统的全精度32位浮点数可以覆盖非常大的数字范围,但也占用大量内存,同时运算时硬件资源开销也很大。其实这么高的精度在深度学习运算中可能用不到,所以最简单直接的方法就是降低精度,用16位甚至8位的浮点数代替原来的32位浮点数计算固定点。一方面,减少数据的位长可以大大减少模型所需的存储空间(1KB可以存储256个32位浮点数,但可以存储1024个8位定点数),在另一方面,低精度运算单元的硬件实现更简单,运行速度更快。当然,随着数据精度的下降,模型的精度也会下降,所以也出现了很多优化策略,比如优化编码(将原来的不动点数线性编码,等间距编码,但非-线性编码在数字集中的地方使数字之间的距离变小以提高精度,在数字稀疏的地方使数字之间的距离变大。非线性编码方法已经在数字通信中使用了几十年。8位非-linear线性编码在合适的场合可以达到接近16位线性编码的精度)等。业界大部分已经开始使用降低精度的解决方案,Nvidia率先推动了16位浮点和8位定点计算,还推出了TensorRT帮助优化精度。除了编码优化,另一种方法是网络修剪。我们都知道深度学习网络中的神经元往往是冗余的,即使去掉很多神经元也不会对准确率造成太大影响。网络建设就是这样一种技术。在原有模型的基础上,通过观察神经元的活跃度,删除不活跃的神经元,从而达到缩小模型规模,减少计算量的效果。当然,网络剪枝和编码优化可以结合起来。宋寒2016年发表在ICLR上的DeepCompression,采用剪枝和编码优化两种方式,实现了35倍的模型尺寸压缩。DeepCompression使用的模型压缩同时使用了网络剪枝和编码优化。另外,训练新模型和模型压缩并不矛盾。可以做一个压缩版的MobileNet,从而进一步提高MobileNet在移动端运行的速度和能效。总结运行在移动端/嵌入式端的深度学习网络模型必须考虑运行速度和能效比,因此模型的计算量和模型尺寸要尽可能小。我们可以训练新的网络拓扑来减少计算,使用网络压缩来提高性能,或者两者兼而有之。面向移动/嵌入式终端的深度学习网络是当前的热门话题。随着边缘计算的逐渐兴起,预计会有更多精彩的研究出现,让我们拭目以待。【本文为栏目组织《机器之心》原创文章,微信公众号《机器之心(id:almosthuman2014)》】点此查看作者更多好文
