爱吧机器人网 » 技术 > 神经网络 > 正文

TensorFlow下构建高性能神经网络模型的最佳实践

随着神经网络算法在图像、语音等领域都大幅度超越传统算法,但在应用到实际项目中却面临两个问题:计算量巨大及模型体积过大,不利于移动端和嵌入式的场景;模型内存占用过大,导致功耗和电量消耗过高。因此,如何对神经网络模型进行优化,在尽可能不损失精度的情况下,减小模型的体积,并且计算量也降低,就是我们将深度学习在更广泛的场景下应用时要解决的问题。

加速神经网络模型计算的方向

在移动端或者嵌入式设备上应用深度学习,有两种方式:一是将模型运行在云端服务器上,向服务器发送请求,接收服务器响应;二是在本地运行模型。

一般来说,采用后者的方式,也就是在PC上训练好一个模型,然后将其放在移动端上进行预测。使用本地运行模型原因在于,首先,向服务端请求数据的方式可行性差。移动端的资源(如网络、CPU、内存资源)是很稀缺的。例如,在网络连接不良或者丢失的情况下,向服务端发送连续数据的代价就变得非常高昂。其次,运行在本地的实时性更好。但问题是,一个模型大小动辄几百兆,且不说把它安装到移动端需要多少网络资源,就是每次预测时需要的内存资源也是很多的。

那么,要在性能相对较弱的移动/嵌入式设备(如没有加速器的ARM CPU)上高效运行一个CNN,应该怎么做呢?这就衍生出了很多加速计算的方向,其中重要的两个方向是对内存空间和速度的优化。采用的方式一是精简模型,既可以节省内存空间,也可以加快计算速度;二是加快框架的执行速度,影响框架执行速度主要有两方面的因素,即模型的复杂度和每一步的计算速度。

精简模型主要是使用更低的权重精度,如量化(quantization)或权重剪枝(weight pruning)。剪枝是指剪小权重的连接,把所有权值连接低于一个阈值的连接从网络里移除。

而加速框架的执行速度一般不会影响模型的参数,是试图优化矩阵之间的通用乘法(GEMM)运算,因此会同时影响卷积层(卷积层的计算是先对数据进行im2col运算,再进行GEMM运算)和全连接层。

模型压缩

模型压缩是指在不丢失有用信息的前提下,缩减参数量以减少存储空间,提高其计算和存储效率,或按照一定的算法对数据进行重新组织,减少数据的冗余和存储的空间的一种技术方法。

目前的压缩方法主要有如下4类:

设计浅层网络。通过设计一个更浅的网络结构来实现和复杂模型相当的效果。但是因为浅层网络的表达能力往往很难和深层网络匹敌,因此一般用在解决简单问题上。

压缩训练好的复杂模型。采用的主要方法有参数稀疏化(剪枝)、参数量化表示(量化),从而达到参数量减少、计算量减少、存储减少的目的。这是目前采用的主流方法,也是本文主要讲述的方法。

多值网络。最为典型就是二值网络、XNOR网络。其主要原理就是采用0和1两个值对网络的输入和权重进行编码,原始网络的卷积操作可以被位运算代替。在减少模型大小的同时,极大提升了模型的计算速度。但是由于二值网络会很大程度降低模型的表达能力。因此也在研究n-bit编码方式。

知识蒸馏(Knowledge Distilling)。采用迁移学习,将复杂模型的输出做为soft target来训练一个简单网络。

下面我们来着重介绍目前应用较多的压缩训练好的复杂模型的方法。

剪枝(Prunes the network)

剪枝就是将网络转化为稀疏网络,即大部分权值都为0,只保留一些重要的连接。如图1所示。

剪枝
 

事实上,我们一般是逐层对神经网络进行敏感度分析(sensitive analysis),看哪一部分权重置为0后,对精度的影响较小。然后将权重排序,设置一个置零阈值,将阈值以下的权重置零,保持这些权重不变,继续训练至模型精度恢复;反复进行上述过程,通过增大置零的阈值提高模型中被置零的比例。具体过程如图2所示。

神经网络敏感度分析
 

剪枝的特点:

通用于各种网络结构与各种任务,且实现简单,性能稳定;

稀疏网络具有更低的功耗,在CPU上使用特定工具时具有更快的计算速度;

剪枝后的稀疏矩阵通常采取特殊的存储方式,例如,常用MKL中的CSR格式。

剪枝的结果:

通过在现有的经典神经网络上做实验,发现压缩倍数在9-12倍之间。如图3所示;

压缩的多是全连接层,CNN层参数少,因此能压缩的倍数也较少;

根据经验,压缩到60%以上模型存储大小,模型大小才会下降比较多。

剪枝的结果
 

