TalkingData来源赵磊编译Bharath Raj原文作者

如何在边缘设备上适配大型神经网络?

本文由机器之心经授权转载自TalkingData(ID:Talkingdata),未经授权禁止二次转载。

原文作者:Bharath Raj,译者:TalkingData 赵磊,原文地址:http://t.cn/Rkofy1e。

对于任何想要创建可扩展服务的人来说,部署有内存限制的深度学习算法都是一种挑战。从长远来看,相比昂贵的云服务,在边缘设备上离线部署模型更为便宜,而且还有其他好处。唯一的缺点是它们缺乏内存和计算能力。

本文探索了一些可以用来在内存受限的设备中适配神经网络的技术。因为“训练”和“推理”阶段用到了不同的技术,所以将把它们分开来讨论。

训练

某些应用程序需要在线学习。也就是说,模型要根据反馈或额外的数据进行改进。在边缘设备部署这样的应用程序会给您的模型带来一个切实的资源约束。这里有4种方法可以减少此类模型的内存消耗。

  • 梯度检查点

TensorFlow 这样的框架需要消耗大量的内存用于训练。在前向传播过程中,计算图中的每个节点的值都会被计算并保存在内存中,因为在反向传播时计算梯度时需要用到。

每个节点的值在前向传播后保存,以便在反向传播中计算梯度。源码:
https://github.com/openai/gradient-checkpointing

通常情况下,这是可以做到的,但当模型变得越来越复杂时,内存消耗会急剧增加。一个巧妙的回避解决方案是在需要时重新计算节点的值,而不是将它们保存到内存中。

重新计算节点值用以计算梯度。注意,我们需要分别做若干次前向传播来完成一个反向传播。源码:
https://github.com/openai/gradient-checkpointing

然而,如上所示,计算成本将显著增加。解决办法是在内存中只保存一些节点,而在需要时重新计算其他节点。这些保存的节点称为“检查点”。这极大地减少了因深层神经网络而积累的内存消耗。如图所示:

左边的第二个节点是检查点节点。它在减少了内存消耗的同时提供了合理的时间成本。源码:
https://github.com/openai/gradient-checkpointing

  • 以速度换内存(重计算)

根据上面的想法,可以重新计算某些操作用以节省时间。Memory Efficient DenseNet 实现就是一个很好的例子。

DenseNet 的一个 dense 块

原文:https://arxiv.org/abs/1608.06993


DenseNets 具有很高的参数效率,但内存效率也很低。之所以出现这种矛盾,是因为拼接和批标准化操作造成的。

为了使卷积在 GPU 上更高效,必须连续地设置这些值。因此,在连接之后,cudNN 在 GPU 上连续地排列这些值。这涉及到大量的冗余内存分配。类似地,正如本文所解释的那样,批标准化涉及到过多的内存分配。这两种操作都会造成内存以二次增长。DenseNets 有大量的拼接和批标准化,因此它们的内存效率很低。

将原始的拼接和批标准化操作
与它们的高效内存实现相比较原文:
https://arxiv.org/pdf/1707.06990.pdf

上述问题的一个简洁的解决方案涉及两个关键的观察。

首先,拼接和批标准化操作不是时间密集型的。因此,我们可以在需要的时候重新计算这些值,而不是保存所有冗余内存。其次,我们可以使用“共享内存空间”来转储输出,而不是为输出分配“新”内存空间。

我们可以重写这个共享空间来存储其他拼接操作的输出。也可以在需要的时候重新计算拼接操作来进行梯度计算。同理还可以将它扩展到批标准化操作。这个简单的技巧节省了大量的 GPU 内存,通过增加少量的计算时间来换取。

  • 减少精度

在一篇优秀的博客中,Pete Warden 解释了如何用8位浮点值训练神经网络。由于精度的降低,出现了一些问题,其中一部分如下:

  • 如本文所述,“激活值、梯度和参数”有非常不同的范围。一个定点表征并不理想。这篇论文声称,一个“动态的固定点”表征将非常适合于低精度的神经网络

  • 正如 Pete Warden 的另一篇博客所述,较低的精度意味着更大的偏差。通常,如果错误是完全随机的,那么它们很有可能相互抵消。然而,0被广泛用于 padding、dropout 和ReLU,在低精度浮点格式中,0的精确表示也许是不可能的,因此可能会在性能中引入总体偏差。

  • 神经网络的架构工程

