混合量化:一种新颖的量化方法,用于在最小化精度影响的情况下减少模型大小

用于量化感知训练和推理的统一套件

在多GPU上运行大规模模型可能有助于减少延迟,但会显著增加部署成本,尤其是随着模型规模的增大。为了缓解这个问题,我们采用了模型压缩技术,并引入了一种新方法,该方法对Transformer网络进行量化,同时对精度的影响最小。我们的技术通过定制的推理内核在相同或更少的GPU数量上实现了与FP16模型相似或更好的性能。

我们的方案在灵活性方面表现出色,它为用户提供了实验任何量化配置的能力,例如用于量化精度的目标位数,以及模型在训练期间被量化的调度。此外,我们将FP16和量化精度结合为一种混合精度机制,以平滑从高精度到低精度的过渡。最后,我们使用参数的二阶梯度(特征值)来调整训练期间的量化调度。

量化方法

应用量化的主要方法有两种:对训练好的模型进行离线量化和在训练过程中减少数据精度的量化感知训练(QAT)。与前者不同,QAT在训练优化过程中考虑了精度损失的影响,从而训练模型。这将显著提高量化模型的准确性。MoQ是在QAT方法的基础上设计的,不同之处在于我们使用混合精度来训练模型以实现目标量化,并定义了减少精度的调度。

所有现有的量化感知训练(QAT)方法从训练开始到完成都以一定的精度(位数)量化模型。然而,即使使用相对较高的量化精度(8位),模型的准确性也会有所下降,这对于某些下游任务可能是不可接受的。例如,Q8BERT工作尝试对BERT网络进行QAT,虽然在某些任务上取得了良好的准确性,但在其他任务(如SQuAD)上F1分数下降了0.8%。其他技术,如Q-BERT,在量化参数矩阵时使用大分组大小(128)的分组量化以获得更高的准确性,但它们仍然不如基线。

在这里,我们介绍MoQ作为一种灵活的线性量化解决方案,允许用户在模型训练过程中定义一个计划。类似于通过迭代剪枝来引入稀疏性,我们从更高的精度(16位量化或FP16)开始量化,并逐渐减少量化位数或FP16部分的混合精度比例,直到达到目标精度(8位)。为了控制精度的过渡,我们定义了一个称为量化周期的超参数,它指示何时应该发生精度降低。我们观察到,通过使用这样的计划,我们获得了最接近基线的准确性。请注意,为了达到一定的精度,我们需要以某种方式定义起始位数和周期,以便在训练样本数量内,模型最终使用目标位数进行量化。有关更多信息,请参阅量化教程。

为了动态调整量化精度,我们采用特征值作为衡量训练对精度变化敏感性的指标。特征值之前已被用于量化(Q-BERT)以选择网络不同部分的精度位数。为了将其与MoQ结合,我们根据特征值的绝对值将其聚类到几个区域,并相应地调整每个区域的量化周期,特征值的幅度越大,因子越大,精度下降得越慢。

MoQ (8bit)

图1. 使用不同层的特征值对GLUE任务之一(QNLI)进行量化调度。不同颜色表示Bert-Base的0到11层。

图1展示了将特征值与MoQ结合应用于12层Bert Base模型的结果。如图所示,前几层(0-4)对精度降低的敏感性高于最后几层,因为它们的量化周期比其他层大一个数量级。从图中还可以观察到,相邻层以相同的方式降低精度。例如,图1左侧图表中的第9、10和11层,以及右侧图表中的第0和4层以及第1和3层,它们的量化计划相似。这是由于这些层在整个训练过程中具有相似的特征值。

MoQ (mixed-precision) 图2:使用目标量化周期为4位的QNLI混合精度量化。

图2展示了另一种混合精度量化方法,该方法将目标位数设置为4,但量化周期通过每层的特征值不断更新。正如我们所看到的,最终所有层的量化位数都不同。由于训练样本不足以减少量化位数,第一层仍然保持8位量化。另一方面,最后一层继续降低精度。我们最终将整个网络的平均精度降低到6位,同时保持了模型的准确性(准确性下降了0.3%)。

MoQ (mixed-precision) 图3:使用MoQ对Bert SQuAD plus进行混合精度量化。

作为另一个例子,我们使用基于特征值的MoQ来量化Bert-Large以进行SQuAD微调。图3显示了我们在每层微调结束时获得的位数。在这里,我们看到与GLUE任务上的BertBase相比,精度谱略有不同。如图所示,我们可以比中间层更积极地降低前几层的精度。此外,最后几层可以容忍非常低的精度,类似于开始层。这种量化方式最终导致90.56的F1分数,与基线非常相似。

量化推理内核

通过使用其他量化方法,模型量化后,只有在硬件支持基于整数的操作时才能获得性能优势。因此,所有GeMM操作的输入和输出都需要进行量化。然而,由于输入的范围可能因请求而异,在推理时为每个输入找到数据范围是具有挑战性的。另一方面,对所有输入使用静态范围可能会影响推理的准确性。

为了缓解这个问题,我们引入了推理自定义内核,这些内核既不需要硬件支持,也不需要输入量化。这些内核读取量化参数并在运行时对其进行反量化,并使用GPU核心的浮点单元进行GeMM操作。使用这些内核的主要好处是它们减少了加载模型所需的内存占用,从而我们可以在更少的GPU上运行推理,同时通过节省在GPU上运行推理所需的内存带宽来提高性能。

关于量化实现,我们根据数据的范围和舍入策略使用不同的算法来量化值。我们支持对称和非对称量化这两种最常用的方案。我们在QAT中应用了这两种技术,并看到了非常相似的结果,但由于对称方法实现起来更简单,我们基于此实现了我们的推理内核。关于舍入,我们支持随机舍入作为正常舍入之外的另一种选择。我们发现,在将精度降低到4位或更低时,随机舍入更有帮助,因为它在训练期间具有无偏随机行为。

易用性

为了通过Deepspeed启用量化,我们只需要通过JSON配置文件传递调度。为了增加量化的影响,我们在优化器更新参数之前对参数进行量化和反量化。因此,我们在模型方面不需要进行任何更改来量化模型。相反,我们通过降低以FP16格式保存的数据的精度来模拟量化的影响。通过使用这种实现方式,我们可以完全灵活地使用训练特性(如步数、参数的特征值和原始FP16数据格式)来改变精度。正如这篇博客文章所示,我们可以通过在训练过程中自适应地改变量化的调度来提高量化模型的质量。有关如何使用MoQ方案的更多信息,请查看我们的量化教程

提高量化精度。

为了展示我们的量化方案如何保持准确性,我们在多个任务和网络上进行了MoQ实验:Bert-Base上的GLUE任务和Bert-Large上的SQuAD。表1显示了未使用量化(w/o Quant)、在训练期间未使用任何调度的基本量化(Basic Quant)以及我们的MoQ方案的准确性结果。在不使用任何调度的情况下,8位量化的准确性通常低于基线,在这个工作负载中,准确性下降了1.02点(ACC)。相比之下,MoQ使8位量化能够获得与FP16基线相当的准确性,甚至略高一些,展示了我们量化方法的有效性。

任务 STSB MRPC COLA WNLI SST2 RTE QNLI QQP MNLI SQuAD ACC+
无量化感知训练(FP16) 88.71 88.12 56.78 56.34 91.74 65.3 90.96 90.67 84.04 90.56 0
基础QAT 88.9 88.35 52.78 55.3 91.5 64.2 90.92 90.59 84.01 90.39 -0.87
MoQ 88.93 89 59.33 56.34 92.09 67.15 90.63 90.94 84.55 90.71 0.75

更新: