当前位置:   article > 正文

推理引擎之模型压缩浅析_推理引擎 模型压缩

推理引擎 模型压缩

前言

这篇文章主要分享下博主最近在 B 站上偶然间看到的一个视频,该视频对模型压缩相关知识进行了简单的介绍,包括量化、剪枝、蒸馏、二值化。比较适合博主这种对各种概念模糊的初学者,因此记录下方便下次查看,博主也就把原作者的话复述了一遍,大家可以自行查看原视频。

视频链接:【推理引擎】模型压缩

文档链接:https://github.com/chenzomi12/DeepLearningSystem/tree/main/043INF_Slim

1. 模型压缩架构和流程介绍

这个系列主要是和大家分享推理引擎或者推理系统里面的模型压缩,也可以叫模型小型化或者模型轻量化。

我们主要是和大家分享模型压缩的 4 件套:

  • 低比特量化
  • 二值化网络
  • 模型剪枝
  • 模型蒸馏

下面来看下在整个推理引擎架构图里面,模型压缩所处位置

在这里插入图片描述

首先最上面有个 API 的层,接着有个模型转换,它会把从不同的 AI 框架训练出来的网络模型转换成为推理引擎的自己的 IR,或者自己的 Schema,那转换成为自己的 IR 之后呢就会经过模型压缩这个功能,那可能会做一些量化、蒸馏、剪枝、二值化,可能会把模型压缩的四件套同时用起来,那这个时候就叫做多维混合压缩算法。实现完模型的压缩之后就真正的去把网络模型给到 Runtime 还有 Kenrel 去执行在不同的硬件上面,这就是整体的流程。

那我们最主要的关注点就是对模型进行压缩,把模型变得越小越好,减少网络模型的大小;第二个就是加快整个推理的速度,使得在推理引擎里面跑得越快越好;最后就是要求保持相同的精度,即在精度损失较小的前提下去减少网络模型的大小和推理速度。

下面我们来看看整体的推理流程,如下图所示:

在这里插入图片描述

我们会把很多不同 AI 框架训练出来的网络模型转换成为推理的模型,接着经过一个模型压缩模块后输出执行,通过模型压缩,如果能使得模型又小,速度又快,精度还能无损,那这是最好的。

OK!以上就是关于模型压缩架构和流程的简单介绍,下面我们会来介绍下具体的压缩方法。

2. 低比特量化原理

这小节内容主要分享量化基础、量化三种方法以及量化算法的原理

2.1 量化基础介绍

模型量化是一种将浮点计算转成低比特定点计算的技术,可以有效的降低模型计算强度、参数大小和内存消耗,但往往带来巨大的精度损失。尤其是在极低比特(<4bit)、二值网络(1bit)、甚至将梯度进行量化时,带来的精度挑战更大。

在这里插入图片描述

如上图所示,数值在计算机里面有多种表示方法,如 FP32、FP16、INT32、INT16 以及 INT8 等,其中 FP32 是我们一般用来去做模型训练的一个精度,我们随便打开一个 ONNX 模型,可以看到里面存储的数据的类型是 float32 即 FP32

在这里插入图片描述

很多时候在模型训练时我们会开启混合精度,即 –amp 参数的指定。那所谓的混合精度一般是把 FP32 和 FP16 混合到一起去训练,FP16 占用的内存位置或地址空间相比于 FP32 确实少了很多。一般我们所说的模型量化,除了把 FP32 的精度降成 FP16,更多的是降到 INT16、INT8 甚至 INT4 更低比特的一种表示,把 FP32 的 32 位比特转换成为更低比特的方式或者技术就叫做模型量化

接下来我们看下神经网络有什么特点

在这里插入图片描述

上图展示了不同的深度学习模型在计算复杂性和分类精度的关系,可以看到基本上模型的效果越好其计算复杂度也越高,相对较大的神经网络模型一般有以下几个特点:

  • 1. 数据参数量大
  • 2. 计算量大
  • 3. 内存占用大
  • 4. 模型精度高

但是当我们要把模型部署起来,特别是在一些资源有限的移动端和边缘嵌入式设备,我们就不得不考虑模型的计算复杂度和参数量了,我们当然希望我们的模型又小,精度又高。

特别是目前的大语言模型,动不动就几百亿的参数量,它们更加需要量化压缩这些技术来减少模型的参数量,提高模型的推理速度。因此我们还是有必要去了解模型压缩相关技术的。

