模型量化是一套通过降低模型数值精度来压缩模型、提升推理速度的核心技术体系。传统计算机视觉(CV)小模型与大语言模型(LLM)在量化上面临的挑战和适用方法有本质区别。
量化基础:从浮点到低比特的映射
量化的数学本质
量化的核心是寻找一个映射函数,将高精度、大范围的浮点数映射到数量有限的低精度离散值集合中。最常用的线性量化通过仿射变换实现:
- 量化公式: q = \\text{round}\\left(\\frac{r}{s}\\right) + z
- 反量化公式: r' = s \\times (q - z)
其中 s 是缩放因子(Scale), z 是零点(Zero Point),负责对齐浮点零点的位置,避免零值在量化时产生偏差,从而保证稀疏性或零点敏感计算的准确性。在对称量化中,零点通常固定为 0;在非对称量化中,零点根据输入数据的实际极值区间动态计算。
对称与非对称量化
| 类型 | 零点机制 | 适用场景 | 优缺点对比 |
|---|---|---|---|
| 对称量化 | 固定为 0 | 权重(通常呈零中心分布) | 计算效率高,无需存储零点偏移,但对非对称分布敏感。 |
| 非对称量化 | 可任意整数 | 激活值(可能存在偏斜分布) | 更精确匹配数据分布,减少截断误差,但计算引入零点减法,需额外存储零点。 |
在实际部署中,权重量化多采用对称方式,激活量化则根据数据分布灵活选择。现代硬件对权重的对称量化有极高的指令级支持,而激活值通常支持两种模式。
量化粒度
量化粒度决定了缩放因子和零点的共享范围,直接影响精度与显存开销:
- Per-Tensor(张量级):整个张量共享一组参数,实现最简单,但精度最低,通常仅适合动态范围稳定的激活值量化。
- Per-Channel(通道级):每个输出通道独立计算参数,精度显著提升,是目前主流权重量化的标准做法。
- Per-Group / Block(分组级):将通道划分为小组(典型 Group Size 为 64 或 128),每组独立量化,在精度和硬件并行效率间取得完美平衡,是 AWQ、GPTQ 等现代 LLM 量化算法的基础。
数据类型演进
BF16、FP8 和 NF4是大模型(LLM)与深度学习演进中最关键的三种"数值与量化格式"。各自代表不同的设计哲学:大动态范围(BF16)、高吞吐硬件加速(FP8)以及极限压缩与信息论最优(NF4)。
BF16 (Bfloat16 / 脑浮点数)
现代大模型(LLM)的默认训练与推理格式。训练与大动态范围的基石:
- 位宽 16 位(2 字节):1 位符号位 + 8 位指数位 + 7 位尾数位(Mantissa)。
- 对比 FP16:传统的标准半精度 FP16 采用 5 位指数位、10 位尾数位。BF16 牺牲了部分尾数精度,换取了与 FP32 完全相同的动态范围( \\approx 3.4 \\times 10\^{38} )。
核心优势与局限
- 免除溢出与对齐调整(Zero Loss of Range):在神经网络训练或大模型推理中,梯度和激活值的数值范围非常广。使用 FP16 时经常因为动态范围太小而发生"上溢(Overflow,变成 Inf)"或"下溢(Underflow,变成 0)",需要复杂的混合精度缩放(Loss Scaling)。BF16 的动态范围与 FP32 完全一致,几乎可以直接无缝替换 FP32。
- 尾数精度较低:尾数只有 7 位,其精确度略低于 FP16。但在深度学习中,神经网络对微小的尾数误差天然具有强大的鲁棒性,而对数值溢出则极其敏感。
FP8 (8-bit Floating Point)
高性能硬件加速的新标杆;云端大模型大规模工业级推理与训练(在保证几乎无损的情况下将显存减半、吞吐加倍)格式:
- 位宽 8 位(1 字节),是现代加速器(如 NVIDIA Hopper H100、Blackwell 架构)原生硬件支持的超低精度浮点格式。两大主流子格式:
- E4M3(4 位指数位,3 位尾数位):动态范围较小,但精度(尾数)稍高,更适合用于激活值(Activation)和权重(Weight)的前向计算。
- E5M2(5 位指数位,2 位尾数位):动态范围更大,更适合用于数值波动剧烈的梯度(Gradient)计算。
核心优势与局限
- 真正的硬件原生浮点加速:NVIDIA 的 Tensor Core 能够直接对 FP8 矩阵进行乘加运算,且无需频繁反量化,推理吞吐量比 FP16 提升高达约 2 倍以上。
- 兼顾动态范围与低带宽:相比 INT8,FP8 引入了指数位,能够更好地应对神经网络中常见的异常值(Outliers),精度损失通常控制在 1% 以内。
- 生态依赖性强:需要较新的硬件架构支持(如 H100/H200 或 RTX 40 系以后的部分新特性,以及更新的 Blackwell),老旧显卡(如 Ampere 架构的 RTX 30 系列)无法获得硬件级的 FP8 加速。
NF4 (Normalized Float 4)
极限压缩与信息论最优的 4 位格式;消费级显卡(单卡)运行或微调超大模型格式:
- 位宽 4 位(仅占 0.5 字节),非均匀量化与分位数对齐;
- 经过预训练的 Transformer 权重往往呈现出严格的零中心高斯分布(正态分布)------绝大部分数值死死地挤在 0 附近,极少数数值分布在两端。
- 传统的 4 位整数(INT4)采用均匀量化,即把一个数值区间等距离切成 16 份。0 附近的密集区域会被塞进极少几个量化格子里,造成巨大的信息丢失。
- NF4基于信息论,将 4 位的 16 个量化水平(Level)精确放置在标准正态分布的高斯分位数(Quantiles)上。数据密度最高的地方(0 附近),分得的量化格网最密集;边缘稀疏的地方分得的格网最稀疏。
核心优势与局限
- 信息论意义上的绝对最优(Quantile Quantization):在数学证明上,对高斯分布的权重而言,NF4 在 4 位比特限制下实现了信息论最优的重构误差(MSE 最低)。相比普通 INT4,它能多保留约 0.3~0.5 的困惑度(Perplexity)优势。
- 专为权重(Weights)设计:NF4 主要用于冻结基底模型的权重量化(配合双精度量化 Double Quantization 进一步压缩 Scale 开销),使得 70B 的大模型可以被塞进单张消费级显卡(如 RTX 4090)中进行 QLoRA 微调。
- 不适合激活值(Activations):由于激活值不具备稳定的高斯分布且包含大量异常值,NF4 无法直接用于激活量化。
核心维度对比
| 维度 | BF16 (Bfloat16) | FP8 (E4M3 / E5M2) | NF4 (NormalFloat 4) |
|---|---|---|---|
| 本质属性 | 高动态范围浮点数 | 高性能低比特浮点数 | 信息论最优的正态分布 4 位量化 |
| 位宽 (Bits) | 16-bit (2 字节) | 8-bit (1 字节) | 4-bit (0.5 字节) |
| 数值分布策略 | 等间隔浮点指数/尾数 | 小动态范围紧凑浮点 | 非均匀分位数(高斯分布适配) |
| 主要优化目标 | 防止训练溢出、替代 FP32 | 硬件原生加速、兼顾带宽与吞吐 | 极限压缩模型体积、支持单卡微调 |
| 精度损失 | 几乎无损 (0) | 极低 (< 1%) | 极低(在 4 位里理论最优) |
| 硬件依赖 | 现代 GPU/TPU 普遍支持 | Hopper/Blackwell 及更新架构 | 纯软件层面实现(如 bitsandbytes 库) |
| 典型生态 | 预训练、全精度推理 | 云端高并发工业推理 | 端侧运行、QLoRA 低成本微调 |
后训练量化(Post-Training Quantization, PTQ)
后训练量化(Post-Training Quantization, PTQ)是目前工业界应用最广泛的量化手段。在模型完成预训练之后,直接对权重和激活值进行低比特转换,无需重新训练(Retraining)或反向传播。相比于需要重新训练的 QAT,PTQ 极大地节省了算力和时间。
PTQ 的具体量化与映射全流程:
- 步骤 1:准备校准数据集(Calibration Dataset)
- 准备一小批具有代表性的真实数据(校准集:通常是 100 到 500 个样本,如 CV 任务中的几百张典型图像,或者 LLM 任务中的几百段典型文本);用于"观察"模型在实际运行时的行为(模拟模型在真实生产环境中的输入流)。
- 步骤 2:运行前向推理与激活值统计(Activation Profiling)
- 将校准数据集输入到全精度的浮点模型(如 FP32/BF16)中,进行一次或多次前向传播(Forward Pass)。
- 收集指标:在模型运行的过程中,通过挂载钩子(Hooks)实时监控并记录下每一层网络中激活值(Activation)的数值分布、最大值、最小值,以及权重(Weight)原有的分布情况。
- 步骤 3:计算量化参数(Scale & Zero-Point 的确定)。有了激活值和权重的极值范围后,就可以为每一层(或每一个 Channel)计算最优的缩放因子 s (Scale)和零点 z (Zero Point):
- 权重的量化参数:由于权重在训练完成后是固定死的,直接扫描整个权重的张量即可计算出固定的 s 和 z 。
- 激活值的量化参数统计策略:激活值随输入而变,因此需要通过校准数据统计出其极值。常用的统计策略包括:
- Min-Max(极值法):直接取校准过程中激活值的绝对最大值和最小值。缺点是对极端异常值(Outliers)非常敏感。
- Percentile(百分位数法):例如去掉极端的 0.1% 噪点,取 99.9% 分位数作为边界,防止个别异常值拉大整体 Scale。
- KL 散度(Kullback-Leibler Divergence / 相对熵):通过计算量化前后的概率分布差异,寻找一个最优的截断阈值,使得信息损失最小(常用于 TensorRT 的 INT8 校准)。
- 步骤 4:执行量化与映射(Quantization & Mapping)。确定好 s 和 z 之后,PTQ 引擎会对模型进行离散化转换:
- 权重量化:将高精度的浮点权重通过公式 q = \\text{round}\\left(\\frac{w}{s}\\right) + z 永久转换为低比特整数(如 INT8),并固化保存。
- 激活量化处理方式的抉择:
- 静态量化(Static Quantization):在校准阶段就把激活值的 Scale 固定下来。推理时直接用固定的 Scale。速度快,但如果遇到未见过的极端输入可能会有精度损失。
- 动态量化(Dynamic Quantization):权重提前量化为整数,而激活值在每次推理时动态计算当前 Batch 的 Scale。这种方法不需要校准集,对 LLM 和 Transformer 结构特别友好(例如 PyTorch 的动态 INT8 线性层)。
- 步骤 5:导出与部署
- 将量化后的权重、固定的缩放因子以及计算图打包,导出为标准的推理格式(如 ONNX、TensorRT 引擎、GGUF 等),交由推理引擎执行硬件加速。
量化感知训练(Quantization-Aware Training, QAT)
在深度学习中,量化感知训练(Quantization-Aware Training, QAT)的核心思想是在模型训练(或微调)的闭环中,人为地给模型制造"量化噪声",让模型学会在面对低精度截断时如何自我修正和适应。
伪量化(Fake Quantization)的三步循环:在 QAT 的前向传播中,每当数据(权重或激活值)流经某一层时,都会被插入一个"伪量化算子"(数学上模拟了量化与反量化的全过程):
- 截断与动态范围计算(Clamp / Truncate)
- 算子会实时统计当前输入张量的极值范围(例如边界 \[\\alpha, \\beta\] )。
- 超出该范围的数值会被强制截断(Clamp),模拟低比特下溢或上溢的效果。
- 量化与四舍五入(Quantize & Round)
- 结合当前的缩放因子 s (Scale)和零点 z (Zero Point),将浮点数映射到离散的整数区间:
q = \\text{round}\\left(\\frac{x}{s}\\right) + z
- 引入了 `round()`(四舍五入)操作,切断了原本连续平滑的数值,带来量化误差(噪声)。
- 立即反量化(Dequantize)
- 为后续的高精度计算能够继续进行,伪量化算子会紧接着将刚刚四舍五入后的离散整数重新反量化回浮点数:
x' = s \\times (q - z)
- 为什么要做反量化? 因为 PyTorch 等框架的神经网络底座(如矩阵乘法、求导)都是基于浮点数设计的。通过"量化 $ \rightarrow $ 取整 $ \rightarrow $ 再反量化",数据在数值形态上已经带有了低比特量化的噪声,但在数据类型和内存格式上依然保持浮点数,从而能够顺利完成后续的前向传播。
- 导出真实量化模型
- 训练结束时,模型会剥离掉伪量化算子中的"反量化"步骤。
- 固化下每个通道的缩放因子 s 、零点 z ,并将浮点权重正式转换为真正的 INT8 或 INT4 整数,打包输出给推理引擎(如 TensorRT、ONNX Runtime)进行高效部署。
直通估计器(STE)
- 四舍五入函数(
round())的导数在几乎所有地方都等于 0,在断点处不可导。如果直接对带有round()的计算图求导,梯度会直接归零(梯度消失),模型根本无法通过反向传播更新权重。 - 为此,QAT 引入了直通估计器(Straight-Through Estimator, STE):
- 前向传播中:严格执行带有
round()的四舍五入截断,制造真实的量化噪声。 - 反向传播(求导)中:人为"忽略"
round()操作,把伪量化算子的导数直接设为恒等函数(即 \\frac{\\partial y}{\\partial x} = 1 )。 - 梯度可以毫无阻碍地穿过伪量化算子,直接传导给前层的权重。
- 前向传播中:严格执行带有
CV vs LLM:量化差异的本质
CV 小模型与 LLM 大模型,两者的参数规模、激活分布和量化敏感性存在根本差异:
| 特性维度 | CNN(传统 CV) | ViT(视觉 Transformer) | LLM(大语言模型) |
|---|---|---|---|
| 参数规模 | 10M - 100M | 10M - 1B | 1B - 1000B+ |
| 主要敏感层 | 首层/尾层卷积 | LayerNorm 后 / Attention Q,K | Attention、LayerNorm、异常值主导通道 |
| 激活分布特点 | 近似高斯分布 / ReLU 截断 | 后 GELU 长尾、通道间变异明显 | 强长尾与持续异常值并存 |
| 权重量化难度 | 中等 | 中等 | 较低(权重分布相对均匀) |
| 激活量化难度 | 低 - 中等 | 高(后 LayerNorm 波动大) | 极高(异常值主导动态范围) |
| 典型算法支持 | BRECQ、QDrop | FIMA-Q、NoisyQuant | GPTQ、SmoothQuant、AWQ |
| 推荐安全位宽 | W4A4 / W8A8 | W4A4 / W4A8 | W4A16 / W8A8 (SmoothQuant) |
| 硬件部署重点 | 算力加速、FPS 提升 | 混合精度计算优化 | 显存带宽瓶颈、KV 缓存压缩 |
激活分布:从"温和"到"极端"
传统 CNN 的激活值经 ReLU 截断后近似高斯分布,动态范围可控,INT8 量化通常 1% 以内的精度损失。而 LLM 的激活值呈现"强长尾与持续异常值(Outliers)"的特征(Transformer 中少数通道的激活幅度比正常值大 100~300 倍)。这些离群值会拉大整体 Scale,导致正常数值被压缩到极小的表示空间中造成精度崩塌。
- 解决方案:如
LLM.int8()采用混合精度策略,将普通值采用 INT8 计算,异常值保留在 FP16 中处理。
现代 LLM 核心量化算法
- GPTQ (Generalized Post-Training Quantization):利用二阶泰勒展开与 Hessian 矩阵逆,通过逐层量化误差补偿机制( \\mathbf{W}_{\\text{quant}} = \\mathbf{W} - \\Delta \\mathbf{W} ),在不重新训练的前提下极大地修正了量化带来的权重偏置。
- AWQ (Activation-aware Weight Quantization):基于激活值分布识别对模型输出影响最大的"关键权重"(通常占 1% 左右),为其引入平滑缩放因子 s ,在保持高精度的同时对其余权重进行激进量化。
- SmoothQuant:通过数学等价线性变换,将激活侧的量化难度平滑迁移到权重侧,成功实现了大模型的 W8A8 权重-激活同时量化。
KV Cache 量化:LLM 独有的内存优化对象
传统 CV 模型属于单次前向推理,无历史缓存需求。而 LLM 在自回归生成时需要维护 KV Cache(已生成 Token 的注意力键值缓存),它随上下文长度和并发数线性增长。在长文本推理中,KV Cache 往往占用大量显存。
- 量化方案:通过 KIVI、KVQuant 等技术将 KV Cache 压缩至 INT4/INT8,可将显存占用降低 2.6 至 6.4 倍,是端侧运行长文本 LLM 的必备技术。
硬件部署的核心瓶颈差异
- CV 模型聚焦于算力加速------利用 Tensor Core 的整数运算指令提升每秒帧数(FPS)。
- LLM 模型聚焦于显存带宽瓶颈------LLM 解码阶段受限于内存带宽,量化不仅节省了权重显存,还显著压缩了 KV Cache 的显存占用,使系统的吞吐量和并发能力双重提升。
总结
模型量化的技术选型需要同时考虑模型类型、算法复杂度和目标硬件:
- CV 小模型可采用激进量化(如 W4A4),通过 INT8 PTQ 部署于 NPU 或 CPU 上,追求极致的实时性。
- 大语言模型(1B ~ 7B)在端侧部署时,应优先采用 W4A16(如 AWQ、GGUF 格式)以突破显存带宽限制,并配合 GPU/NPU 协同调度。
- 超大模型(70B+)则依赖集群化的高性能推理框架(如 TensorRT-LLM)结合 FP8/INT8 混合精度进行部署。
量化的艺术在于平衡压缩率与智能水平:Q8 接近无损,Q4 是消费级部署的黄金甜点,而过度量化(如极低比特 Q2/Q3)会导致明显的性能退化。