量化(Quantize the weights)

量化(Quantization)又称定点,用更少的数据位宽进行神经网络存储和计算。它的优势在于节省存储,并进行更快地访存和计算。

量化是一个总括术语,用比32位浮点数更少的空间来存储和运行模型,并且TensorFlow量化的实现屏蔽了存储和运行细节。

神经网络训练时要求速度和准确率,训练通常在GPU上进行,所以使用浮点数影响不大。但是在预测阶段,使用浮点数会影响速度。量化可以在加快速度的同时,保持较高的精度。

量化网络的动机主要有两个。最初的动机是减小模型文件的大小。模型文件往往占据很大的磁盘空间,例如,上一节介绍的网络模型,很多模型都接近200MB,模型中存储的是分布在大量层中的权值。在存储模型的时候用8位整数,模型大小可以缩小为原来32位的25%左右。在加载模型后运算时转换回32位浮点数,这样已有的浮点计算代码无需改动即可正常运行。

量化的另一个动机是降低预测过程需要的计算资源。这在嵌入式和移动端非常有意义,能够更快地运行模型,功耗更低。从体系架构的角度来说,8位的访问次数要比32位多,在读取8位整数时只需要32位浮点数的1/4的内存带宽,例如,在32位内存带宽的情况下,8位整数可以一次访问4个,32位浮点数只能1次访问1个。而且使用SIMD指令,可以在一个时钟周期里实现更多的计算。另一方面,8位对嵌入式设备的利用更充分,因为很多嵌入式芯片都是8位、16位的,如单片机、数字信号处理器(DSP芯片),8位可以充分利用这些。

此外,神经网络对于噪声的健壮性很强,因为量化会带来精度损失(这种损失可以认为是一种噪声),并不会危害到整体结果的准确度。

那能否用低精度格式来直接训练呢?答案是,大多数情况下是不能的。因为在训练时,尽管前向传播能够顺利进行,但往往反向传播中需要计算梯度。例如,梯度是0.2,使用浮点数可以很好地表示,而整数就不能很好地表示,这会导致梯度消失。因此需要使用高于8位的值来计算梯度。因此,正如在本文一开始介绍的那样,在移动端训练模型的思路往往是,在PC上正常训练好浮点数模型,然后直接将模型转换成8位,移动端是使用8位的模型来执行预测的过程。

图4展示了不同精度(FP32、FP16、INT8)表示的数据范围。

不同精度(FP32、FP16、INT8)表示的数据范围
 

量化有2种类型,均为量化和非均匀量化。我们以将32bit浮点表示成3bit定点值为例。如图5,用INT3来近似表示浮点值,取值范围是8种离散取值(-4,-3,…,3)。如果不论权值的疏密,直接对应,我们称之为“均匀量化”;如果权值密的量化后的范围也较密,权值稀疏的量化后的范围也较稀疏,称之为“非均匀量化”。

均匀量化和非均匀量化的对比图
 

TensorFlow下的模型压缩工具

我们以TensorFlow下8位精度的存储和计算来说明。

量化示例

举个将GoogleNet模型转换成8位模型的例子,看看模型的大小减小多少,以及用它预测的结果怎么样。

从官方网站上下载训练好的GoogleNet模型,解压后,放在/tmp目录下,然后执行:

bazel build tensorflow/tools/quantization:quantize_graph

bazel-bin/tensorflow/tools/quantization/quantize_graph

–input=/tmp/classify_image_graph_def.pb

–output_node_names=”softmax” –output=/tmp/quantized_graph.pb

–mode=eightbit

生成量化后的模型quantized_graph.pb大小只有23MB,是原来模型classify_image_graph_ def.pb(91MB)的1/4。它的预测效果怎么样呢?执行:

bazel build tensorflow/examples/label_image:label_image

bazel-bin/tensorflow/examples/label_image/label_image

–image=/tmp/cropped_panda.jpg

–graph=/tmp/quantized_graph.pb

–labels=/tmp/imagenet_synset_to_human_label_map.txt

–input_width=299

–input_height=299

–input_mean=128

–input_std=128

–input_layer=”Mul:0”

–output_layer=”softmax:0”

运行结果如图6所示,可以看出8位模型预测的结果也很好。

生成量化后的模型quantized_graph.pb运行结果
 

量化过程的实现

TensorFlow的量化是通过将预测的操作转换成等价的8位版本的操作来实现。量化操作过程如图7所示。

TensorFlow下模型量化的过程
 

