论文(NeurIPS 2021 Accepted):https://openreview.net/forum?id=TUplOmF8DsM
源码(Pytorch):https://github.com/ModelTC/MQBench
官方网站:http://mqbench.tech/
MQBench 概要
- 1 Motivation
- 2 Introduction Towards Reproducible Quantization of QAT
- 3 Introduction Towards Deployable Quantization of QAT
- 4 MQBench Implementation of QAT
- 5 MQBench Evaluation
- 附录待解读ing......
- 个人思考
1 Motivation
- 近年来虽然深度学习模型量化做的越来越好,但其缺乏一个系统的研究与探讨——这些研究工作是否真的可以应用于实践?量化后性能的提升是由量化算法本身带来的,还是由训练的 Tricks 带来的?且目前仍缺乏一个 Benchmark 来统一规范量化的训练流程,并彻底和公正地比较量化算法。
- 作者发现大多数量化相关的学术研究论文没有在实际硬件设备上测试过,也就是说实际在硬件部署时的效果是不清楚的。因为实际部署不仅会进行 Fold BN 操作,还会量化除 Weight、Activation 以外的 Parameters (即整个计算图均被量化)。
- 其次,大部分量化算法采用的是 Per-tensor 方案,而转为使用 Per-channel 方案后性能会发生怎样变化?
藉此作者提出 Reproducibility 和 Deployability 两个概念,并根据这两个概念来展开有关实验。以上 Motivation在 Fig1 & Table 1 中均有体现。
2 Introduction Towards Reproducible Quantization of QAT
为了体现 Reproducibility ,作者将在 ImageNet 图像分类任务上进行 QAT 、 PTQ 实验(PTQ 实验展示在 Appendix. C 中)。没有对检测、分割和自然语言处理任务做实验,因为对应的 Baseline 较少。个人认为本小节是对 Reproducible Quantization 的一种介绍,作者对专用硬件及其推理库、量化算法、模型结构、位宽四个方面的实验引入了相关概念和 Setting 。
2.0 What to Experiment
Hardware-friendly Quantizer
在本文中,主要探讨均匀量化,因为其在硬件部署上比较简明,而非均匀量化在硬件上的设计过于复杂,不展开赘述。作者将 w \bm{w} w 和 x \bm{x} x 分别定义为一个神经网络中的权重矩阵和激活矩阵。一次完整的均匀量化过程包括 Quantization Operation 和 De-quantization Operation ,下面给出公式:
其中
s
∈
R
+
s \in \mathbb{R_{+}}
s∈R+ 和
z
∈
Z
z \in \mathbb{Z}
z∈Z 分别为量化尺度(Scale)和量化零点(Zero-Point),
⌊
⋅
⌉
\lfloor \cdot \rceil
⌊⋅⌉ 为四舍五入操作。公式 (1) 首先将权重或激活量化为
[
N
m
i
n
,
N
m
a
x
]
[N_{min},N_{max}]
[Nmin,Nmax] 范围内的整数,然后再将整数反量化回原始范围。给定
t
t
t bits,那么整数范围就为
[
−
2
t
−
1
,
2
t
−
1
−
1
]
[-2^{t-1},2^{t-1}-1]
[−2t−1,2t−1−1] 。进一步划分量化器的种类,有:
- 对称量化或非对称量化。对于对称量化,量化零点固定为0,而非对称量化具有可调整的量化零点以适应不同的范围。
- Per-tensor 量化或 Per-channel 量化。Per-tensor 量化在一个层中只使用一个 s s s 和一个 z z z 来量化整个张量;而 Per-channel 量化则独立地量化每一个权重核(也就是 w i , : \bm{w}_{i,:} wi,: ,每一个通道)。
- FP32 (32-bit 浮点数) scale 或 POT (二的幂次) scale。FP32的量化尺度几乎是连续的;POT的量化尺度更具挑战性,但可以提供进一步的加速。
本文选用了5钟专用硬件及其推理库来做实验:针对 GPU 的NVIDIA TensorRT、针对专用集成电路(ASIC)的 HUAWEI ACL 、针对移动数字信号处理器(DSP)的 Qualcomm SNPE、针对 ARM *处理器(CPU)的 TVM、针对 X86 服务器端 CPU 的 FBGEMM 。硬件环境的详细设置展示在 Appendix. E 中。这些推理库的属性展示在在 Table 2 中上半部分。
Quantization Algorithm
作者比较了6种 QAT 算法,而其他的算法因为怎么调整量化器配置和其他要求也无法部署,故不再展开。所对比的算法都使用 Per-tensor、Symmetry 设置,称为学术环境,展示在 Table 2 的下半部分。有关这些算法的详细说明以及它们可以扩展到可部署量化的原因参见 Appendix. F。
Network Architecture
涉及的模型为 ResNet-18、ResNet-50、MobileNetV2、EfficientNet-Lite、RegNetX-600MF。
Bit-width
在本文中,作者主要对 8-bit PTQ(见 Appendix. C)和 4-bit QAT 进行了实验。在测试量化模型准确性时作者采用伪量化来模拟算法。作者没有进行 3-bit 量化,因为它不能在一般硬件上部署;而对于 2-bit 量化,作者发现大多数算法在硬件上不收敛。
2.1 Training Pipelines and Hyper-parameters
作者对所有 QAT 算法都进行 Fine-tuning,每个模型都由相同的预训练模型初始化。这消除了初始化时的不一致性。作者对训练数据采用标准数据预处理,包括 RandomResizeCrop 成224分辨率、RandomHorizontalFlip、参数 brightness= 0.2 contrast= 0.2 saturation=0.2 hue=0.1 的 ColorJitter 。测试数据被居中裁剪为224分辨率。作者在训练中还使用0.1的 Label Smoothing 来引入正则化项。所有的模型都只训练100个 Epochs,第一个 Epoch 均进行 Linear Warmup。学习率采用余弦退火策略,Optimizer采用 Momentum 为0.9、更新方式为 Nesterov 的 SGD。其他训练超参数展示在 Table 3 中。至于为什么使用这些超参数,作者在 Appendix. A 中进行了详细讨论。
3 Introduction Towards Deployable Quantization of QAT
3.1 Fake and Real Quantization
设权重矩阵为 w ^ \bm{\hat{w}} w^ ,激活矩阵为 x ^ \bm{\hat{x}} x^ ,卷积输出为 y \bm{y} y 那么有如下乘积计算:
在GPU上进行 FP32 的模拟实验时,使用公式 (2) 左部分的 Fake Quantize;在实际硬件部署加速时,使用公式 (2) 右部分的 Real Quantize,以保证计算过程是以整数形式进行的。在 Fig 2 中作者展示了二者在计算图上的区别。
在实际部署时,模型推理中的累积计算使用 INT32。为了进一步优化加速卷积运算,可以将公式 (2) 中的右侧后两项提前计算并储存下来,因为
w
\bm{w}
w 、
z
w
z_{w}
zw 、
z
x
z_{x}
zx 在部署时均是已知、值不变的;对于 Bias 偏置项
b
^
\hat{b}
b^ ,其将被量化成INT32精度的
b
ˉ
=
b
^
s
b
\bar{b}=\frac{\hat{b}}{s_b}
bˉ=sbb^ ,其中
s
b
=
s
w
s
x
{s_b=s_w s_x}
sb=swsx。也就是说,Bias可以 Fuse 进公式 (2) 里。在 Fig 2 (b) 中,INT32 形式的累计运算还会被进一步量化成 INT8 形式,该过程称为再量化(Requantization),有公式为:
3.2 Folding Batch Normalization
Batch Normalization(BN) 层用于减少内部协变量移位,同时平滑损失函数,促进快速收敛。本质上其引入了两步线性变换。在实际部署中,BN 层可以 Fuse(或称为 Fold )到卷积核中,进一步减少运算量。有推理时 Fold BN 公式:
其中 μ \mu μ 是 Running Mean, σ 2 \sigma^{2} σ2 是 Running Variance, γ \gamma γ 是 缩放因子, β {\beta} β 是偏移因子。 ϵ \epsilon ϵ 是避免分母为0的微小值。
但在学术界很少考虑 BN Folding 问题,这在部署方面来说是棘手的。设当前 Batch Mean 为 μ ~ \tilde{\mu} μ~ ,当前 Batch Variance 为 σ ~ 2 \tilde{\sigma}^{2} σ~2 。作者给出了 BN Folding 的5种策略(具体构建在 Fig 3 中):
- Strategy 0:如 Fig 3 (a) 所示。无论训练还是推理,完全移除 BN 层,直接执行公式 (4) ,得到 w f o l d \bm{w}_{fold} wfold 。再由 w f o l d \bm{w}_{fold} wfold 进入量化器后得到 w ^ f o l d \hat{\bm{w}}_{fold} w^fold 。原先 BN 层的所有参数都不会被更新。这不适合 QAT 的 Fine-tuning,且无法以高学习率进行。因为会出现梯度爆炸情况,需要广泛调参。
- Strategy 1:如 Fig 3 (b) 所示。无论训练还是推理,也是完全移除 BN 层,但是允许缩放因子 γ \gamma γ 和偏移因子 β \beta β 参与梯度更新,不允许 Running Mean μ \mu μ 和 Running Variance σ 2 \sigma^{2} σ2 更新。这种策略仍然可以平滑损失函数,并尽可能维护模型准确度,避免数据上的同步,显著减少训练时间。
- Strategy 2:如 Fig 3 (c) 所示。也是完全移除 BN 层,不仅允许利用运行时统计情况来更新 μ \mu μ 和 σ 2 \sigma^{2} σ2 ,还允许允许缩放因子 γ \gamma γ 和偏移因子 β \beta β 参与梯度更新。但是卷积将在训练期间计算两次,产生额外开销。具体来说,第一次卷积运算以FP32形式进行,基于 Output Feature Maps 统计出 Batch Mean μ ~ \tilde{\mu} μ~ 和 Batch Variance σ ~ 2 \tilde{\sigma}^{2} σ~2 来更新 μ \mu μ 和 σ 2 \sigma^{2} σ2 。第二次卷积运算则是正常的前向计算过程。需要注意的是,在训练时, Fold Weight 操作使用的是 σ ~ 2 \tilde{\sigma}^{2} σ~2 来参与而不是 σ 2 \sigma^{2} σ2 ,Fold Bias 操作使用的是 μ ~ \tilde{\mu} μ~ 而不是 μ \mu μ 。在推理时,Weight 和 Bias 才会与 μ \mu μ 和 σ 2 \sigma^{2} σ2 进行 Merge 。
- Strategy 3:如 Fig 3 (d) 所示。也是完全移除 BN 层,不仅允许利用运行时统计情况来更新 μ \mu μ 和 σ 2 \sigma^{2} σ2 ,还允许允许缩放因子 γ \gamma γ 和偏移因子 β \beta β 参与梯度更新。类似于 Strategy 2 ,也有两次卷积计算。同样第一次卷积是统计出 μ ~ \tilde{\mu} μ~ 和 σ ~ 2 \tilde{\sigma}^{2} σ~2 来更新 μ \mu μ 和 σ 2 \sigma^{2} σ2 ,第二次是正常的前向计算过程。有区别的是,在训练时, Fold Weight 操作使用的是 σ 2 \sigma^{2} σ2 ,以避免统计数据出现巨大波动,而Fold Bias 操作使用的仍是 μ ~ \tilde{\mu} μ~ 。接着会在第二次卷积计算后通过乘积计算来消去 σ \sigma σ,取而代之的是 σ ~ \tilde{\sigma} σ~ 。
- Strategy 4:如 Fig 3 (e) 所示,来自于 Pytorch 官方用例。相比于 Strategy 3,该策略不用进行两次卷积计算。但在训练时,该策略保留了 BN 层, μ \mu μ 、 σ 2 \sigma^{2} σ2 、 μ ~ \tilde{\mu} μ~ 、 σ ~ 2 \tilde{\sigma}^{2} σ~2 、 γ \gamma γ、 β {\beta} β 均来自于该 BN层。Weight 先和 γ \gamma γ 、 σ \sigma σ Merge 到一起,然后过伪量化、卷积计算后再把 μ \mu μ 、 σ \sigma σ 给抵消掉。BN 层此时使用 μ ~ \tilde{\mu} μ~ 和 σ ~ 2 \tilde{\sigma}^{2} σ~2 参与 Feature Maps 的标准化,好处就是 μ ~ \tilde{\mu} μ~ 和 σ ~ 2 \tilde{\sigma}^{2} σ~2 是由量化过的 Weight 结果统计而来的。在推理时, BN 层使用的是 μ \mu μ 、 σ 2 \sigma^{2} σ2,那么就会和 σ γ \frac{\sigma}{\gamma} γσ 中和掉,也就是说最后也可以转换为 Fig 3 (a) 所示的形式。
有一个细节就是,图中作者把 Weight 的 Merge 操作(即 w \bm{w} w 转变为 w f o l d \bm{w}_{fold} wfold )拆写成 w γ σ \bm{w} \frac{\gamma}{\sigma} wσγ 或 w γ σ ~ \bm{w} \frac{\gamma}{\tilde{\sigma}} wσ~γ,个人认为是想说明 γ \gamma γ 、 σ \sigma σ 或 σ ~ \tilde{\sigma} σ~ 是可训练或可变化的。
3.3 Block Graph
大多数学术界的工作只量化了输入、权重核,没有讨论其他的运算操作的量化细节,如 ResNet 的 Elementwise-add 和 InceptionV3 的 Concatenation 。此外,不同的硬件将考虑不同级别的图形优化并构建不同的量化神经网络的图形。作者将特殊运算的计算图构建方法总结在 Fig 4 中(只展示 ResNet-18/-34 的 Basic Block 示例,Bottleneck Block 也类似如此)。关于 MobileNetV2 的 Inverted Residual Bottleneck Block 的细节展示在 Appendix. G 中。
Fig 4 的左图展示了用于量化 Basic Block 的传统学术实现。可以看到只有卷积层的输入进行了伪量化,该计算图的输入和输出以及 Element-wise Add 都以全精度运行。也就是说,从块整体来看,网络吞吐量没有降低,并且将显著影响延迟。值得注意的是,Downsample 块的输入也单独量化了,这增加了不必要的成本。
Fig 4 的中间图展示了 TensorRT 对 Basic Block 的实现。从计算图整体来看,输入和输出都低比特位的,这降低了吞吐量。与左图不同,该图的低比特输入可确保两个分支使用相同的低比特激活,这剔除了不必要的成本。需要注意的是,Element-wise 操作和 Downsample 分支的输出被 Fuse 到 左分支的卷积层中的 Bias 项里了,同 Bias 一起进行 32-bits 运算,因此 Downsample 层的输出也进行了伪量化。
Fig 4 的右图展示了 FBGEMM 和 TVM 的实现。唯一的区别是,他们需要对元素加法的所有输入进行量化(也不进行 Fuse 了?)。在低比特对称量化中会严重影响模型准确度。
4 MQBench Implementation of QAT
作者使用 Pytorch 1.8 来实现 MQBench,并使用 torch.fx 库(也成为 FX 库)。Trace 一个全精度模型并将其转换为量化模型只需要一个API调用,代码演示如下所示:
有关更多信息参见作者官方 Repository。
5 MQBench Evaluation
本节,作者将对量化算法、网络架构以及硬件进行全面的评估和分析。作者讨论了如下评估指标:
- Test Accuracy:也就是 ImageNet Validation Dataset 的 Top-1 准确度。其能直接反映算法对于任务的性能。
- Hardware Gap:测试集在理论准确度和硬件实际准确度上的差异度。其能反应该算法的可部署性。
- Hardware Robustness:在硬件环境中运行5次测试集后取平均的准确度。
- Architecture Robustness:在5种模型架构上运行测试集后取平均的准确度。
在 Appendix. B 种作者还会展示更多的细节。
5.1 Evaluation with Academic Setting
如 Table 4 所示,该实验重现了量化算法在学术环境下 4-bits 量化的表现(例如 Per-tensor,对称量化且不进行 BN Folding )。大多数研究论文采用这种设置。括号内展示的是原论文的性能,括号旁是作者实际在统一超参数下复现的结果。作者得出了如下令人惊讶的结果:
- 算法之间的差异并不像原论文中所报告的那样明显。
- 没有哪种算法在各种体系结构上都能获得最好或最差的性能。
- Rule-based 算法可以实现与 Learning-based 算法相当的性能。
5.2 Evaluation with BN Folding
接下来作者以 LSQ、PACT 为基础,在 ResNet-18 和 MobileNetV2 上讨论了不同 BN Folding 策略对 QAT的影响。需要注意的是这里使用的仍是学术设置(例如 Per-tensor,对称量化)。实验结果展示在 Table 5 中。作者总结出了以下结论:
- BN Folding 对量化算法敏感,策略 4 的总体效果最好。
- 策略 4 相比于策略 2、3 没有起到加速效果,即使它只计算一次卷积计算。因为其在梯度计算上更加耗费时间。
- 对于像 LSQ 这样的 BN Folding 友好算法,更新 Batch 的统计信息可能不是必要的。
- 在并行运算时 BN 数据的同步可以提高学习准确度。
- Fold BN 后 训练的初始阶段会产生严重的不稳定性,而学习率的 Warmup 技巧可以有效缓解。(也就是说,进行 1 Epoch 的 Warmup 是有利的)。
5.3 Evaluation with Graph Implementation
本部分作者讨论了 Fig 4 中不同计算图对 PACT、LSQ 的影响。实验同样是在学术设置下进行,如 Table 6 所示。作者发现:计算图的方式反而对模型架构敏感,对量化算法不敏感。
5.4 Evaluation with Reproducibility and Deployability
本节的量化实验均在工业界部署环境下以 4-bit进行。作者的目的不是为了回答“哪种方法在这个基准上最有效?”,而是想展示实际部署时的基准情况。作者希望在新的见解下可以对量化算法的未来研究起指导作用,而主要结果见 Table 7,接下来在该表的基础上展开讨论。
Test Accuracy
从表中可以看出,没有任何算法在所有设置上都能获得绝对最好的性能。而 Fig 5 展示了不同硬件和网络结构组合下,Test 准确度在5种量化算法上的标准差。低方差意味着量化算法之间的差异较小。由 Fig 5 可见,深度可分离卷积网络(MobileNetV2 和 EfficienctNet-Lite )和 Per-tensor 量化(TVM 和 SNPE)由非常大的方差。作者期待未来研究能更关注这个现象可能存在的问题。
Hardware Gaps
作者也进一步探讨了从学术设置过渡到硬件设置时的性能下降情况。下降比率以彩色数值展示在表中。显而易见的是93%的实验都引起了准确度的下降,没有一个算法能在每种实验设置中实现最小的 Hardware Gap。
Hardware & Architecture Robustness
作者在 Fig 6 中验证了架构和硬件的鲁棒性。左图展示了不同量化算法和网络结构组合下,在5种硬件部署框架上的平均 Test 准确度,可以发现不同的网络体系结构对量化算法具有不同的敏感性。;右图展示了不同量化算法和硬件部署框架组合下,在5种网络结构上的平均 Test 准确度。也可以发现不同的硬件部署框架对量化算法具有不同的敏感性。
Hardware & Architecture Robustness
鉴于以上实验可得,虽然 QAT 中没有一种量化算法适用于所有情况,但算法选择可以遵循一些基本规则。基于 Fig 6,作者发现通常 LSQ 在 Per-tensor 量化(SNPE和TVM)中表现最好,而 PACT 在 Per-channel 量化(TensorRT、ACL、FBGEMM)中表现最好。因此,作者建议对 Per-channel 量化使用PACT,对 Per-tensor 量化使用LSQ。如果你所需要的网络模型或硬件部署架构不在以上范围内,那么作者还是推荐你使用 LSQ。当然作者也提到,并非所有情况都需要仔细选择算法。在 Fig 5 中,在 Per-channel 量化和非深度卷积网络的情况下,算法的方差相当低。因此,在这些设置中,算法的选择很简单。
附录待解读ing…
个人思考
好文。首先直击一个现象就是新的量化算法的有效性是否因为训练 Tricks导致的,最后做的实验也很让人信服。算是立了一个风向标,让人们关注量化算法本身而不是关注训练 Tricks,个人认为这才是对学术社区有意义的。当然 MQBench 也有局限性,量化在目标检测和 NLP 应用等部署中面临更多挑战,且还有更多的量化算法没有被考虑。作者也提到会在今后的工作中加以研究。