基本概念
模型量化技术可以通过减少深度神经网络模型参数的位宽和中间过程特征图的位宽,从而达到压缩加速深度神经网络的目的,使量化后的网络能够部署在资源有限的边缘设备上。
问题定义
神经网络模型的量化问题可以被定义为以下的优化问题:
对于神经网络模型 G \mathcal{G} G ,假设其内部包含 t t t 个需要被量化的参数层,所有参数层中的权值组成集合 W = { w 1 , ⋯ , w t } \mathcal{W} = \{\mathbf{w}_1, \cdots, \mathbf{w}_t\} W = { w 1 , ⋯ , w t } ;同时,其内部包含 m m m 个需要被量化的激活值层,所有激活值层中的值组成集合 A = { a 1 , ⋯ , a m } \mathcal{A} = \{\mathbf{a}_1, \cdots, \mathbf{a}_m\} A = { a 1 , ⋯ , a m } 。给出所有权值和激活值对应的量化映射集合 F = { q 1 ( w 1 ; b 1 ) , ⋯ , q t + m ( a m ; b t + m ) } \mathcal{F} = \{q_1(\mathbf{w}_1; b_1), \cdots, q_{t+m}(\mathbf{a}_m; b_{t+m})\} F = { q 1 ( w 1 ; b 1 ) , ⋯ , q t + m ( a m ; b t + m )} ,其中 q i q_i q i 表示第 i i i 个参数层或激活值层的量化映射,b b b 为量化映射后低精度数值的位宽。将此量化映射插入到神经网络模型 G \mathcal{G} G 中的特定位置,形成量化网络模型 Q \mathcal{Q} Q 。通过优化量化映射集合 F \mathcal{F} F ,使得量化网络模型 Q \mathcal{Q} Q 的损失函数 L ( Q ) L(\mathcal{Q}) L ( Q ) 最小,即:
min F , W ∣ L ( Q ) − L ( G ) ∣
\min_{\mathcal{F,W}} |L(\mathcal{Q}) - L(\mathcal{G})|
F , W min ∣ L ( Q ) − L ( G ) ∣
量化计算原理
以线性非对称量化为例,浮点数量化为有符号定点数的计算原理如下:
x int = clip ( ⌊ x s ⌉ + z ; − 2 b − 1 , 2 b − 1 − 1 )
\mathbf{x}_{\text{int}} = \operatorname{clip}(\lfloor \cfrac{\mathbf{x}}{s} \rceil + z; -2^{b-1}, 2^{b-1}-1)
x int = clip (⌊ s x ⌉ + z ; − 2 b − 1 , 2 b − 1 − 1 ) 其中,x \mathbf{x} x 为输入的浮点数值,x int \mathbf{x}_{\text{int}} x int 为量化后的有符号定点数值,s s s 为量化比例因子,z z z 为量化零点,b b b 为量化后的定点数的位宽,如 INT8 数据类型中 b b b 为 8。clip \operatorname{clip} clip 为截断函数,定义如下
clip ( x ; a , c ) = { a , x < a x , a ≤ x ≤ c c , x > c
\operatorname{clip}(x; a, c) = \begin{cases}
a, & x < a \\
x, & a \leq x \leq c \\
c, & x > c
\end{cases}
clip ( x ; a , c ) = ⎩ ⎨ ⎧ a , x , c , x < a a ≤ x ≤ c x > c 从定点数转换为浮点数称为反量化过程,具体定义如下:
x ≈ x ^ = s ( x int − z )
\mathbf{x} \approx \hat{\mathbf{x}} = s({\mathbf{x}_{\text{int}} - z})
x ≈ x ^ = s ( x int − z ) 设置量化范围为 ( q min , q max ) (q_{\min},q_{\max}) ( q m i n , q m a x ) ,截断范围为 ( c min , c max ) (c_{\min},c_{\max}) ( c m i n , c m a x ) ,量化参数 s s s 和 z z z 的计算公式如下:
s = q max − q min c max − c min = q max − q min 2 b − 1 z = c max − ⌊ q max s ⌉ 或 z = c min − ⌊ q min s ⌉
\begin{aligned}
s &= \cfrac{q_{\max} - q_{\min}}{c_{\max} - c_{\min}} = \cfrac{q_{\max} - q_{\min}}{2^{b} - 1} \\
z &= c_{\max} - \lfloor \cfrac{q_{\max}}{s} \rceil \text{ 或 } z = c_{\min} - \lfloor \cfrac{q_{\min}}{s} \rceil
\end{aligned}
s z = c m a x − c m i n q m a x − q m i n = 2 b − 1 q m a x − q m i n = c m a x − ⌊ s q m a x ⌉ 或 z = c m i n − ⌊ s q m i n ⌉ 其中截断范围是根据量化的数据类型决定的,如 INT8 的截断范围为 [ − 128 , 127 ] [-128, 127] [ − 128 , 127 ] ;量化范围根据不同的量化算法确定。
量化误差
量化误差来源于舍入误差和截断误差,即 ⌊ ⋅ ⌉ \lfloor \cdot \rceil ⌊ ⋅ ⌉ 和 clip 运算。四舍五入的计算方式会产生舍入误差,误差范围为[ − s 2 , s 2 ] [-\cfrac{s}{2}, \cfrac{s}{2}] [ − 2 s , 2 s ] 。当浮点数 x x x 过大,比例因子 s s s 过小时,容易导致量化定点数超出截断范围,产生截断误差。理论上,比例因子 s s s 的增大可以减小截断误差,但会造成舍入误差的增大。因此为了权衡两种误差,需要设计合适的比例因子和零点,来减小量化误差。
线性对称量化和线性非对称量化
线性量化中定点数之间的间隔是均匀的,例如 INT8 线性量化将量化范围均匀等分为 256 个数。线性对称量化中零点是根据量化数据类型确定并且零点 z z z 位于量化定点数范围上的中心对称点,例如 INT8 中零点为 0。线性非对称量化中零点 z z z 一般不在量化定点数范围上的中心对称点。
对称量化是非对称量化的简化版本,理论上非对称量化能够更好的处理数据分布不均匀的情况,因此实践中大多采用非对称量化方案。
图 1 线性对称量化和线性非对称量化
Per-Layer 量化和 Per-Channel 量化
图 2 Per-Layer 量化和 Per-Channel 量化
注意
Per-Channel 量化中只针对权重进行 Per-Channel 量化,激活值和中间值仍为 Per-Layer 量化。
量化算法
量化比例因子 s s s 和零点 z z z 是影响量化误差的关键参数,而量化范围的求解对量化参数起到决定性作用。本章节介绍三种关于量化范围求解的算法:Max,KL-Divergence 和 MSE, Percentile。
Max 量化算法是通过计算浮点数中的最大值和最小值直接确定量化范围的最大值和最小值。可知,Max 量化算法不会产生截断误差,但对异常值很敏感,因为大异常值可能会导致舍入误差过大。
q min = min V q max = max V
\begin{aligned}
q_{\min} &= \min \mathsf{V} \\
q_{\max} &= \max \mathsf{V} \\
\end{aligned}
q m i n q m a x = min V = max V 其中 V \mathsf{V} V 表示浮点数 Tensor。
KL-Divergence 量化算法计算浮点数和定点数的分布,通过调整不同的阈值来更新浮点数和定点数的分布,并根据 KL 散度最小化两个分布的相似性来确定量化范围的最大值和最小值。KL-Divergence 量化算法通过最小化浮点数和定点数之间的分布差异,能够更好地适应非均匀的数据分布并缓解少数异常值的影响。
arg min q min , q max H ( Ψ ( V ) , Ψ ( V i n t ) )
{\arg\min}_{q_{\min}, q_{\max}} H(\Psi(\mathsf{V}), \Psi(\mathbf{V}_{int}))
arg min q m i n , q m a x H ( Ψ ( V ) , Ψ ( V in t )) 其中H ( ⋅ , ⋅ ) H(\cdot, \cdot) H ( ⋅ , ⋅ ) 表示 KL 散度。Ψ ( ⋅ ) \Psi(\cdot) Ψ ( ⋅ ) 为分布函数,将对应数据计算为离散分布,V i n t \mathbf{V}_{int} V in t 为量化定点数 Tensor。
MSE 量化算法通过最小化浮点数与量化反量化后浮点数的均方误差损失,确定量化范围的最大值和最小值,在一定程度上缓解大异常值带来的量化精度丢失问题。由于MSE 量化算法的具体实现是采用暴力迭代搜索近似解,速度较慢,内存开销较大,但通常会比 Max 量化算法具有更高的量化精度。
arg min q min , q max ∣ ∣ V − V ^ ( q min , q max ) ∣ ∣ F 2
{\arg\min}_{q_{\min}, q_{\max}} ||\mathsf{V} - \hat{\mathbf{V}}(q_{\min}, q_{\max})||_F^2
arg min q m i n , q m a x ∣∣ V − V ^ ( q m i n , q m a x ) ∣ ∣ F 2 其中 V ^ ( q min , q max ) \hat{\mathbf{V}}(q_{\min}, q_{\max}) V ^ ( q m i n , q m a x ) 为 V \mathbf{V} V 的量化、反量化形式,∣ ∣ ⋅ ∣ ∣ F ||\cdot||_F ∣∣ ⋅ ∣ ∣ F 为 F 范数。
Percentile 量化算法通过统计学方法计算浮点数的百分位数来确定量化范围,能有效排除异常值干扰。
q min = percentile ( V , p low ) q max = percentile ( V , p high )
q_{\min} = \text{percentile}(\mathsf{V}, p_{\text{low}}) \\
q_{\max} = \text{percentile}(\mathsf{V}, p_{\text{high}})
q m i n = percentile ( V , p low ) q m a x = percentile ( V , p high ) 该公式中变量定义如下:
V \mathsf{V} V :待量化的原始数据分布(通常为权重或激活值)
p low p_{\text{low}} p low :预设的下分位点(如 p low = 5 % p_{\text{low}}=5\% p low = 5% )
p high p_{\text{high}} p high :预设的上分位点(如 p high = 95 % p_{\text{high}}=95\% p high = 95% )
q min q_{\min} q m i n :通过下分位点计算的最小截断值
q max q_{\max} q m a x :通过上分位点计算的最大截断值
该方法的优势在于: