为了提高人脸识别的实时性,我们团队将传统的利用神经网络框架推理升级至统一的TensorRT加速推理。经实验对比,经TensorRTFP16模式推理加速后的人脸识别不仅几乎无损精度,甚至于在部分场景精度有提升,识别速度提升为原来的2.3倍。统一加速推理的人脸识别不仅能为客户提供优质高响应的服务,同时也能提升AI服务器资源利用率,降低服务成本,也有利于各模型推理的整合统一。
一、目的及背景
首先,量化推理的出现为提升人脸识别服务的响应速度,给客户提供更优质的服务体验提供了更多的选择。
其次,由于不同业务需求的神经网络模型可能是在不同的神经网络框架下训练生成的,比如说人脸检测利用的是TensorFlow,人脸识别利用的是MxNet,而肖像生成利用的是PyTorch。如果线上服务都用深度学习框架进行推理,则需要在服务器上部署多种框架,相对于统一的推理引擎,多种框架不利于结构的优化以及数据之间的通信,且会增加升级和维护的成本。
最后,面对日益增长的AI服务需求,为了保证响应的服务质量,企业需要采购更多的服务器资源,特别是GPU服务器。如何提升服务器资源的利用率,降低相应的服务成本也成为迫切的需求。通过模型量化推理减少计算和存储资源的占用,而推理加速也可以减少服务器资源占用。
基于以上背景,我们团队对现有的量化推理和深度学习推理服务进行了调研和实验。
二、相关技术
1、TensorRT
什么是TensorRT?TensorRT是Nvidia开发的用于高性能深度学习推理的SDK。其包括一个高性能的神经网络InferenceOptimizer和一个RuntimeEngine用于生产部署。利用TensorRT,可以优化所有主要深度学习框架中训练的神经网络模型,以高准确性来校准低精度,最终部署到超大规模的数据中心、嵌入式设备或汽车产品平台。如图1所示:
TensorRT通过融合层和优化内核来优化网络,从而提高延迟、吞吐量、功率效率和内存消耗。如果应用程序指定,它还将优化网络以降低运行精度,进一步提高性能并减少内存需求。如图2所示:
TensorRT为深度学习推理应用的生产部署提供INT8和FP16优化,如视频流、语音识别、推荐和自然语言处理。减少精度推理可以显著降低应用程序延迟,降低延迟是许多实时服务、自动驾驶和嵌入式应用程序的需求。
①LowPrecisionInference
MxNet、TensorFlow、PyTorch等现有的深度学习框架,在训练模型的时候,一般都会使用Float32(简称FP32)的精度来表示权值、偏置、激活值等.而当网络的层数逐渐加深,其参数的计算量是极其多的,比如像ResNet、VGG这种网络。如此大的计算量,如果在推理过程中都用FP32的精度来计算,会比较耗费时间和资源。如果是在对计算资源有限制的移动设备或者是嵌入式设备,如此大的计算量简直无法想法,甚至于根本运行不起来。
在部署推理的时候使用低精度的数据,比如INT8、FP16等就是解决大计算量以及提升推理速度的一种方法。当然解决大计算量问题的方法,还有模型压缩这类方法。但本文的方法专注于模型推理阶段的优化。
那么问题就来了,使用更低精度的数值表示会不会降低原来的模型准确性。毕竟如表格1所示,不同精度的动态范围相差还是很大。
对这个精度损失的问题,已经有不少学者在经验层面对其进行了相应的分析。比如WhyareEightBitsEnoughforDeepNeuralNetworks?[1]以及LowPrecisionInferencewithTensorRT[2]这两篇博文的提出即便是推理时使用低精度的数据,在提升推理速度的同时,并不会对精度造成太大的影响。博文作者认为神经网络学习到数据样本的模式可分性,同时由于数据中存在的噪声,使得网络具有较强的鲁棒性,也就是说在输入样本中做轻微的变动并不会过多的影响结果性能。甚至有研究发现,在某些场景下,低精度推理能提升结果的准确性。此外ImprovingtheSpeedofNeuralNetworksonCPUs[3]和TrainingDeepNeuralNetworkswithLowPrecisionMultiplications[4]这两篇文章则在理论上其进行了分析论证。
由于INT8的低存储占用以及高通过率,但是由于其表示范围与FP32相差还是太大,实际上将FP32精度降为INT8精度,即用8bit来表示原来用32bit表示的tensor,这其实相当于信息再编码过程,而且不能有明显的精度损失,还是具有相当大的挑战。该转换过程需要将每一层输入张量(Tensor)和网络学习的参数都从原来的FP32表示转为INT8表示。因此需要最小化该转换过程的信息损失,而且转换方式得要是简单而且计算效率高的。TensorRT采用是简单有效的线性量化的转换方式。即式(1):
FP32Tensor(T)=FP32scalefactor*8-bitTensor(t)+FP32_bias(b)(1)
其中Nvidia的研究者经过证明可以将其中的偏置项去掉,即式(2):
FP32Tensor(T)=FP32scalefactor*8-bitTensor(t)(2)
那么在转换过程中最重要的就是确定这个scalefactor,最简单的方法就是如图3左边所示的直接将FP32tensor值中的–
max
和
max
映射为INT8对应的-和,中间的值按照线性的关系进行映射,该方法也被称为不饱和(Nosaturation)映射。但是经过实验表明,该种方式有明显的精度损失。因此TensorRT的开发者采用被称为饱和(saturate)映射的方式,如图3右边所示:
相对于非饱和映射,不再是直接将两端的±
max
值映射到±,而是选取一个阈值
T
,将±
T
映射为±,其中
T
max
。在[-
T
,
T
]区间外的值直接映射为±,比如图3中的三个红色x点就直接映射为-,而在[-
T
,
T
]区间内的按照线性映射的方式。
TensorRT开发者分别对网络推理过程中涉及的权重(weights)和激活值(activation)做了实验,得出对权重做饱和映射相对于不饱和方式并没有精度的提高,而对激活值做饱和映射有明显的精度提升。因此在TensorRT中对权重采用的是不饱和映射的方式,对激活值采用的是饱和映射的方式。
那么为什么非饱和映射的方式相对饱和映射有精度的提升?此外非饱和映射中的T要如何选取呢?首先来看下图右边所示,该图是resnet-网络模型中间层的激活值统计,横坐标是激活值,纵坐标是统计数量的归一化表示。
可以看到图4中白线左边的激活值分布比较的集中重合,而白线(该线对应的就是阈值T线)右边,即红色框内的激活值就比较的分散,而且在红色框内的激活值在整个层中所占的比例比较少,因此这部分可以不考虑到映射关系中,如图右边所示。研究发现大部分的网络都具有这种大部分激活值集中,少量激活值分散的特点。
T值需要满足FP32模式到INT8模式转换的信息损失最小化,而信息损失可以用KL散度(也叫做相对熵)来衡量,即如式(3)所示:
KL_divergence(P,Q):=SUM(P*log(P/Q),i)(3)
其中P,Q分别表示FP32和INT8模式下的分布,每一层tensor对应的T值都是不同的,而确定T值的过程被称为校准(Calibration),如图5所示校准的原理图。
首先需要在校准数据集(CalibrationDataset)做FP32推理,然后获取每一层激活值的直方图,并用不同的量化阈值生成相应的量化分布。其中量化阈值就如上面的激活值直方图中,等间隔的虚线所对应的激活值就是量化阈值,我们需要的T值就是这些虚线中能够使得KL散度最小化的激活值。这个校准是需要一些时间的,所以每次进行量化的时候,会将校准得到的T值都保存在相应的文件中,待下次进行FP32到INT8推理模式转换的时候,直接读取保存了每层T值的文件,这样可以节省整个流程的时间。
显而易见的是校准数据集(CalibrationDataset)会直接的影响到激活值的分布,进而影响到T值的选择。校准数据集要具有代表性、多样性,比如在图像分类应用中,校准数据集的要能够代表所有的分类目标。验证集(validationdataset)的子集是比较理想的校准集,当然有人或许会问,把全部的数据用于校准不就可以最好的体现原始数据分布么?但是这样的话也会增加整个流程的时间,而经过研究和实验表明校准集只需要个样本即可。
TensorRTINT8量化的性能和精度,图6和图7来自Nvidia官方的PPT。
从上面图6和图7中可以看到经过校准的INT8推理相对于FP32的推理,准确率(Accuracy)有略微的损失,也可见在部分情况下(图6表格中绿色所示)INT8推理相比FP32推理准确率有略微提升。另外可以看见一个趋势,随着Calibrationdataset中图片数量的增加,INT8相对于FP32的精度损失是在逐渐减小。从Performance这张图中可见在不同的推理BatchSize(注意实际推理的BatchSize和Calibration过程中的BatchSize并不需要保持一致)设定下,INT8推理相比于FP32推理的加速比。图中可见BatchSize越大,加速效果越好,在BatchSize为的时候,加速比大约在3.5倍左右,当然实际的加速比和硬件平台,还有神经网络本身也有关系。除了速度上面的提升以外,低精度推理在存储消耗上相对于FP32也有相应的优化,如图8所示:
图8中,INT8onP40即表示在P40显卡上进行INT8推理,可以看出相比FP32推理模式内存占用减少了3倍多,而速度提升了3倍多。而FP16模式也减少了30%的内存占用,速度提升了近两倍。
当然,上述的实验对比测试均来自Nvidia官方,具体到我们实际的深度学习场景,还需要经过实验进行对比精度的损失以及速度的提升,在第三章中,将会概述我们团队利用TensorRT加速人脸识别的实验流程以及效果,还有在实施中遇到的一些问题和解决方法。
②神经网络优化
TensorRT除了通过支持FP16和INT8这两种低精度模式的推理来提升速度以外,其在底层会根据GPU特性对神经网络进行相应的重构和优化。首先是其会删除一些并没有使用输出的层,以避免不必要的计算。然后会对神经网络中一些可以合并的运算进行合并,例如在图9所示的原始网络,TensorRT会将其中的conv、bias、relu这三个层融合在一个层中,即图10所示的CBR层,这个合并操作也被成为垂直层融合。进一步的还有水平层融合,即如图10到图11的过程,将处于同一水平层级的1x1CBR融合到一起。
2、InferenceServer
InferenceServer是一类为机器学习模型提供一站式管理、推理服务、集成等功能的高性能模型服务系统。以下简要介绍几种常见的InferenceServer。
①TensorFlowServing
TensorFlowServing是由Google的TensorFlow团队开发的一种灵活的、高性能的机器学习模型服务系统,专为生产环境设计。在机器学习推理方面,其可以对训练后的模型进行生命周期管理,通过高性能、引用计数的查找表为客户端提供版本化访问。其提供了与TensorFlow模型开箱即用的集成,也能拓展到其他模型。如果模型由TensorFlow训练生成的,用TensorFlowServing最为方便。详细介绍参见