文@小P家的021419
0 前言
在模型实践的业务落地进程中,咱们是否遇到过这样的场景:含辛茹苦练习出了精度满足业务需求的模型,总算能够上线啦!经过模型转换、量化、打包等等一系列复杂的流程后,成功布置到实践硬件渠道上,模型总算能够运转了!然而一波操作猛如虎,模型精度与最初练习成果比较却下降了不少……一脸茫然,不知所措,彻底不知该从何下手,也不知道怎样才能有效的康复模型的练习精度。 本次共享将针对布置流程中导致精度下降的头号疑犯——模型量化进行剖析,带咱们一探精度丢失的幕后真相。
本文将从以下三个方面进行“揭秘”:
- 量化的根本进程
- 量化的丢失来历
- 常见芯片的量化支撑
1 量化的根本进程
模型量化粗略地能够分为在线量化(Quantization Aware Training, QAT)和离线量化(Post Training Quantization, PTQ)两大类。 尽管在线量化能够对量化后的模型精度提供更高的保证,但因其与模型的练习进程过于耦合,开发本钱和门槛较高,在模型布置阶段选用更多的是另一种办法——离线量化。因而,本文首要针对选用离线量化办法对模型量化后,产生的精度丢失进行剖析。
图1 量化的三阶段步骤示意图
神经网络的量化本质上是将数据从接连空间 C\mathbb{C} 映射到离散空间 D\mathbb{D},这个进程一般包括三个阶段:数据缩放(scale),数据离散化(discretize),数据反向缩放(rescale)。 三个阶段之间关系的能够形式化描绘如下:
Q(x)=f−1(round(f(x)))Q(x) = f^{-1}(round(f(x)))
输入数据xx是来自接连空间C\mathbb{C}的全精度值,即原始的浮点精度表明数据,Q(x)Q(x)是量化后在离散空间D\mathbb{D}中的对应值,即定点类型的数据。 首要,缩放函数f(⋅)f(\cdot)将数据xx从原始空间 C\mathbb{C} 的表明规模缩放到离散空间D\mathbb{D}。 然后,缩放后所得到的数据被离散化为归于离散空间 D\mathbb{D} 内的中心值zz,该阶段最常用的离散函数是round(⋅)round(\cdot)。 最后,由于量化操作只改动数据的表明精度,不更改数据的表明规模,所以离散化后的中心值zz需求运用反向缩放函数f−1(⋅)f^{-1}(\cdot),从头调整zz到与xx在原始空间 C\mathbb{C} 中相同的表明规模。在不同的量化办法中,数据缩放函数和数据离散函数各不相同。
当时较为成熟且运用较多的量化机制为线性均匀量化,指缩放函数f(⋅)为线性映射函数,离散空间f(\cdot)为线性映射函数,离散空间 \mathbb{D}中的各个离散值之间的间隔是均匀的。如运用的是线性量化,原始数据中的各个离散值之间的间隔是均匀的。如运用的是线性量化,原始数据x的数值表明规模为的数值表明规模为[\alpha, \beta]$,缩放函数能够表明为:
f(x)=scale_factor∗clip(x,,)+zero_pointf(x) = scale\_factor * clip(x, \alpha, \beta) + zero\_point
在对称量化中,zero_point设置为0,一起要求 −=-\alpha = \beta;在非对称量化中,zero_point会依据实践的数据规模进行确认,一般会选取zero_point=round(−2)zero\_point = round(\frac{\alpha – \beta}{2})。
2 量化的丢失来历
实践布置进程中,为了获得更大的压缩率和更快的运转速度,或受限于布置渠道的核算单元类型,模型一般需求对整个网络模型的权值和激活值均进行定点量化。为了简化评论,咱们以一层卷积作为示例,选用线性均匀量化的办法,并假设bias已经经过优化融合到了conv的weight中。如下图所示,整层网络的核算差错首要来自于三部分:
图2 量化的差错位置来历示意图
- W\Delta W 权值数据量化引进的差错,首要来自于不同量化办法的选取产生的差错。因weights的数值是确认可控的,其他来历的差错(如取整舍入差错)能够进行部分修正,归于可控差错,此处暂不进行具体的剖析。
- X\Delta X 激活值数据量化引进的差错,首要来自于不同量化办法产生的差错和数值取整核算带来的差错。
- Y\Delta Y 核算进程中数据累计核算的差错,一方面来自多项数据进行累加和累乘等核算进程中,数值溢出和取整等核算带来的差错,另一方面来自定点芯片需求在定点域核算原本应该在浮点域核算的缩放函数和反向缩放函数,产生必定的核算差错。
为了进一步考虑上述差错是如安在核算进程中引进的,咱们固定量化的比特位数NN。依据量化的三个核算阶段咱们能够看到,均匀线性量化进程中涉及到的可能引进差错的操作首要有三个:Round操作,Clip操作,scaling factor的选取。Round和Clip操作引进的即为前文所指的各类取整和溢出差错,不同的线性均匀量化办法和优化战略本质上即为不同scaling factor的选取。三者对差错的引进和影响是紧耦合在一起的,相互作用和影响,需求进行必定的trade-off。
Round操作完成数据的离散化,将原始接连空间的数值映射到间隔它数值最近的离散点。原始数据xx和其映射后所对应的离散值x′x^{\prime}之间的差值xr=x−x′\Delta x_r = x – x^{\prime}即为Round操作引进的量化差错。咱们能够将差错项近似看做遵守均值为0的正态散布,则有:
关于每一部分的量化差错, 其最大值不会超越两个相邻的量化离散值的间距,依据公式可知离散量化值之间的间距由原始数据的动态表明规模 −\beta – \alpha 决议。在NN固定的情况下,动态表明规模越大,由Round操作引发的量化丢失也就越大。
Clip操作对[,][\alpha, \beta]外的数据进行截取,使得一切的数据都在动态表明规模内。这些超出规模的数据xx需求截取映射到\alpha或者\beta, 之间的差值即为Clip操作引进的量化差错。
咱们来看一个遵守正态散布的浮点数据进行线性均匀量化的进程示意:
图3 浮点数据离散化示意图
在图3(a)中,咱们选取原始数据的真实最小值和最大值作为动态表明规模[,][\alpha, \beta],因而不存在超出规模的数值点,即xc=0\Delta x_c = 0;因动态表明规模过大,各个离散数据值之间的间隔较大,会导致xr\Delta x_r偏大。在图3(b)中,咱们选取了较为适宜的动态表明规模来尽可能减小xr\Delta x_r,使得较多的数据散布在[,][\alpha, \beta]外围,这些数据会引进较大的xc\Delta x_c,在长尾散布中引进的差错尤为显着。当时不同的量化算法和优化战略往往是寻觅一个恰当的[,][\alpha, \beta],使得xr+xc\Delta x_r+\Delta x_c较小。
Scaling factor和动态表明规模在不同的量化办法中有着不同的核算办法,例如在线性均匀量化中,二者之间的关系为:
scale_factor=2N−1−scale\_factor = \frac{2^N – 1}{\beta – \alpha}
一般确认了二者中的一个,别的一个能够依据公式核算得来。除了上述提到的xr\Delta x_r和xc\Delta x_c, scaling facor引进的量化差错首要来历于各个离散数值利用率的平衡性。例如在图3(a)中,动态规模选取较大带来的别的一个坏处,即为离散数值利用率不均衡的问题。关于N−bitN-bit的量化,离散数值共有2N2^N种挑选(在部分量化战略中会强制保存1-bit表明数值0,则离散数值的挑选剩余2N−12^N – 1种)。神经网络的原始浮点数据一般遵守长尾正态散布,大部分的数值散布在均值邻近,量化后映射到0值邻近;小部分数值会散布在远离均值的位置,带有必定信息量无法彻底直接舍弃。较大的动态规模使得离散数值之间的间距较大,大部分散布在均值邻近的数据只能映射到少数的离散值上,导致N−bitsN-bits的实践表明能力会丢失1∼2bits1 \sim 2 bits甚至更多。 怎么平衡各个离散数值之间的数据散布和利用率,是当时一些量化战略削减数化丢失的方向。
3 常见芯片的量化支撑
需求进行量化的模型,其布置目标渠道多为边缘侧/终端侧,即对模型的大小和运转速度有必定约束和要求的移动端和嵌入式设备。较为常用的典型硬件渠道有NVIDIA Jetson系列GPU、Qualcomm Hexagon系列DSP、以及新式的神经网络加速器。在加速器系列中,咱们选取寒武纪(Cambricon)的推理芯片为例,各类硬件渠道对量化的支撑情况如下表所示:
硬件渠道 | 后端推理库 | 权值数据量化支撑类型 | 是否支撑外部参数写入 |
---|---|---|---|
NVIDIA Jetson [1] | TensorRT | per-tensor & per-channel | Yes |
Quanlcomm Hexagon DSP [2] | SNPE | per-tensor | No |
Cambricon MLU [3] | CNRT | per-tensor & per-channel | Yes |
其间per-tensor的量化办法也称per-layer,指关于给定的网络层的weight tensor中的一切数据共享一个量化参数;per-channel也称per-axis,指关于给定网络层的weight tensor,每一个axis对应一个channel,每个channel有自己独立的量化参数。一般情况下,per-channel由于量化的粒度更细致,量化参数的自由度更高,往往更优于per-tensor的量化精度。 NVIDIA TensorRT在对权值(weights)的量化上支撑per-tensor和per-channel两种办法,选用对称最大值的办法 [4];关于激活值(activations)只支撑per-tensor的办法,选用KL-divergence的办法进行量化;量化参数既支撑内部主动生成,也支撑外部指定,支撑weights和activations选用不同的指定办法。更为具体的机制解析和运用办法已有官方技能文档 [5]和很多文章 [6]进行了剖析讲解,感兴趣的同学能够自行阅览,此处不再赘述。 Quanlcomm Hexagon DSP的官方后端推理库SNPE只支撑per-tensor的量化办法,选用非对称最大最小值的办法 [7],并提供Enhanced Quantization Mode进行精度优化,暂不支撑外部量化参数写入。为了补偿SNPE在运用时的量化精度丢失,Quanlcomm推出了自己的模型量化压缩工具AIMET [8],支撑DFQ [9]、AdaRound [10]等量化算法,依托于AIMET也能够完成部分外部量化参数的写入。 寒武纪MLU系列加速器的官方后端为CNRT,同样支撑per-tensor和per-channel两种量化办法,也支撑外部参数的写入,但只支撑weights和activations选用同样的指定办法,即一起由内部生成或一起由外部指定。咱们能够看到,当时的硬件渠道除了本身的工具链提供的原生量化办法外,大部分均支撑外部参数的写入,经过指定scaling_factor或动态规模[,][\alpha, \beta]二者之一,别的一个在内部经过核算得到。当原生量化工具无法满足模型布置精度需求时,咱们能够经过差错剖析,自行调整量化参数,然后到达康复精度的意图。
4 结语
本文对量化进程中的差错来历进行了粗略的归类,理解这些差错如安在核算进程中引进,并对各个差错项之间的耦合和影响关系进行了剖析。当时很多量化算法和优化战略本质上仍是在寻觅一些减小这些差错项的办法,并在其间寻觅平衡点。例如,AdaRound算法不再选用四舍五入的办法,而是选用一种自运用的战略动态决议向上取整仍是向下取整,然后减小Round操作引进的差错项xr\Delta x_r;DFQ算法经过核算恒等性修改权值数据的散布,削减长尾部分的数据,然后削减Clip操作引进的差错项xc\Delta x_c,一起也能够有效下降xr\Delta x_r和离散值利用率低的问题;ACIQ [11]算法直接经过对优化问题求解,得到最优的动态规模,然后下降上述差错项,等等。本文对量化差错背后的根本原理进行了介绍,关于怎么评价哪类差错对整个网络最终的成果起到了更大的影响,怎么依据丢失去挑选适宜的量化算法等问题,欢迎继续重视AI结构技能共享模型布置专题系列。
PS:欢迎咱们重视AI结构技能共享专栏内容,假如有感兴趣的技能内容和难点欢迎随时指出,能够多多谈论留言。咱们也希望能经过本次技能共享让咱们了解到更多的AI结构前沿技能,也期待和咱们一起评论,更欢迎咱们加入咱们,一同为AI结构及AI开展贡献力量!简历直投邮箱:parrotshr@sensetime.com
感谢阅览,欢迎在谈论区留言评论哦~
P.S. 假如喜爱本篇文章,请多多 点赞,让更多的人看见咱们 :D
重视 大众号「SenseParrots」,获取人工智能结构前沿业界动态与技能考虑。