图7中左侧是原始的Relu操作,输入和输出均是浮点数。右侧是量化后的Relu操作,先根据输入的浮点数计算最大值和最小值,然后进入量化(Quantize)操作将输入数据转换成8位。一般来讲,在进入量化的Relu(QuantizedRelu)处理后,为了保证输出层的输入数据的准确性,还需要进行反量化(Dequantize)的操作,将权重再转回32位精度,来保证预测的准确性。也就是整个模型的前向传播采用8位段数运行,在最后一层之前加上一个反量化层,把8位转回32位作为输出层的输入。

实际上,我们会在每个量化操作(如QuantizedMatMul、QuantizedRelu等)的后面执行反量化操作(Dequantize),如图8左侧所示在QuantizedMatMul后执行反量化和量化操作可以相互抵消。因此,在输出层之前做一次反量化操作就可以了。

量化操作和反量化操作相互抵消
 

量化数据的表示

将浮点数转换为8位的表示实际上是一个压缩问题。权重和经过激活函数处理过的上一层的输出(也就是下一层的输入)实际上是分布在一个范围内的值。量化的过程一般是找出最大值和最小值后,将分布在其中的浮点数认为是线性分布,做线性扩展。因此,假设最小值是-10.0f,最大值是30.0f,那量化后的结果如表1所示。

量化数据的表示
 

ResNet50上的模型压缩实验

笔者在ResNet50-v1上,采用官方GitHub上提供的模型作为Baseline,在ImageNet测试集5万张图片上进行测试。结果如图9。

ResNet50网络量化前后的精度对比
 

在均匀量化的过程中,首先是仅仅对权重进行量化,得到精度为72.8%。随后,分别用模型对测试集的10张、1000张图片的范围进行提前计算最值(Max和Min),并进行存储,得到的精度分别为72.9%和73.1%。

从量化前后的可视化模型对比,也可以看成量化对模型做了哪些操作。图10是未经量化的原始模型。

ResNet50原始网络的节点结构
 

图11仅仅对权重进行量化,没有计算输入图片的最值范围的可视化模型。可以看出原本的Conv2D等节点都转换为QuantizedConv2D的对应节点。并且在进行QuantizedConv2D操作后,得到INT32类型的记过,需要对操作的结果转换为8位(ReQuantize操作),而转换的过程需要知道INT32结果的最值范围,因此也加入了ReQuantizationRange节点。

仅量化权重,在 Conv2D节点计算后,需要ReQuantizationRange来得到计算后的范围
 

如果已经预先使用10张或者1000张图片计算了每一个Conv2D等操作之后需要计算的范围,则ReQuantizationRange的计算过程就可以省去,直接从存储的计算好最值文件中读取。如图12所示。

事先计算好1000张图片的范围,可以省去ReQuantizationRange节点
 

其他建议

在性能受限环境下,对开发者还有没有技术和工程实现方面的其他建议呢?

设计小模型

可以将模型大小做为约束,在模型结构设计和选择时便加以考虑。例如,对于全连接,使用 bottleneck是一个有效的手段。

例如,我们使用TensorFlow官方网站提供的预训练好的Inception V3模型在此花卉数据集上进行训练。在项目根目录下执行:

python tensorflow/examples/image_retraining/retrain.py

–bottleneck_dir=/tmp/bottlenecks/

–how_many_training_steps 10

–model_dir=/tmp/inception

–output_graph=/tmp/retrained_graph.pb

–output_labels=/tmp/retrained_labels.txt

–image_dir /tmp/flower_photos

训练完成后,可以在/tmp下看到生成的模型文件retrained_graph.pb(大小为83M)和标签文件retrained_labels.txt。

我们看到,上述命令行中存储和使用了“瓶颈”(bottlenecks)文件。瓶颈是用于描述实际进行分类的最终输出层之前的层(倒数第二层)的非正式术语。倒数第二层已经被训练得很好,因此瓶颈值会是一个有意义且紧凑的图像摘要,并且包含足够的信息使分类器做出选择。因此,在第一次训练的过程中,retrain.py文件的代码会先分析所有的图片,计算每张图片的瓶颈值并存储下来。因为每张图片在训练的过程中会被使用多次,因此在下一次使用的过程中,可以不必重复计算。这里用tulips/9976515506_d496c5e72c.jpg为例,生成的瓶颈文件为tulips/9976515506_d496c5e72c.jpg.txt,内容如图13所示。

bottleneck文件的内容
 

再如,Highway、ResNet、DenseNet这些带有skip connection结构的模型,也可以用来作为设计窄而深网络的参考,从而减少模型整体参数量和计算量。

还如,SqueezeNet网络结构中通过引入1x1的小卷积核、减少feature map数量等方法,最终将模型大小压缩在1M以内,分类精度与AlexNet相当,而模型大小仅是AlexNet的1/50。

模型小型化