架构工程涉及到设计准确率、内存和速度最优的神经网络结构。有几种方法可以在空间和时间上优化卷积。

  • 将 NxN 的卷积分解成 Nx1 和 1 xN 卷积的组合。这可以节省大量的空间,同时也提高了计算速度。在 Inception 网络的更新版本中使用了这种方案以及其他一些优化技巧。

    更详细的讨论,请查看这篇博客:
    https://towardsdatascience.com/a-simple-guide-to-the-versions-of-the-inception-network-7fc52b863202

  • 在 MobileNet 和 Xception Net 中使用深度可分离的卷积。

    关于卷积的类型的详细讨论,请查看这篇博客:
    https://towardsdatascience.com/types-of-convolutions-in-deep-learning-717013397f4d

  • 使用1x1卷积作为一个瓶颈来减少传入通道的数量。这种技术已经在几种流行的神经网络中使用了。

谷歌的 AutoML 的描述,视频:
https://www.youtube.com/watch?reload=9&v=Y2VF8tmLFHw

一个有趣的解决方案是让机器为特定的问题确定最佳的架构。神经架构搜索使用 ML 来为给定的分类问题找到最好的神经网络体系结构。当在 ImageNet 上使用时,它生成的网络(NASNet)是迄今为止创建的最佳性能模型之一。谷歌的 AutoML 也遵循同样的原则。

推理

为边缘设备推理拟合模型相对比较容易。本节将介绍可用于优化边缘设备神经网络的技术。 

  • 去除臃肿

TensorFlow 这样的机器学习框架,消耗了大量的内存空间来创建计算图。这个额外的空间对于加速训练过程是很有用的,但是它不用于推理。因此,专门用于训练的计算图部分可以被删除,我们把这部分称为计算图的“臃肿”。

建议将模型检查点转换为冻结的推理图。这个过程会自动删除消耗内存的“臃肿”部分。当转换为一个冻结的推理图时,从模型检查点抛出“资源耗尽的错误”的计算图有时可以被适配进内存中。

  • 修剪特征

在 Scikit-Learn 上的一些机器学习模型(如随机森林XGBoost)会输出一个名为特征重要度(feature_importance)的属性。这个属性代表了分类或回归任务的每个特性的重要性。我们可以简单地删除那些最不重要的特征。如果您的模型有大量的特征,而且不能通过任何其他方法来减少,这将非常有用。

一个特征重要度可视图的例子:

https://machinelearningmastery.com/feature-importance-and-feature-selection-with-xgboost-in-python/

类似地,在神经网络中,许多权重值接近于零。我们可以简单地删除这些连接。然而,删除层间的单个连接会形成稀疏的矩阵。创建高效推理引擎(硬件)方面的工作正在进行,它可以无缝地处理稀疏操作。然而,大多数 ML 框架都是将稀疏矩阵转换成密集的形式,然后再将它们发送到 GPU 上。

去掉一个无关紧要的过滤器,原文:
http://machinethink.net/blog/compressing-deep-neural-nets/

相反,可以移除无关紧要的神经元,并稍微对模型进行重新训练。对于 CNNs,也可以删除整个过滤器。研究和实验表明,通过使用这种方法,可以保留大部分的精确度,同时获得大规模的缩小。

  • 权重共享

为了更好地说明权重的共享,参考一下这篇深度压缩论文:https://arxiv.org/pdf/1510.00149.pdf中给出的例子。一个4x4的权重矩阵。它有16个32位浮点值。我们需要512位(16*32)来表示这个矩阵。

我们将权重值量化到4个级别,但是保留它们的32位性质。现在,4x4的权重矩阵只有4个唯一的值。4个唯一的值存储在一个单独的(共享)内存空间中。我们可以分别给这4个唯一值一个2位地址(可能的地址值为0、1、2和3)。

可以通过使用2位地址来引用权重。因此,这里获得了一个新的4x4矩阵,其中包含2位地址,矩阵中的每个位置都指向共享内存空间中的一个位置。这个方法需要160位(162+432)来表示整个矩阵,得到了3.2的大小减少因子。

不用说,这种规模的缩小伴随着时间复杂度的增加。但是,访问共享内存并不会消耗太多的时间。

  • 量子化和更低的精度(推理)

回想一下,在本篇文章的“训练”部分中提到了精度的降低。对于推理来说,精确度的降低并不像训练过程那么麻烦。权重可以被转换成更低的精度格式,并发送到推理过程中。但是,可能需要轻微的权重调整来防止精确度的急剧下降。

  • 编码

修剪和量子化的权重可以通过编码进一步优化。Huffman 编码可以用更少的位表示最频繁的权重值。因此,在比特级别上,一个 Huffman 编码的字符串比普通字符串占用更小的空间。

