大学网站建设工作总结,做一份seo网站诊断,iis如何发布php网站,郑州网站建设及托管1 量化的介绍
量化是减少神经网络计算时间和能耗的最有效的方法之一。在神经网络量化中#xff0c;权重和激活张量存储在比训练时通常使用的16-bit或32-bit更低的比特精度。当从32-bit降低到8-bit#xff0c;存储张量的内存开销减少了4倍#xff0c;矩阵乘法的计算成本则二…1 量化的介绍
量化是减少神经网络计算时间和能耗的最有效的方法之一。在神经网络量化中权重和激活张量存储在比训练时通常使用的16-bit或32-bit更低的比特精度。当从32-bit降低到8-bit存储张量的内存开销减少了4倍矩阵乘法的计算成本则二次地减少了16倍。 神经网络已被证明对量化具有鲁棒性这意味着它们可以被量化到较低的位宽而对网络精度的影响相对较小。然而神经网络的量化并不是自由的。低位宽量化会给网络带来噪声从而导致精度的下降。虽然一些网络对这种噪声具有鲁棒性但其他网络需要额外的工作来利用量化的好处。
量化实际上是将FLOAT3232位浮点数的参数量化到更低精度精度的变化并不是简单的强制类型转换而是为不同精度数据之间建立一种数据映射关系最常见的就是定点与浮点之间的映射关系使得以较小的精度损失代价得到较好的收益。
2 均匀仿射量化
均匀仿射量化也称为非对称量化定义如下 s s s放缩因子scale factor/量化步长step size是浮点数 z z z零点zero-point是整数保证真实的0不会有量化误差对ReLU和zero-padding很重要 b b b位宽bit-width是整数比如2, 4, 6, 8 s s s和 z z z的作用是将浮点数转化为整数范围由b来定
1将真实输入的浮点数 x \mathbb x x转化为无符号整数 x i n t c l a m p ( ⌊ x s ⌉ z ; 0 , 2 b − 1 ) \mathbf{x}_{int} \mathrm{clamp}(\lfloor\frac{\mathbf{x}}{s}\rceilz; 0, 2^b-1) xintclamp(⌊sx⌉z;0,2b−1)
截断/四舍五入函数的定义 c l a m p ( x ; a , c ) { a , x a , x , a ≤ x ≤ b , b , x c . \mathrm{clamp}(x; a, c) \begin{cases} a, x a, \\ x, a \leq x\leq b,\\ b, xc. \end{cases} clamp(x;a,c)⎩ ⎨ ⎧a,xa,x,a≤x≤b,b,xc.
2反量化de-quantization近似真实的输入 x \mathbf x x x ≈ x ^ s ( x i n t − z ) \mathbf x\approx \mathbf{\hat x} s(\mathbf x_{int} -z) x≈x^s(xint−z)
结合以上12步骤得到如下量化函数的普遍定义 x ^ q ( x ; s , z , b ) s ( c l a m p ( ⌊ x s ⌉ z ; 0 , 2 b − 1 ) − z ) \mathbf{\hat x}q(\mathbf x; s, z, b)s(\mathrm{clamp}(\lfloor\frac{\mathbf{x}}{s}\rceilz; 0, 2^b-1)-z) x^q(x;s,z,b)s(clamp(⌊sx⌉z;0,2b−1)−z)
可以发现量化函数包含了1中的“浮点转整数”以及“反量化近似浮点”两个过程这个过程通常被称为 伪量化fake quantization操作。 对伪量化的理解把输入的浮点数据量化到整数再反量化回 浮点数以此来模拟量化误差同时在反向传播的时候采用Straight-Through-Estimator (STE)把导数回传到前面的层。
由上面的公式有两个误差概念 1 截断误差clipping error浮点数 x x x超过量化范围时会被截断产生误差 2舍入误差rounding error在做 ⌊ ⋅ ⌉ \lfloor \cdot\rceil ⌊⋅⌉时会产生四舍五入的误差误差范围在 [ − 1 2 , 1 2 ] [-\frac{1}{2}, \frac{1}{2}] [−21,21] 为了权衡两种误差就需要设计合适的s和z而它们依赖于量化范围和精度。
根据反量化过程我们设 整数格 上的最大和最小值分别是 Q P q m a x / s , Q N q m i n / 2 Q_Pq_{max}/s, Q_Nq_{min}/2 QPqmax/s,QNqmin/2量化值浮点 范围为 ( q m i n , q m a x ) (q_{min}, q_{max}) (qmin,qmax)其中 q m i n s Q P s ( 0 − z ) − s z , q m a x s Q N s ( 2 b − 1 − z ) q_{min}sQ_Ps(0-z)-sz, q_{max}sQ_Ns(2^b-1-z) qminsQPs(0−z)−sz,qmaxsQNs(2b−1−z)。 x \mathbf x x超过这个范围会被截断产生截断误差如果希望减小截断误差可以增大s的值但是增大s会增大舍入误差因为舍入误差的范围是 [ − 1 2 s , 1 2 s ] [-\frac{1}{2}s, \frac{1}{2}s] [−21s,21s]。
怎么计算放缩因子 s s s s q m a x − q m i n 2 b − 1 . s\frac{q_{max}-q_{min}}{2^b-1}. s2b−1qmax−qmin.
2.1 对称均匀量化
对称均匀量化是上面非对称量化的简化版限制了放缩因子 z 0 z0 z0但是偏移量的缺失限制了整数和浮点域之间的映射。
反量化de-quantization近似真实的输入 x \mathbf x x x ≈ x ^ s x i n t x\approx \hat x s\mathbf x_{int} x≈x^sxint
将真实输入的浮点数 x \mathbb x x转化为无符号整数 x i n t c l a m p ( ⌊ x s ⌉ ; 0 , 2 b − 1 ) \mathbf{x}_{int} \mathrm{clamp}(\lfloor\frac{\mathbf{x}}{s}\rceil; 0, 2^b-1) xintclamp(⌊sx⌉;0,2b−1)
将真实输入的浮点数 x \mathbb x x转化为有符号整数 x i n t c l a m p ( ⌊ x s ⌉ ; − 2 b , 2 b − 1 ) \mathbf{x}_{int} \mathrm{clamp}(\lfloor\frac{\mathbf{x}}{s}\rceil; -2^b, 2^b-1) xintclamp(⌊sx⌉;−2b,2b−1) 坐标轴上方蓝色表示整数量化格下方黑色表示浮点格。可以很清楚地看到放缩因子 s s s就是量化的步长step size s x i n t s\mathbf x_{int} sxint是反量化近似真实浮点数。
2.2 Power-of-two量化2的幂
Power-of-two量化是对称量化的特例放缩因子被限制到2的幂 s 2 − k s2^{-k} s2−k这对硬件是高效的因为放缩 s s s相当于简单的比特移位操作bit-shifting。
2.3 量化的粒度
1Per-tensor张量粒度神经网络中最常用硬件实现简单累加结果都用同样的放缩因子 s w s x s_ws_x swsx 2Per-channel通道粒度更细粒度以提升模型性能比如对于权重的不同输出通道采用不同的量化 3Per-group分组粒度
3 量化模拟过程/伪量化
量化模拟为了测试神经网络在量化设备上的运行效果我们经常在用于训练神经网络的相同通用硬件上模拟量化行为。 我们的目的使用浮点硬件来近似的定点运算。 优势与在实际的量化硬件上实验或在使用量化的卷积核上实验相比这种模拟明显更容易实现 a在设备推理过程中对硬件的所有输入偏置、权重和输入激活都是定点格式 b然而当我们使用通用的深度学习框架和通用硬件来模拟量化时这些量都是以浮点格式表示的。这就是为什么我们在计算图中引入量化器块来诱导量化效应的原因
值得注意的是 1每个量化器都由一组量化参数放缩因子、零点、位宽来定义 2量化器的输入和输出都是浮点格式但输出都在量化网格上 3每个量化器都由该公式计算 x ^ q ( x ; s , z , b ) s ( c l a m p ( ⌊ x s ⌉ z ; 0 , 2 b − 1 ) − z ) \mathbf{\hat x}q(\mathbf x; s, z, b)s(\mathrm{clamp}(\lfloor\frac{\mathbf{x}}{s}\rceilz; 0, 2^b-1)-z) x^q(x;s,z,b)s(clamp(⌊sx⌉z;0,2b−1)−z)也就是包含了反量化过程 4模拟量化实际上还是在浮点数上计算模拟的其实是截断与舍入误差
4 基于STE的反向传播优化过程
严峻的优化问题量化公式中中的round函数的梯度要么为零要么到处都不定义这使得基于梯度的训练不可能进行。一种解决方案就是采用straight-through estimator (STE方法将round函数的梯度近似为1: ∂ ⌊ y ⌉ ∂ y 1 \frac{\partial \lfloor y\rceil}{\partial y}1 ∂y∂⌊y⌉1
于是量化的梯度就可求了现对输入 x \mathbf x x进行求导 ∂ x ^ ∂ x ∂ q ( x ) ∂ x ∂ c l a m p ( ⌊ x s ⌉ ; Q N , Q P ) s ∂ x { s ∂ Q N ∂ x 0 , x q m i n , s ∂ ⌊ x / s ⌉ ∂ x s ∂ ⌊ x / s ⌉ ∂ ( x / s ) ∂ ( x / s ) ∂ x s ⋅ 1 ⋅ 1 s 1 , q m i n ≤ x ≤ q m a x , s ∂ Q P ∂ x 0 , x q m a x . { 0 , x q m i n , 1 , q m i n ≤ x ≤ q m a x , 0 , x q m a x . \frac{\partial\mathbf{\hat x}}{\partial\mathbf x}\frac{\partial q(\mathbf x)}{\partial\mathbf x}\\~~~~~~\frac{\partial \mathrm{clamp}(\lfloor\frac{\mathbf x}{s}\rceil; Q_N, Q_P)s}{\partial\mathbf x}\\~~~~~~\begin{cases} s\frac{\partial Q_N}{\partial \mathbf x}0, \mathbf x q_{min}, \\ s\frac{\partial \lfloor \mathbf x/s\rceil}{\partial \mathbf x}s\frac{\partial \lfloor \mathbf x/s\rceil}{\partial (\mathbf x/s)}\frac{\partial (\mathbf x/s)}{\partial \mathbf x}s\cdot 1\cdot \frac{1}{s}1, q_{min} \leq x\leq q_{max},\\ s\frac{\partial Q_P}{\partial \mathbf x}0, xq_{max}. \end{cases}\\~~~~~~\begin{cases} 0, \mathbf x q_{min}, \\ 1, q_{min} \leq \mathbf x\leq q_{max},\\ 0, \mathbf xq_{max}. \end{cases} ∂x∂x^∂x∂q(x) ∂x∂clamp(⌊sx⌉;QN,QP)s ⎩ ⎨ ⎧s∂x∂QN0,xqmin,s∂x∂⌊x/s⌉s∂(x/s)∂⌊x/s⌉∂x∂(x/s)s⋅1⋅s11,qmin≤x≤qmax,s∂x∂QP0,xqmax. ⎩ ⎨ ⎧0,xqmin,1,qmin≤x≤qmax,0,xqmax. 也就是说根据STE方法当输入 x \mathbf x x在量化范围内时其量化值对真实浮点值的梯度为1反之为0。 对 s s s求导的数学推导过程如下文中LSQ工作所示。 下图展示了基于STE的反向传播过程计算时有效跳过了量化器。
5 经典量化工作
Learned Step Size Quantization (ICLR 2020)
顾名思义LSQ这篇文章就是在上述介绍的伪量化中引入可学习/训练的放缩因子 s s s。 设clamp的在 整数格 上的最大和最小值分别是 Q P q m a x / s , Q N q m i n / 2 Q_Pq_{max}/s, Q_Nq_{min}/2 QPqmax/s,QNqmin/2。 x ^ s ( c l a m p ( ⌊ x s ⌉ ; Q N , Q P ) ) { s Q N , x s Q N , s ⌊ x s ⌉ , Q N ≤ x s ≤ Q P , s Q P , x s Q P . \hat xs(\mathrm{clamp}(\lfloor\frac{\mathbf{x}}{s}\rceil; Q_N, Q_P))\\~~~~\begin{cases} sQ_N, \frac{\mathbf{x}}{s} Q_N, \\ s\lfloor\frac{\mathbf{x}}{s}\rceil, Q_N \leq \frac{\mathbf{x}}{s}\leq Q_P,\\ sQ_P, \frac{\mathbf{x}}{s}Q_P. \end{cases} x^s(clamp(⌊sx⌉;QN,QP)) ⎩ ⎨ ⎧sQN,sxQN,s⌊sx⌉,QN≤sx≤QP,sQP,sxQP. x ^ \mathbf{\hat x} x^对 s s s求导有 ∂ x ^ ∂ s { Q N , x s Q N , ⌊ x s ⌉ s ∂ ⌊ x s ⌉ ∂ s , Q N ≤ x s ≤ Q P , Q P , x s Q P . \frac{\partial\mathbf{\hat x}}{\partial s}\begin{cases} Q_N, \frac{\mathbf{x}}{s} Q_N, \\ \lfloor\frac{\mathbf{x}}{s}\rceil s\frac{\partial\lfloor\frac{\mathbf{x}}{s}\rceil}{\partial s}, Q_N \leq \frac{\mathbf{x}}{s}\leq Q_P,\\ Q_P, \frac{\mathbf{x}}{s}Q_P. \end{cases} ∂s∂x^⎩ ⎨ ⎧QN,sxQN,⌊sx⌉s∂s∂⌊sx⌉,QN≤sx≤QP,QP,sxQP. 其中 Q N , Q P , ⌊ x s ⌉ Q_N, Q_P, \lfloor\frac{\mathbf{x}}{s}\rceil QN,QP,⌊sx⌉都可以直接得到但是 s ∂ ⌊ x s ⌉ ∂ s s\frac{\partial\lfloor\frac{\mathbf{x}}{s}\rceil}{\partial s} s∂s∂⌊sx⌉就不那么好算了。
根据STE将round函数梯度近似为一个直通操作 s ∂ ⌊ x s ⌉ ∂ s s ∂ x s ∂ s − s x s 2 − x s s\frac{\partial\lfloor\frac{\mathbf{x}}{s}\rceil}{\partial s}s\frac{\partial\frac{\mathbf{x}}{s}}{\partial s}-s\frac{\mathbf x}{s^2}-\frac{\mathbf x}{s} s∂s∂⌊sx⌉s∂s∂sx−ss2x−sx
于是得到LSQ原文中的导数值 ∂ x ^ ∂ s { Q N , x s Q N , ⌊ x s ⌉ − x s , Q N ≤ x s ≤ Q P , Q P , x s Q P . \frac{\partial\mathbf{\hat x}}{\partial s}\begin{cases} Q_N, \frac{\mathbf{x}}{s} Q_N, \\ \lfloor\frac{\mathbf{x}}{s}\rceil - \frac{\mathbf x}{s}, Q_N \leq \frac{\mathbf{x}}{s}\leq Q_P,\\ Q_P, \frac{\mathbf{x}}{s}Q_P. \end{cases} ∂s∂x^⎩ ⎨ ⎧QN,sxQN,⌊sx⌉−sx,QN≤sx≤QP,QP,sxQP.
在LSQ中每层的权重和激活值都有不同的 s s s被初始化为 2 ⟨ ∣ x ∣ ⟩ Q P \frac{2\langle| \mathbf x|\rangle}{\sqrt{Q_P}} QP 2⟨∣x∣⟩。
计算 s s s的梯度时还需要兼顾模型权重的梯度二者差异不能过大LSQ定义了如下比例 R ∇ s L s / ∣ ∣ ∇ w L ∣ ∣ ∣ ∣ w ∣ ∣ → 1 R\frac{\nabla_sL}{s}/\frac{||\nabla_wL||}{||w||}\rightarrow1 Rs∇sL/∣∣w∣∣∣∣∇wL∣∣→1。 为了保持训练的稳定LSQ在 s s s的梯度上还乘了一个梯度缩放系数 g g g对于权重 g 1 / N W Q P g1/\sqrt{N_WQ_P} g1/NWQP 对于激活 g 1 / N F Q P g1/\sqrt{N_FQ_P} g1/NFQP 。其中 N W N_W NW是一层中的权重的大小 N F N_F NF是一层中的特征的大小。
代码实现 参考LSQuantization复现
import torch
import torch.nn.functional as F
import math
from torch.autograd import Variableclass FunLSQ(torch.autograd.Function):staticmethoddef forward(ctx, weight, alpha, g, Qn, Qp):assert alpha 0, alpha {}.format(alpha)ctx.save_for_backward(weight, alpha)ctx.other g, Qn, Qpq_w (weight / alpha).round().clamp(Qn, Qp) # roundclamp将FP转化为intw_q q_w * alpha # 乘scale重量化回FPreturn w_qstaticmethoddef backward(ctx, grad_weight):weight, alpha ctx.saved_tensorsg, Qn, Qp ctx.otherq_w weight / alphaindicate_small (q_w Qn).float()indicate_big (q_w Qp).float()indicate_middle torch.ones(indicate_small.shape).to(indicate_small.device) - indicate_small - indicate_biggrad_alpha ((indicate_small * Qn indicate_big * Qp indicate_middle * (-q_w q_w.round())) * grad_weight * g).sum().unsqueeze(dim0) # 计算s梯度时的判断语句grad_weight indicate_middle * grad_weightreturn grad_weight, grad_alpha, None, None, Nonenbits 4
Qn -2 ** (nbits - 1)
Qp 2 ** (nbits - 1) - 1
g 1.0 / 22 LSQ: Improving low-bit quantization through learnable offsets and better initialization (CVPR 2020)
LSQ和LSQ非常相似就放在一起讲了。LSQ在LSQ的基础上引入了可学习的offset也就是零点 z z z其定义如下 x i n t c l a m p ( ⌊ x − β s ⌉ ; Q N , Q P ) \mathbf x_{int}\mathrm{clamp}(\lfloor\frac{\mathbf{x-\beta}}{s}\rceil; Q_N, Q_P) xintclamp(⌊sx−β⌉;QN,QP) x ^ s x i n t β \mathbf{\hat x}s\mathbf x_{int}\beta x^sxintβ 然后按照LSQ的方式对 s , β s,\beta s,β求偏导数进行优化。
参考资料
量化训练之可微量化参数—LSQA White Paper on Neural Network Quantization