一般采用知识蒸馏。在利用深度神经网络解决问题时,人们常常倾向于设计更复杂的网络,来得到更优的性能。蒸馏模型是采用是迁移学习,通过采用预先训练好的复杂模型(Teacher model)的输出作为监督信号去训练另外一个简单的网络,得到的简单的网络称之为Student model。实验表明,蒸馏模型的方法在MNIST及声学建模等任务上都有着很好的表现。

总结

随着深度学习模型在嵌入式端的应用越来越丰富,例如安防、工业物联网、智能机器人等设备,需要解决图像、语音场景下深度学习的加速问题,减小模型大小及计算量,构建高性能神经网络模型。


上一篇:tensorflow 神经网络分类模型构建全过程
下一篇:神经网络是怎样理解图片的?
精选推荐
新型轻便机器人套装重5kg,辅助跑步和步行
新型轻便机器人套装重5kg,辅助跑步和步行

[2019-10-23]  虽然步行对大多数人来说似乎不是负担,但对有些人来说,这项简单的运动往往会让人感到筋疲力尽。比如手术或中风后恢复的患者、帕金森氏症患 ...

基于生物启发的机器人很容易适应丢失附属器官
基于生物启发的机器人很容易适应丢失附属器官

[2017-12-17]  很多机器人被设计应用在危险环境,如灾难现场。在这些地方,他们的运动系统完全有可能被损坏。那这样会吓跑这些机器人吗?也许不是,如果它们像日本的东北和北海道大学创造的......

一个让深度学习惨败的通用人工智能领域——语境处理
一个让深度学习惨败的通用人工智能领域——语境处理

[2019-11-04]  Context是指用来解释一段给定文本或语句的来源框架,我们可以翻译为上下文或语境。维基百科将context定义为:*在符号学、语言学、社会学和 ...

2018年企业数字化转型的五大趋势
2018年企业数字化转型的五大趋势

[2017-12-16]  据2016年哈佛商学院研究表明,选择进行数字化转型的企业在3年内表现出了55%的平均毛利润提升,相比之下其他企业毛利润同期降低了37%。数字化转型企业的领头羊,也曾是收入处于......

南加州大学机器人学家:机器人更适合粗暴的爱
南加州大学机器人学家:机器人更适合粗暴的爱

[2019-11-07]  图片来自JOHN MADERE GETTY IMAGES打是疼骂是爱,当人类粗暴的将物体从机器人手中敲掉,看似残忍,实际上却能帮助机器人找到最好的握持物 ...

MIT用深度学习处理3D点云数据 应用于无人汽车等领域
MIT用深度学习处理3D点云数据 应用于无人汽车等领域

[2019-10-23]  如果你见过自动驾驶汽车,也许会对车顶上那个一直在旋转的圆柱体感到好奇。这是一个雷达传感器,无人驾驶汽车依靠它在现实世界中进行导航。 ...

这些人型机器人是如此真实,你的肉眼几乎无法区分
这些人型机器人是如此真实,你的肉眼几乎无法区分

[2017-09-03]   我们生活在一个区分现实与幻想变得越来越困难的世界。由于机器人技术的进步,创造人工的人类正在逐渐接近完美的最终目标。我们现在看到的机器人不再只是一块发光二极管,......

谷歌《Nature》发论文称实现量子霸权 18亿倍速碾压世界最强超算
谷歌《Nature》发论文称实现量子霸权 18亿倍速碾压世界最强超算

[2019-10-23]  谷歌坚称自己已经取得了量子霸权——这标志着计算研究领域的一个重要里程碑。谷歌首次发布声明是在今年9月,虽然遭到竞争对手的质疑,但就 ...

本周栏目热点

神经网络:人工智能以及我们的未来

[2016-11-20]   作者:James Crowder翻译:王益军审校:心原文链接:techcrunch把自己想象成在一辆未来的自动驾驶汽车的乘客。这辆汽车与你以一种 ...

[2016-11-20]   include "stdio h" include "stdlib h" include "time h" include "math h" *********************************************i ...

OpenAI开辟全新AI音乐领域,发布Jukebox神经网络生产歌曲

[2020-05-19]  日前,外媒报道,人工智能(AI)技术生成的音乐会给人们带来非常奇妙体验。其中有两大原因,第一,这是一个非常吸引人的全新领域;第二,这 ...

50行代码玩转生成对抗网络GAN模型!(附源码)

[2018-07-30]  本文为大家介绍了生成对抗网络(Generate Adversarial Network,GAN),以最直白的语言来讲解它,最后实现一个简单的 GAN 程序来帮助大家加深理解。...

深度神经网络揭示了大脑喜欢看什么

[2019-11-06]  爱吧机器人网编者按:近日,《自然-神经科学》发表了一篇论文,研究人员创建了一种深度人工神经网络,能够准确预测生物大脑对视觉刺激所产 ...