那我们先不去谈模型量化到底做了什么,我们先来看看模型量化的一些优点,主要有以下几点:

  • 1. 保持精度:量化会损失精度,因为这相当于给网络引入了噪声,但是神经网络一般对噪声是不太敏感的,只要控制好量化的程度,对高级任务精度影响可以做到更小。博主之前的文章有测试过 YOLOv5 模型的量化,FP32 到 FP16 基本无损,FP32 到 INT8 会掉 3~4 个点左右,这取决于你的量化方式,QAT 量化相比于 PTQ 量化掉点要好些
  • 2. 加速计算:传统的卷积操作都是使用 FP32 浮点数进行的计算,低比特的位数减少计算性能也更高,INT8 相对比 FP32 的加速比可达到 3 倍甚至更高。博主之前的文章有测试过 YOLOv5 模型的量化,FP16 比 FP32 快 2.4 倍,INT8 比 FP32 快 3 倍
  • 3. 节省内存:与 FP32 类型相比,FP16、INT8、INT4 低精度类型所占用空间更小,对应存储空间和传输时间都可以大幅下降
  • 4. 节能和减少芯片面积:每个数值如果使用了更少的位数表示,则做运算时需要搬运的数据量就少了,减少了访存开销(节能),同时所需的乘法器数目也减少了(减少芯片面积)

下面我们来看下模型量化的五个特点:

  • 1. 参数压缩
  • 2. 提升速度
  • 3. 降低内存
  • 4. 功耗降低
  • 5. 提升芯片面积

也就是对上面的优点进行了一个简单的总结。

接着我们来看下量化技术落地的三大挑战

1. 精度挑战

  • 量化方式:现在的量化方法大部分是线性量化,但线性量化对数据分布的描述不精确
  • 低比特:从 16bits → 4bits 比特数越低,精度损失越大
  • 任务:分类、检测、分割中任务越复杂,精度损失越大
  • 大小:模型越小,精度损失越大

2. 硬件支持程度

  • 不同硬件支持的低比特指令不相同,比如 Jetson nano 就不支持 INT8
  • 不同硬件提供不同的低比特指令计算方式不同(PF16、HF32)
  • 不同硬件体系结构 Kernel 优化方式不同

3. 软件算法是否能加速

  • 混合比特量化需要进行量化和反量化,如果硬件指令不支持低比特,但我还是想要做量化,这时需要插入 Cast 算子,但 Cast 算子将影响 kernel 执行性能
  • 降低运行时内存占用,与降低模型参数量的差异
  • 模型参数量小,压缩比高,不代表执行内存占用少

OK!以上就是关于量化基础知识的介绍,下面我们来看量化方法

2.2 量化方法

量化方法现在来看一般分为三大种:

  • 量化训练(Quant Aware Training,QAT)
    • 量化训练让模型感知量化运算对模型精度带来的影响,通过 finetune 训练降低量化误差
    • 具体实现可以参考:YOLOv5-QAT量化部署
  • 动态离线量化(Post Training Quantization Dynamic,PTQ Dynamic)
    • 动态离线量化仅将模型中特定算子的权重从 FP32 类型映射成 INT8/16 类型
  • 静态离线量化(Post Training Quantization Static,PTQ Static)
    • 静态离线量化使用少量无标签校准数据,采用 KL 散度等方法计算量化比例因子
    • 具体实现可以参考:YOLOv5-PTQ量化部署

下面我们来看一个图,更好的去理解这三种具体的算法

在这里插入图片描述

首先就是感知量化 QAT,我们会先准备一个训练好的网络模型,然后对它进行一个转换,具体是插入一些伪量化的算子,也就是我们常说的 Q/DQ 节点,从而得到一个新的网络模型,接着对新的网络模型进行 Finetuning 微调得到真正量化后的模型,最后交给部署端。

静态离线量化 PTQ-static,首先准备一个训练好的网络模型和一堆训练的数据,然后通过训练数据对模型进行校准,校准的方法可能会用 KL 散度或者其它的方式

