模型量化(Model Quantization
)是一种通过降低神经网络模型中参数和激活值的数值精度(如从 32 位浮点数转换为 8 位整数),以减小模型体积、提升计算效率并降低功耗的技术。它是深度学习模型压缩和优化的核心方法之一,尤其适用于在资源受限的设备(如手机、嵌入式设备)上部署模型。
核心原理
精度降低
:
- 原始模型通常使用 32 位浮点数(
float32
)存储权重和激活值
- 量化后,数值会被映射到更低精度的表示(如
int8
、uint8
甚至4位
整数),大幅减少存储和计算资源需求
映射过程
:
- 通过
缩放因子(scale)
和零点(zero point)
将浮点数值范围线性映射到整数范围
- 例如:将
[-1.0, 1.0]
的浮点数映射到 0~255
的 8 位整数
量化的主要优势
减小模型体积
:
float32
-> int8
量化可减少 75%的存储空间
- 例如,100MB 的模型可压缩到 25MB 以下
加速推理
:低精度运算(如整数计算)在硬件(如 CPU、GPU、NPU)上的速度通常快于浮点运算
降低功耗
:整数运算的能耗远低于浮点运算,适合移动端和物联网设备
硬件兼容性
:许多边缘设备(如手机、摄像头)的芯片专门优化了低精度计算
量化方法分类
训练后量化(Post-Training Quantization, PTQ)
:
- 对已训练好的模型直接进行量化,无需重新训练
- 速度快,但可能损失一定精度
适用场景
:快速部署,对精度要求不极端敏感的任务
量化感知训练(Quantization-Aware Training, QAT)
:
- 在模型训练过程中模拟量化过程,让模型适应低精度表示
- 精度损失较小,但需要重新训练,耗时较长
适用场景
:对精度要求较高的任务(如目标检测、语义分割)
Quantization Types/量化类型
type |
source |
description |
F64 |
Wikipedia |
64-bit standard IEEE 754 double-precision floating-point number. |
I64 |
GH |
64-bit fixed-width integer number. |
F32 |
Wikipedia |
32-bit standard IEEE 754 single-precision floating-point number. |
I32 |
GH |
32-bit fixed-width integer number. |
F16 |
Wikipedia |
16-bit standard IEEE 754 half-precision floating-point number. |
BF16 |
Wikipedia |
16-bit shortened version of the 32-bit IEEE 754 single-precision floating-point number. |
I16 |
GH |
16-bit fixed-width integer number. |
Q8_0 |
GH |
8-bit round-to-nearest quantization (q). Each block has 32 weights. Weight formula: w = q * block_scale. Legacy quantization method (not used widely as of today). |
Q8_1 |
GH |
8-bit round-to-nearest quantization (q). Each block has 32 weights. Weight formula: w = q * block_scale + block_minimum. Legacy quantization method (not used widely as of today) |
Q8_K |
GH |
8-bit quantization (q). Each block has 256 weights. Only used for quantizing intermediate results. All 2-6 bit dot products are implemented for this quantization type. Weight formula: w = q * block_scale. |
I8 |
GH |
8-bit fixed-width integer number. |
Q6_K |
GH |
6-bit quantization (q). Super-blocks with 16 blocks, each block has 16 weights. Weight formula: w = q * block_scale(8-bit), resulting in 6.5625 bits-per-weight. |
Q5_0 |
GH |
5-bit round-to-nearest quantization (q). Each block has 32 weights. Weight formula: w = q * block_scale. Legacy quantization method (not used widely as of today). |
Q5_1 |
GH |
5-bit round-to-nearest quantization (q). Each block has 32 weights. Weight formula: w = q * block_scale + block_minimum. Legacy quantization method (not used widely as of today). |
Q5_K |
GH |
5-bit quantization (q). Super-blocks with 8 blocks, each block has 32 weights. Weight formula: w = q * block_scale(6-bit) + block_min(6-bit), resulting in 5.5 bits-per-weight. |
Q4_0 |
GH |
4-bit round-to-nearest quantization (q). Each block has 32 weights. Weight formula: w = q * block_scale. Legacy quantization method (not used widely as of today). |
Q4_1 |
GH |
4-bit round-to-nearest quantization (q). Each block has 32 weights. Weight formula: w = q * block_scale + block_minimum. Legacy quantization method (not used widely as of today). |
Q4_K |
GH |
4-bit quantization (q). Super-blocks with 8 blocks, each block has 32 weights. Weight formula: w = q * block_scale(6-bit) + block_min(6-bit), resulting in 4.5 bits-per-weight. |
Q3_K |
GH |
3-bit quantization (q). Super-blocks with 16 blocks, each block has 16 weights. Weight formula: w = q * block_scale(6-bit), resulting. 3.4375 bits-per-weight. |
Q2_K |
GH |
2-bit quantization (q). Super-blocks with 16 blocks, each block has 16 weight. Weight formula: w = q * block_scale(4-bit) + block_min(4-bit), resulting in 2.625 bits-per-weight. |
IQ4_NL |
GH |
4-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix. |
IQ4_XS |
HF |
4-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix, resulting in 4.25 bits-per-weight. |
IQ3_S |
HF |
3-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix, resulting in 3.44 bits-per-weight. |
IQ3_XXS |
HF |
3-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix, resulting in 3.06 bits-per-weight. |
IQ2_XXS |
HF |
2-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix, resulting in 2.06 bits-per-weight. |
IQ2_S |
HF |
2-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix, resulting in 2.5 bits-per-weight. |
IQ2_XS |
HF |
2-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix, resulting in 2.31 bits-per-weight. |
IQ1_S |
HF |
1-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix, resulting in 1.56 bits-per-weight. |
IQ1_M |
GH |
1-bit quantization (q). Super-blocks with 256 weights. Weight w is obtained using super_block_scale & importance matrix, resulting in 1.75 bits-per-weight. |
Q4_K_M
Q4_K_M
是一种用于大型语言模型(LLM)的量化格式,特别是在 llama.cpp 项目及其派生项目中非常流行
- 4 位量化:
Q4
指的是模型权重被量化到 4 位整数
- 在保持一定精度的前提下,大幅减小模型大小和内存占用的常用选择
K-量化 (K-quantization)
的应用: K
指的是它使用了 llama.cpp 中的 K-量化方案
。
- 权重被分成小块进行量化,每个块都有自己的量化参数(如缩放因子和零点)
M
在 K-量化中通常表示一种中等平衡的量化配置
- 具体来说,Q4_K_M 和 Q4_K_S 都是 4 位 K-量化,但它们在量化块的大小、量化组的分布等方面可能有所不同,导致在模型大小和推理速度之间有不同的权衡
- 通常,Q4_K_M 会在性能和精度之间提供一个比较好的折衷
AWQ (Activation-aware Weight Quantization) 量化
AWQ 是一种权重感知量化 (Weight-Only Quantization) 方法,主要针对模型的权重进行量化,而通常保持激活在更高的精度(例如 FP16)。
主要特点:
- 激活感知 (Activation-aware): AWQ 的核心思想是,并非所有权重都对模型性能同等重要。它通过分析模型在少量校准数据上的激活值分布,识别出对模型输出影响最大的
显著权重
通道。
- 保护显著权重: 对于那些被认为是
显著
的权重,AWQ 会采用特殊的策略(如缩放)来保护它们,以最小化量化带来的精度损失。它通过对显著通道进行缩放,然后对所有权重进行量化,并在运行时对激活进行反向缩放,从而有效地减少量化误差。
- 主要关注内存压缩: 由于只量化权重,AWQ 在大幅减少模型内存占用方面表现出色,特别是对于将模型压缩到 4 位整数(INT4)时,可以使模型大小减小到原始的 1/4。这使得在资源受限的设备上部署大型模型成为可能。
- 对推理吞吐量的影响: 纯粹的权重感知量化(如 AWQ)主要改善了内存带宽,从而降低了首次生成时间(time to first token) 和 延迟。对于计算密集型的预填充(prefill) 阶段,如果激活仍然是高精度,提升可能不如权重+激活量化那么显著。然而,通过与一些高效的核函数(如 Marlin/Machete)结合,AWQ 也能显著提升解码速度。
- 适用性: AWQ 适用于各种模型架构和领域,因为它不依赖反向传播或复杂的重建过程,因此在不牺牲泛化能力的情况下,能很好地应用于指令微调模型和多模态模型。
FP8 (8-bit Floating Point) 量化
FP8 是一种新兴的权重+激活量化 (Weight + Activation Quantization) 方法,它将模型的权重和激活都量化到 8 位浮点格式。
主要特点:
- 浮点格式的优势: 浮点数相比于整数具有更高的动态范围,尤其是在处理具有大量异常值(outliers)的数据分布时。LLM 的激活通常存在长尾分布和异常值,FP8 的浮点特性使其在处理这些数据时比 INT8 更具鲁棒性,能够更好地保持模型精度。
- 全面加速: FP8 量化同时作用于权重和激活,这意味着模型的计算(如矩阵乘法)可以直接在 FP8 精度下进行。这不仅可以减少内存占用,还可以显著提高吞吐量和计算效率,尤其是在支持 FP8 计算的现代 GPU(如 NVIDIA Hopper 系列 H100 及更新的 GPU,AMD MI300x)上。
- 精度保持良好: 经验表明,FP8 量化通常能在保持与 FP16/BF16 模型非常接近的输出质量的同时,提供显著的性能提升。这使得 FP8 成为在不牺牲太多精度的前提下实现高效推理的理想选择。
- 对硬件的依赖: FP8 的性能优势高度依赖于支持 FP8 原生计算的硬件。旧的 GPU 架构可能无法充分利用 FP8 的潜力。
- 校准: FP8 量化可能需要进行校准,以确定合适的缩放因子,但也可以支持动态量化,即在运行时根据数据分布动态调整缩放。
AWQ vs FP8 对比总结
特性 |
AWQ (Activation-aware Weight Quantization) |
FP8 (8-bit Floating Point) |
量化对象 |
主要量化权重到低位整数(如 INT4),激活通常保持高精度(如 FP16)。 |
权重和激活都量化到 8 位浮点数。 |
精度格式 |
通常是INT4或其他低位整数。 |
FP8 (8 位浮点数)。 |
核心策略 |
通过分析激活值,保护模型中对性能影响大的显著权重,减少量化误差。 |
利用浮点数的高动态范围和对异常值的鲁棒性,同时量化权重和激活。 |
内存压缩 |
非常高,特别是 INT4 量化,可将模型大小减小到原模型的 1/4。 |
高,通常将模型大小减半(相对于 FP16/BF16)。 |
推理速度 |
主要提升内存带宽,降低延迟和首个 token 生成时间。通过优化的内核(如 dequantization-aware kernels)也能加速解码。 |
显著提升整体吞吐量和计算效率,尤其是在支持 FP8 的原生硬件上,因为计算可以直接在 FP8 进行。 |
精度损失 |
在极低位(如 INT4)下能较好地保持精度,因其激活感知的保护机制。 |
通常能非常接近 FP16/BF16 的精度,因为 FP8 对异常值更鲁棒且有更高的动态范围。 |
硬件依赖 |
可以在更广泛的 GPU上部署(包括 Ampere 及更早的架构),但一些性能优化需要特定库支持。 |
最佳性能依赖于支持FP8 原生计算的现代 GPU(如 NVIDIA Ada Lovelace, Hopper 及更新的架构)。 |
校准时间 |
通常需要校准数据,校准时间可能需要几分钟到十几分钟。 |
需要校准数据,校准时间通常在几分钟。也可以支持动态量化。 |
适用场景 |
对内存限制严格、且主要关注解码阶段延迟的场景(如长文本生成、聊天机器人)。 |
追求最高推理吞吐量、且在FP8 原生硬件上部署的场景(如大型输入处理、高并发服务)。 |
量化带来的挑战
精度损失
:低精度可能导致模型输出误差,尤其在极端值或敏感任务中
动态范围适配
:如何选择合适的缩放因子和零点,以最小化信息损失
硬件支持差异
:不同硬件对量化格式的支持可能不同(如是否支持int4
)
应用场景
移动端部署
:如手机 APP 中的图像分类、语音识别
边缘计算
:无人机、智能摄像头等设备的实时推理
大规模服务
:降低服务器计算成本,提升响应速度
工具支持
TensorFlow
:TensorFlow Lite
、TensorFlow Model Optimization Toolkit
PyTorch
:PyTorch Quantization
(支持 QAT 和 PTQ)
ONNX
:通过 ONNX Runtime 支持量化模型推理
总结
模型量化通过权衡精度与效率,让深度学习模型更轻量、更高效,是实际应用中不可或缺的优化手段。选择合适的量化策略(如 PTQ 或 QAT)需结合任务需求、硬件条件和精度容忍度综合考虑。