深度压缩探讨了使用无损压缩技术的编码,如 Huffman 。然而,研究也探讨了有损压缩技术的使用。这两种方法的缺点是翻译的开销。

  • 推理优化器

到目前为止,我们已经讨论了一些很有建设性的想法,但是若从头开始实现它们需要相当长的时间。这就是推理优化器发挥作用的地方。例如,Nvidia 的 TensorRT 包含了所有以上这些想法。并提供了一个经过训练的神经网络的“优化推理引擎”。

TensorRT:
https://developer.nvidia.com/tensorrt

此外,TensorRT 可以优化模型,使其能够更好地利用 Nvidia 的硬件。下面是一个使用 TensorRT 优化的模型更有效地利用了 Nvidia 的 V100 的例子。

在 Nvidia 的 V100 上使用 TensorRT 优化的模型:

https://devblogs.nvidia.com/tensorrt-3-faster-tensorflow-inference/

  • 知识蒸馏

我们可以“教”较小的模型来模拟更健壮、更大的模型,而无需花哨的优化技术。这项技术被称为“知识蒸馏”,它是谷歌“ Learn2Compress ”的重要组成部分。

Teacher-Student 模型:

https://ai.googleblog.com/2018/05/custom-on-device-ml-models.html

通过使用这种方法,我们可以强制使用更小的模型,这些模型可以适配在边缘设备上,以达到大型模型的性能水平。据统计,精确度的下降是最小的。

更多信息可以参考Hinton的论文:

https://arxiv.org/pdf/1503.02531.pdf

本文由机器之心经授权转载自TalkingData(ID:Talkingdata),未经授权禁止二次转载。

原文链接:https://mp.weixin.qq.com/s/p7DR11sZr7aO473Nt4gQfg

工程云服务神经网络TensorFlow
4
相关数据
深度学习技术

深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。 深度学习是机器学习中一种基于对数据进行表征学习的算法,至今已有数种深度学习框架,如卷积神经网络和深度置信网络和递归神经网络等已被应用在计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域并获取了极好的效果。

权重技术

线性模型中特征的系数,或深度网络中的边。训练线性模型的目标是确定每个特征的理想权重。如果权重为 0,则相应的特征对模型来说没有任何贡献。

机器学习技术

机器学习是人工智能的一个分支,是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、计算复杂性理论等多门学科。机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。因为学习算法中涉及了大量的统计学理论,机器学习与推断统计学联系尤为密切,也被称为统计学习理论。算法设计方面,机器学习理论关注可以实现的,行之有效的学习算法。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

时间复杂度技术

在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。例如,如果一个算法对于任何大小为 n (必须比 n0 大)的输入,它至多需要 5n3 + 3n 的时间运行完毕,那么它的渐近时间复杂度是 O(n3)。

TensorFlow技术

TensorFlow是一个开源软件库,用于各种感知和语言理解任务的机器学习。目前被50个团队用于研究和生产许多Google商业产品,如语音识别、Gmail、Google 相册和搜索,其中许多产品曾使用过其前任软件DistBelief。

张量技术

张量是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数,这些线性关系的基本例子有内积、外积、线性映射以及笛卡儿积。其坐标在 维空间内,有 个分量的一种量,其中每个分量都是坐标的函数,而在坐标变换时,这些分量也依照某些规则作线性变换。称为该张量的秩或阶(与矩阵的秩和阶均无关系)。 在数学里,张量是一种几何实体,或者说广义上的“数量”。张量概念包括标量、矢量和线性算子。张量可以用坐标系统来表达,记作标量的数组,但它是定义为“不依赖于参照系的选择的”。张量在物理和工程学中很重要。例如在扩散张量成像中,表达器官对于水的在各个方向的微分透性的张量可以用来产生大脑的扫描图。工程上最重要的例子可能就是应力张量和应变张量了,它们都是二阶张量,对于一般线性材料他们之间的关系由一个四阶弹性张量来决定。

神经网络技术

(人工)神经网络是一种起源于 20 世纪 50 年代的监督式机器学习模型,那时候研究者构想了「感知器(perceptron)」的想法。这一领域的研究者通常被称为「联结主义者(Connectionist)」,因为这种模型模拟了人脑的功能。神经网络模型通常是通过反向传播算法应用梯度下降训练的。目前神经网络有两大主要类型,它们都是前馈神经网络:卷积神经网络(CNN)和循环神经网络(RNN),其中 RNN 又包含长短期记忆(LSTM)、门控循环单元(GRU)等等。深度学习是一种主要应用于神经网络帮助其取得更好结果的技术。尽管神经网络主要用于监督学习,但也有一些为无监督学习设计的变体,比如自动编码器和生成对抗网络(GAN)。

