量化无处不在,从数字通信到信号处理,再到你日常使用的边缘设备。在现代数字世界中,量化至关重要。量化是将数值信息以较低的精度进行存储的过程,旨在节省空间或计算资源。你们中可能很多人是在人工智能的背景下听到这个术语的,特别是关于量化大语言模型(LLM)。今天,我们将深入探讨通过量化对 LLM 进行压缩。
量化是缩小模型体积且不失精度的最简单、最有效的方法之一。如今,它几乎在生产环境的人工智能中无处不在,从运行在手机上的模型到庞大的推理集群都在使用。正如我们所知,一个模型只是一大堆权重、激活值或参数存储在一起。你可以将这些视为在训练过程中经过微调的小旋钮,用以代表知识。
但知识是复杂的,因此模型拥有海量的这些参数。例如,Gymaphor 有一个包含超过 300 亿参数的密集模型;Llama 3 拥有 700 亿参数的模型,而前沿模型的参数估计达到万亿级别。每个参数都必须存储在某个地方,而你为每个参数存储的细节多少,决定了整个模型所需的存储空间、内存和计算量。
让我们对拥有 700 亿参数的模型进行数学计算,看看为什么量化如此重要。大多数模型使用 FP16(半精度浮点数)或 BF16 格式存储信息。这意味着它们为每个参数分配了 16 位,即两个字节。将其乘以 700 亿个参数,存储这些模型大约需要 140 GB。
这比许多单台数据中心 GPU 拥有的内存还要多。因此,我们需要缩小每个参数所占的空间。问题在于,你不能简单地将数字砍半就称之为降低精度。这些数字并非存储为构成数值的简单数字字符串,而是被分割成不同的部分,每一部分编码特定的信息。
例如符号、大小或数值的细节。如果你切断了错误的位,最终得到的可能是一个完全不同的数字。我们需要一个实际的过程来一致地将数值转换为较低的精度再转换回来。让我们用一个简单的例子来看看量化在底层是如何工作的。
模型由层组成,每层包含一定数量的权重。量化的过程类似于推理,是逐层进行的。对于每一层,我们会查看存在的数值全范围。假设这一层的值在 0 到 100 之间,我们将整个范围映射到一个占用更少位数的较小数值集合中。
假设这里我们要存储 0 到 10 之间的数字,我们会将原始范围内的任何值缩小比例,并四舍五入到该较小集合中最近的数值。例如,让我们取原始值 53,将其缩小到我们的小尺寸将是 5.3,四舍五入到最近的表示后结果为 5。
做得好的话,这种映射将尽可能保留原始范围的信息并最小化信息损失。这肯定是对真实模型中处理的数值的过度简化,但基本上就是这个理念。在现实生活中,这个较小的数值集合映射到一些标准格式上。
如前所述,FP16 是 16 位或两个字节;FP8(浮点 8)和 INT8(整型 8,原文误写为 int8/IN4等,此处依语境修正为标准术语)是 8 位或一个字节;INT4(整型 4,原文误写为 end four/int 4)是 4 位或半个字节。
回到之前提到的拥有 700 亿参数的模型,在全 FP16 精度下需要 140 GB;在 FP8 或 INT8 精度下,则需要接近 70 GB。而在 INT4 精度下,存储所有这些权重仅需 35 GB。这要容易管理得多。
你经常会在模型名称中看到精度标识。例如,某种命名方式意味着该模型拥有 80 亿参数并量化为 FP8(浮点 8);或者意味着模型权重处于 8 位精度,而激活值仍处于 16 位。但量化既给予也剥夺。
随着我们降低权重的精度,虽然减少了内存占用,但也降低了存储信息的细节水平。这就像照片变得越来越像素化,直到难以辨认原始图像一样。量化过度会导致精度下降。在 INT8 量化中,大多数模型能保持其准确性,并在延迟方面显示出显著改善。
INT4 是一个更大的削减幅度,因此精度损失成为一个真正的风险。然而,通过良好的映射机制,INT4 仍然可以接近原始模型的精度水平。只是需要更谨慎的四舍五入才能达到这一目标。
明确地说,当我提到“真正的风险”时,我指的是百分之零点几到 1% 的数量级。通常,精度保持在原始模型精度的 90% 以上。此外,量化可以在两个不同的阶段介入:首先是训练后量化(PTQ)。
PTQ 针对已经充分训练的模型,并在之后对其进行压缩。这种方法速度快且更为常见。另一方面是量化感知训练(QAT)。QAT 在模型仍在训练时模拟较低的精度,因此模型在学习过程中会针对这种精度损失进行调整。
QAT 需要更多的计算时间,但在更激进的量化级别(如 INT4)下表现更好,而在这些级别上 PTQ 更有可能丢失精度。综上所述,量化将构建模型的数值逐层存储为较低的精度(如 INT8 或 INT4)。
它可以在训练后通过 PTQ 进行,也可以在训练中通过 QAT 进行。无论哪种方式,你都是在用一定的精度换取内存和速度。而你推动这种权衡的程度取决于你的模型需要保留多少内容。请在评论区留下您的问题,或告诉我你在生产中使用的模型精度。