动态离线量化 PTQ-dynamic,准备一个网络模型,然后对其进行转换,最后得到转换后或者量化后的网络模型(使用较少

现在我们来看一下这三种方法有什么区别,对它们做一个简单的比较,如下表所示:

量化方式功能经典适用场景使用条件易用性精度损失预期收益
量化训练(QAT)通过 Finetune 训练将模型量化误差降到最小对量化敏感的场景、模型,例如目标检测、分割、OCR 等有大量带标签的数据极小减少存续空间4x,降低计算内存
静态离线量化(PTQ Static)通过少量校准数据得到量化模型对量化不敏感的场景,例如图像分类任务有少量无标签数据较好较少减少存续空间4x,降低计算内存
动态离线量化(PTQ Dynamic)仅量化模型的可学习权重模型体积大、访存开销大的模型,例如 BERT 模型一般一般减少存续空间2/4x,降低计算内存

QAT 量化训练的精度损失确实比较少,但它的缺点是需要大量带标签的数据进行 Finetune;PTQ Static 静态离线量化方式的好处是精度损失也是比较小的,但不能说没有,因为它缺少了 Finetune 训练的步骤,它只需要有一些少量无标签的数据进行校准;PTQ Dynamic 动态离线量化方法的精度损失一般来说不可控,但它没有任何使用的约束,你想咋用就咋用。

OK!以上就是关于量化方法的介绍,下面我们正式进入到量化原理的分析

2.3 量化算法原理

模型量化桥接了定点和浮点,建立了一种有效的数据映射关系(主要是线性映射),使得以较小的精度损失代价获得了较好的收益。

在这里插入图片描述

上面这个图表示了从定点到浮点的映射,先看左图,上面是指浮点数权重参数的数值,它有最小值和最大值,当然也有 0 值,现在我们希望把这一堆数据映射到一个具体的范围 -127-127 之间,其实就是 INT8 所表示的范围。

当然还有另外一种映射方式,就是截断的方式,看右图,我们会去设置一个最小值和最大值,把最小值和最大值范围内的参数去映射到 -127-127 之间,而不在这个范围内的数据直接把它丢弃掉,这个就是简单的量化方法。

量化的类型其实可以分为对称量化和非对称量化,所谓的对称很简单,就是以 0 作为中心轴,量化范围从 -127-127,就是两边的对称,可以用 INT 来表示。另一种非对称量化可能就没有中心轴了,以 0 作为开始,以 255 作为结束,这种表示方式直接可以使用 UINT 去进行一个表示

在这里插入图片描述

下面我们真正的来到了量化的原理。

要弄懂模型量化的原理就是要弄懂定点和浮点之间的数据映射关系,浮点和定点数据的转换公式如下:
Q = R S + Z R = ( Q − Z ) ∗ S

Q=RS+ZR=(QZ)S
QR=SR+Z=(QZ)S

  • R R R 表示输入的浮点数据,FP32、FP16 都行
  • Q Q Q 表示量化之后的定点数据,INT 类型的数据
  • Z Z Z 表示零点(Zero Point)的数值,偏移值用于决定做对称量化还是非对称量化
  • S S S 表示缩放因子(Scale)的数值

第一条公式叫做量化,第二条公式叫做反量化

这里面最重要的就是找到缩放因子 S S S 和零点 Z Z Z,有了它们就能够求得 Q Q Q。那如何求取 S S S Z Z Z 呢?其实有很多种方法,这里列举其中比较简单一种方式(MinMax)如下:
S = R max − R min Q max − Q min Z = Q max − R max S

S=RmaxRminQmaxQminZ=QmaxRmaxS
SZ=QmaxQminRmaxRmin=QmaxSRmax

  • Rmax 表示输入浮点数据中的最大值
  • Rmin 表示输入浮点数据中的最小值
  • Qmax 表示最大的定点值(127/255)
  • Qmin 表示最小的定点值(-128/0)

下面我们来看下 MinMax 方式的实际使用公式推导

1. 量化算法原始浮点精度数据与量化后 INT8 数据的转换如下:
f l o a t = s c a l e × ( u i n t + o f f s e t ) float = scale\times(uint+offset) float=scale×(uint+offset)

  • f l o a t float float 表示原始模型中的 float32 精度的数据
  • s c a l e scale scale 表示缩放尺度
  • u i n t uint uint 表示量化后模型中的 int8 精度的数据
  • o f f s e t offset offset 表示偏移量 Z Z Z
  • 这是反量化公式

2. 确定后通过原始 float32 高精度数据计算得到 uint8 数据的转换即如下公式所示:
u i n t 8 = r o u n d ( f l o a t / s c a l e ) − o f f s e t uint8 = round(float/scale)-offset uint8=round(float/scale)offset

  • r o u n d round round 表示四舍五入操作
  • 这是量化公式

3. 若待量化数据的取值范围伪 [ X m i n , X m a x ] [X_{min},X_{max}] [Xmin,Xmax],则 s c a l e scale scale 的计算公式如下:
s c a l e = ( x max − x min / Q max − Q min ) scale = (x_{\text{max}}-x_{\text{min}} / Q_{\text{max}}-Q_{\text{min}}) scale=(xmaxxmin/QmaxQmin)
4. o f f s e t offset offset 的计算方式如下:
o f f s e t = Q min − r o u n d ( x min / s c a l e ) offset = Q_\text{min} - round(x_{\text{min}}/scale) offset=Qminround(xmin/scale)
其它求取的 S S S Z Z Z 方式可以参考:TensorRT量化第三课:动态范围的常用计算方法

OK!以上就是关于量化算法原理的知识,在下节中我们将会讨论感知量化训练 QAT 的相关知识。

2.4 讨论

讨论1:在量化基础介绍小节中我们有介绍模型量化的最终目的是得到更小性能更好的小模型,那我们为什么不直接训练一个小模型呢?在小模型上面调参让它性能更好呢?

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/376548
推荐阅读
相关标签