随机森林技术

在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。 Leo Breiman和Adele Cutler发展出推论出随机森林的算法。而"Random Forests"是他们的商标。这个术语是1995年由贝尔实验室的Tin Kam Ho所提出的随机决策森林(random decision forests)而来的。这个方法则是结合Breimans的"Bootstrap aggregating"想法和Ho的"random subspace method" 以建造决策树的集合。

准确率技术

分类模型的正确预测所占的比例。在多类别分类中,准确率的定义为:正确的预测数/样本总数。 在二元分类中,准确率的定义为:(真正例数+真负例数)/样本总数

分类问题技术

分类问题是数据挖掘处理的一个重要组成部分,在机器学习领域,分类问题通常被认为属于监督式学习(supervised learning),也就是说,分类问题的目标是根据已知样本的某些特征,判断一个新的样本属于哪种已知的样本类。根据类别的数量还可以进一步将分类问题划分为二元分类(binary classification)和多元分类(multiclass classification)。

神经元技术

(人工)神经元是一个类比于生物神经元的数学计算模型,是神经网络的基本组成单元。 对于生物神经网络,每个神经元与其他神经元相连,当它“兴奋”时会向相连的神经元发送化学物质,从而改变这些神经元的电位;神经元的“兴奋”由其电位决定,当它的电位超过一个“阈值”(threshold)便会被激活,亦即“兴奋”。 目前最常见的神经元模型是基于1943年 Warren McCulloch 和 Walter Pitts提出的“M-P 神经元模型”。 在这个模型中,神经元通过带权重的连接接处理来自n个其他神经元的输入信号,其总输入值将与神经元的阈值进行比较,最后通过“激活函数”(activation function)产生神经元的输出。

深度压缩技术

韩松等人提出的深度压缩(Deep Compression)由剪枝、量化训练和可变长度编码(variable-length coding)组成,它可以压缩深度神经网络数个量级而没有什么预测准确度损失。「深度压缩」是一种三阶段流程,它可以在保留原始准确度的情况下减小深度神经网络的模型大小。

密集型连接网络技术

Gao Huang等研究者提出了DenseNet,该论文获得了CVPR 2017的最佳论文。DenseNet的目标是提升网络层级间信息流与梯度流的效率,并提高参数效率。它也如同ResNet那样连接前层特征图与后层特征图,但DenseNet并不会像ResNet那样对两个特征图求和,而是直接将特征图按深度相互拼接在一起。DenseNet最大的特点即每一层的输出都会作为后面所有层的输入,这样最后一层将拼接前面所有层级的输出特征图。这种结构确保了每一层能从损失函数直接访问到梯度,因此可以训练非常深的网络。

推理引擎技术

推理机是实施问题求解的核心执行机构,常见于专家系统。它是对知识进行解释的程序,根据知识的语义,对按一定策略找到的知识进行解释执行,并把结果记录到动态库的适当空间中去。

知识蒸馏技术

Hinton 的工作引入了知识蒸馏压缩框架,即通过遵循“学生-教师”的范式减少深度网络的训练量,这种“学生-教师”的范式,即通过软化“教师”的输出而惩罚“学生”。为了完成这一点,学生学要训练以预测教师的输出,即真实的分类标签。这种方法十分简单,但它同样在各种图像分类任务中表现出较好的结果。

XGBoost技术

XGBoost是一个开源软件库,为C ++,Java,Python,R,和Julia提供了渐变增强框架。 它适用于Linux,Windows,MacOS。从项目描述来看,它旨在提供一个“可扩展,便携式和分布式的梯度提升(GBM,GBRT,GBDT)库”。 除了在一台机器上运行,它还支持分布式处理框架Apache Hadoop,Apache Spark和Apache Flink。 由于它是许多机器学习大赛中获胜团队的首选算法,因此它已经赢得了很多人的关注。

图网技术

ImageNet 是一个计算机视觉系统识别项目, 是目前世界上图像识别最大的数据库。

优化器技术

优化器基类提供了计算梯度loss的方法,并可以将梯度应用于变量。优化器里包含了实现了经典的优化算法,如梯度下降和Adagrad。 优化器是提供了一个可以使用各种优化算法的接口,可以让用户直接调用一些经典的优化算法,如梯度下降法等等。优化器(optimizers)类的基类。这个类定义了在训练模型的时候添加一个操作的API。用户基本上不会直接使用这个类,但是你会用到他的子类比如GradientDescentOptimizer, AdagradOptimizer, MomentumOptimizer(tensorflow下的优化器包)等等这些算法。

推荐文章
暂无评论
暂无评论~