模型压缩是指对算法模型进行精简,进而得到一个轻量且性能相当的小模型,压缩后的模型具有更小的结构和更少的参数,可以有效降低计算和存储开销,便于部署在端侧设备中。
随着AI技术的飞速发展,不管是移动端产品还是线上产品,进行AI赋能都成为了趋势。这种情况下,AI算法的实时性与减少内存占用都显得极为重要。AI模型的参数在一定程度上能够表达其复杂性,但并不是所有的参数都在模型中发挥作用,部分参数作用有限,表达冗余,甚至会降低模型的性能。
AI服务器与PC端一般都是使用X86架构,因为其高性能;AI端侧设备(手机/端侧盒子等)一般使用ARM架构,因为需要低功耗。
X86指令集中的指令是复杂的,一条很长指令就可以很多功能;而ARM指令集的指令是很精简的,需要几条精简的短指令完成很多功能。
X86的方向是高性能方向,因为它追求一条指令完成很多功能;而ARM的方向是面向低功耗,要求指令尽可能精简。
常规精度一般使用FP32(32位浮点,单精度)占用4个字节,共32位;低精度则使用FP16(半精度浮点)占用2个字节,共16位,INT8(8位的定点整数)八位整型,占用1个字节等。
混合精度(Mixed precision)指使用FP32和FP16。 使用FP16 可以减少模型一半内存,但有些参数必须采用FP32才能保持模型性能。
虽然INT8精度低,但是数据量小、能耗低,计算速度相对更快,更符合端侧运算的特点。
不同精度进行量化的归程中,量化误差不可避免。
在模型训练阶段,梯度的更新往往是很微小的,需要相对较高的精度,一般要用到FP32以上。在inference的阶段,精度要求没有那么高,一般F16或者INT8就足够了,精度影响不会很大。同时低精度的模型占用空间更小了,有利于部署在端侧设备中。
GPU在训练时有两个重要指标可以查看,即显存占用和GPU利用率。
显存指的是GPU的空间,即内存大小。显存可以用来放模型,数据等。
GPU 利用率主要的统计方式为:在采样周期内,GPU 上有 kernel 执行的时间百分比。可以简单理解为GPU计算单元的使用率。
Float32 是在深度学习中最常用的数值类型,称为单精度浮点数,每一个单精度浮点数占用4Byte的显存。
在整个神经网络训练周期中,在GPU上的显存占用主要包括:数据,模型参数,模型输出等。
数据侧:举个🌰,一个323128128的四维矩阵,其占用的显存 = 323128128*4 /1000 / 1000 = 6.3M
模型侧:占用显存的层包括卷积层,全连接层,BN层,梯度,优化器的参数等。
输出侧:占用的显存包括网络每一层计算出来的feature map以及对应的梯度等。
我在之前专门沉淀了一篇关于算法模型部署逻辑的文章,大家可以直接进行阅读取用:
AI端侧设备多聚焦于深度学习算法模型的加速与赋能,而传统图像算法在没有加速算子赋能的情况下,在AI端侧设备无法发挥最优的性能。
首先,假设卷积核的尺寸是 K × K K \times K K×K,有 C C C个特征图作为输入,每个输出的特征图大小为 H × W H \times W H×W,输出为 M M M个特征图。
由于模型参数量主要由卷积,全连接层,BatchNorm层等部分组成,我们以卷积的参数量为例进行参数量的计算分析:
卷积核参数量:
M × C × K × K M\times C\times K\times K M×C×K×K
偏置参数量:
M M M
总体参数量:
M × C × K × K + M M\times C\times K\times K + M M×C×K×K+M
同样,我们假设卷积核的尺寸是 K × K K\times K K×K,有 C C C个特征图作为输入,每个输出的特征图大小为 H × W H \times W H×W,输出为 M M M个特征图。
由于在模型中卷积一般占计算量的比重是最高的,我们依旧以卷积的计算量为例进行分析:
FLOPS(全大写):是floating point operations per second的缩写,意指每秒浮点运算次数,理解为计算速度。是一个衡量硬件性能的指标。
FLOPs(s小写):是floating point operations的缩写(s表示复数),意指浮点运算数,理解为计算量。可以用来衡量算法/模型的复杂度。
针对模型的计算量应该指的是FLOPs。
在上述情况下,卷积神经网络一次前向传播需要的乘法运算次数为:
H × W × M × C × K × K H\times W\times M\times C\times K\times K H×W×M×C×K×K
同时,所要进行的加法计算次数分为考虑偏置和不考虑偏置:
(1)考虑偏置的情况:
为了得到输出的特征图的一个未知的像素,我们需要进行
(
C
×
K
×
K
?
1
)
+
(
C
?
1
)
+
1
=
C
×
K
×
K
(C\times K\times K - 1) + (C - 1) + 1 = C \times K \times K
(C×K×K?1)+(C?1)+1=C×K×K
次加法操作,其中
K
×
K
K\times K
K×K大小的卷积操作需要
K
×
K
?
1
K\times K - 1
K×K?1次加法,由于有C个通道,所以需要将结果乘以C,每个通道间的数要相加,所以需要C - 1次加法,最后再加上偏置的1次加法。
所以总的加法计算量如下:
H × W × M × C × K × K H\times W\times M\times C\times K\times K H×W×M×C×K×K
所以总的卷积运算计算量(乘法+加法):
2 × H × W × M × C × K × K 2 \times H\times W\times M\times C\times K\times K 2×H×W×M×C×K×K
(2)不考虑偏置的情况:
总的卷积计算量:
H × W × M × ( 2 × C × K × K ? 1 ) H\times W\times M\times (2\times C\times K\times K - 1) H×W×M×(2×C×K×K?1)
首先,异构现象是指不同计算平台之间,由于硬件结构(包括计算核心和内存),指令集和底层软件实现等方面的不同而有着不同的特性。
异构计算是指联合使用两个或者多个不同的计算平台,并进行协同运算。比如CPU和GPU的异构计算,TPU和GPU的异构计算以及TPU/GPU/CPU的异构计算等等。
通常的深度学习模型参数是FP32浮点型的,而模型量化主要是使用FP16,INT8以及INT4等低精度类型来保存模型参数,从而有效的降低模型计算量和内存占用,并将精度损失限制在一个可接受的范围内。
模型量化主要分在线量化和离线量化。在线量化在模型训练阶段采用量化方法进行量化。离线量化主要在模型离线工具(模型转换阶段)中采用量化方法进行量化。
工业界中主要使用离线量化作为通用模型量化的解决方案。
模型剪枝按照剪枝粒度可分为突触剪枝、神经元剪枝、权重矩阵剪枝等,主要是将权重矩阵中不重要的参数设置为0,结合稀疏矩阵来进行存储和计算。通常为了保证性能,需要逐步进行迭代剪枝,让精度损失限制在一个可接受的范围。
突触剪枝剪掉神经元之间的不重要的连接。对应到权重矩阵中,相当于将某个参数设置为0。
神经元剪枝则直接将某个节点直接裁剪。对应到权重矩阵中,相当于某一行和某一列置零。
除此之外,也可以将整个权重矩阵裁剪,每一层中只保留最重要的部分,这就是权重矩阵剪枝。相比突触剪枝和神经元剪枝,权重矩阵剪枝压缩率要大很多。
GPU乃至硬件侧的整体逻辑,是CV算法工作中必不可少的组成部分,也是算法模型所依赖的重要物理载体。
现在AI行业有个共识,认为是数据的爆发和算力的突破开启了深度学习在计算机视觉领域的“乘风破浪”,而其中的算力,主要就是指以GPU为首的计算平台。
GPU(Graphical Processing Unit)从最初用来进行图形处理和渲染(玩游戏),到通过CUDA/OpenCL库以及相应的工程开发之后,成为深度学习模型在学术界和工业界的底层计算工具,其有以下的一些特征:
CUDA/cuDNN/OpenCL科普小知识:
深度学习的端侧设备,又可以叫做边缘计算设备,深度学习特别是CV领域中,模型+端侧设备的组合能够加快业务的即时计算,决策和反馈能力,极大释放AI可能性。
深度学习的端侧设备主要由ARM架构的CPU+ GPU/TPU/NPU等协处理器 + 整体功耗 + 外围接口 + 工具链等部分组成,也是算法侧对端侧设备进行选型要考虑的维度。
在实际业务中,根据公司的不同,算法工程师涉及到的硬件侧范围也会不一样。如果公司里硬件和算法由两个部门分别负责,那么算法工程师最多接触到的硬件侧知识就是硬件性能评估,模型转换与模型硬件侧验证,一些硬件高层API接口的开发与使用;如果公司里没有这么细分的部门,那么算法工程师可能就会接触到端侧的视频编解码,模型推理加速,Opencv,FFmpeg,Tensor RT,工具链开发等角度的知识。
首先,整体上还是要将硬件侧工具化,把端侧设备当做算法模型的一个下游载体,会熟练的选型与性能评估更加重要。
端侧设备是算法产品整体解决方案中一个非常重要的模块,算法+硬件的范式将在未来的边缘计算与万物智能场景中持续发力。
在日常业务中,算法模型与端侧设备的适配性与兼容性是必须要考虑的问题,端侧设备是否兼容一些特殊的网络结构?算法模型转化并部署后,精度是否下降?功耗与耗时能否达标?等等都让算法工程师的模型设计逻辑有更多的抓手。
当设置静态多Batch后,如Batch=6,那么之后不管是输入2Batch还是4Batch,都会按照6Batch的预设开始申请资源。
而动态多Batch不用预设Batch数,会根据实际场景中的真实输入Batch数来优化资源的申请,提高端侧实际效率。
由于动态多Batch的高性能,通常Inference耗时和内存占用会比静态多Batch时要大。
ONNX是一种神经网络模型的框架,其最经典的作用是作为不同框架之间的中间件,成为模型表达的一个通用架构,来增加不同框架之间的交互性。
ONNX的优势:
TensorRT是一个高性能的深度学习前向Inference的优化器和运行的引擎。
TensorRT的核心:将现有的模型编译成一个engine,类似于C++的编译过程。在编译engine过程中,会为每一层的计算操作找寻最优的算子方法,将模型结构和参数以及相应kernel计算方法都编译成一个二进制engine,因此在部署之后大大加快了推理速度。
我们需要给TensorRT填充模型结构和参数,也就是解析我们自己的模型结构和参数文件,获取数据放到其中。官方给了三种主流框架模型格式的解析器(parser),分别是:ONNX,Caffe以及TensorFlow。
TensorRT的优势: